F# 的語法與基本特性
阿新 • • 發佈:2020-12-09
本文只是筆記/摘錄,沒有解釋說明,因為原文有些句子太精彩了,忍不住要記下來。
原文:
https://fsharpforfunandprofit.com/posts/expressions-vs-statements/
https://fsharpforfunandprofit.com/series/understanding-fsharp-types.html
下面是摘錄:
- In F# everything is an expression.
- Using expressions consistently leads to code that is both safer and more compact.
- In fact, it is not even helpful to think of “control flow” in a functional language; the concept doesn’t really exist.
- Better to just think of the program as a giant expression containing sub-expressions.
- If you need to work with a disposable “outside” the function that created it, probably the best way is to use a callback.
- One trick in F# is to appropriate the use keyword to do any kind of “stop” or “revert” functionality automatically.
- It is considered a good practice to always have an explicit “do”, as it acts as documentation that you do not want a result.
- The best way to avoid
if-then-else
is to use “match” instead. - The best way to avoid loops is to use the built in list and sequence functions instead.
- There is no equivalent of “break” and “continue” (this can generally done better using sequences anyway).
- In the functional world, returning error codes (or rather error types) is generally preferred to throwing exceptions.
- The
match..with
should be on a new line. - If you can’t have every case be explicit, you might try to document your boundary conditions as much as possible, and assert an runtime error for the wildcard case.
- You can match on subtypes, using the
:?
operator - Partial active patterns have a return value that is an option type. (MSDN)
- To be as specific as possible when defining the domain, typically by creating lots of very specific types.
- Complicated logic is often a sign that you don’t quite understand the domain properly.
- A well designed object-oriented program will have a strong focus on behavior rather than data. A well designed functional program, on the other hand, will have a strong focus on data types rather than behavior.
- Tuples are perfect for small, temporary, lightweight structures.
- If you just need a single property, you can use dot notation rather than pattern matching. (Records)
- Note that in F#, unlike some other functional languages, two types with exactly the same structural definition are not the same type.
- The case constructors for union types are normal functions, so you can use them anywhere a function is expected.
- A convenient thing about single case union types is you can pattern match directly against a value without having to use a full
match-with
expression. - The option type has functions such as
IsSome
,IsNone
andValue
, don’t use them! Instead use theOption
module and thedefaultArg
function. - It is good practice to immediately check for nulls and convert them into an option type!
- You can convert a primitive type to an object directly, by using the
box
keyword. - To convert an object back to an primitive type, use the
unbox
keyword.
The common naming conventions are as follows:
- “a”, “b”, “c” etc., are types
- “f”, “g”, “h” etc., are functions
- “x”, “y”, “z” etc., are arguments to the functions
- Lists are indicated by adding an “s” suffix, so that “xs” is a list of x’s, “fs” is a list of functions, and so on.
Formatted text using printf
https://fsharpforfunandprofit.com/posts/printf/
- %s for strings
- %b for bools
- %i for ints
- %f for floats
- %A for pretty-printing tuples, records and union types
- %O for other objects, using ToString()