I think most of your comments are related to the fact that the names of the entries become available in the namespace where the entry is defined, that is, when you define the Person entry with the Name and Id properties, the Name and Id names are displayed globally. This has both advantages and disadvantages:
- Itβs good that it simplifies programming, because you can simply write
{Id=1; Name="bob"} {Id=1; Name="bob"} - The bad news is that names can interfere with other record names that are in scope, and therefore, if your names are not unique (your first example), you get into trouble.
You can tell the compiler that you should always explicitly specify a name using the RequireQualifiedAccess attribute. This means that you will not be able to write only Id or Name , but you should always specify a type name:
[<RequireQualifiedAccess>] type AnotherPerson = {Id: int; Name: string} [<RequireQualifiedAccess>] type Person = {Id: int; Name: string;}
This gives you a more strict mode, but makes programming less convenient. By default (a bit more ambiguous behavior) @pad is already explained - the compiler will just pick the name defined later in your source. He does this even if he can infer the type by looking at other fields in the expression - simply because searching for other fields will not always work (for example, when you use the with keyword), so itβs better to stick to a simple consistent strategy.
Regarding pattern matching, I was very confused when I first saw the syntax. I think it is not used very often, but it can be useful.
It is important to understand that F # does not use structural typing (this means that you cannot use a record with a large number of fields as an argument to a function that takes a record with fewer fields). This may be a useful feature, but it is not suitable for a system like .NET. This basically means that you cannot expect too bizarre things - the argument should be a record of a known type of record.
When you write:
let {Id = id; Name = name} = p
The term lvalue refers to the fact that Id and Name appear in the template, and not in the expression. The syntax definition in F # tells you the following:
expr := let <pat> = <expr> | { id = <expr>; ... } | <lots of other expressions> pat := id | { id = <pat>; ... } | <lots of other patterns>
So, the left side of = in let is a template, and the right side is an expression. Two similar structures in F # - (x, y) can be used both for constructing and for deconstructing a tuple. And the same goes for records ...
Tomas petricek
source share