-
Notifications
You must be signed in to change notification settings - Fork 5.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
F# 4.1 Updates #1916
F# 4.1 Updates #1916
Conversation
@@ -73,6 +73,52 @@ You can also use global to reference the top-level .NET namespace, for example, | |||
|
|||
[!code-fsharp[Main](../../../samples/snippets/fsharp/lang-ref-2/snippet6408.fs)] | |||
|
|||
## | |||
|
|||
F# 4.1 introduces the notion of namespaces which allow for all underlying code to be mutually recursive. This is done via `namespace rec`. Use of `module rec` can alleviate some pains in not being able to write mutually referential code between types and modules. The following is an example of this: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo:
This is done via namespace rec
. Use of module rec
...
should be:
This is done via namespace rec
. Use of namespace rec
...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks!
@dsyme I would love a look at these. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Absolutely fantastic to have this added, this is wonderful!
|
||
[Attributes](attributes.md) | ||
|
||
[Named Arguments](parameters-and-arguments.md#named-arguments) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just wondering - do we have some kind of link checker for #named-arguments
and other hash-labels?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We do, but it's only in our CI. No way to test it locally.
Discriminated unions provide support for values that can be one of a number of named cases, possibly each with different values and types. Discriminated unions are useful for heterogeneous data; data that can have special cases, including valid and error cases; data that varies in type from one instance to another; and as an alternative for small object hierarchies. In addition, recursive discriminated unions are used to represent tree data structures. | ||
|
||
## Syntax | ||
|
||
```fsharp | ||
[ struct-attribute ] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should really add requirequalifiedaccess-attribute
here too since it is an attribute that has linguistic effect
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also no-equality-attribute
, no-comparison-attribute
and friends
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added as a new section below, "Common attributes"
| Case3 of double | ||
``` | ||
|
||
>[!WARN] With the current release of F# 4.1, multicase struct unions have multiple bugs. We do not recommend using them at this time. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this warning is a little too strong - in F# 4.1 they work well enough as long as each case has a separate type. However it is important to say that the overall size of the struct in F# 4.1 is the sum(field-sizes)
not max(field-sizes)
which may be very different to what people expect.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Made it less severe.
|
||
>[!WARN] With the current release of F# 4.1, multicase struct unions have multiple bugs. We do not recommend using them at this time. | ||
|
||
Because these are value types and not reference types, there are extra considerations compared with reference Discriminated Unions: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't capitalize Discriminated Unions
here?
## Syntax | ||
|
||
```fsharp | ||
use ptr = fixed expression |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's worth being clearer that this extends the syntax of expressions (not the syntax of other let
declarations such as declarations in class types)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I addressed this now:
This extends the syntax of expressions to allow extracting a pointer and binding it to a name which is prevented from being collected or moved during garbage-collection.
A pointer from an expression is fixed via the [...]
[...]
Use offixed
must occur within an expression in a function or a method. It cannot be used at a script-level or module-level scope.
X : float | ||
Y: float | ||
Z: float; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No semicolon needed here
(a + 1, b + 1) | ||
|
||
// Struct Tuple of floats | ||
struct(1.025f, 1.5f) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Space after struct
let (a, b) = (1, 2) | ||
|
||
// Construct a struct tuple from it | ||
let struct(c, d) = struct(a, b) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Space after struct
let struct(c, d) = struct(a, b) | ||
|
||
// | ||
// Fst and Snd functions |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// Fst and Snd functions (reference tuples only)
let (a, b) = struct(1, 2) | ||
|
||
// Will not compile! | ||
let struct(c, d) = (1, 2) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Space after struct
, likewise below
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Approving since I think all the feedback has been actioned
@BillWagner, would really love a once-over from you as well, particularly to see if my choice of presentation makes sense. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A few quick edit comments
@@ -0,0 +1,84 @@ | |||
--- |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this needs to be added to the TOC
@@ -0,0 +1,84 @@ | |||
--- | |||
title: Caller Information (F#) | |||
description: Caller Information (F#) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
description needs to be different than title
ms.assetid: a3dcc335-433b-4672-ac2d-ae6b11b816f3 | ||
--- | ||
|
||
# Caller Information |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: sentence case for headings
|
||
## Member Names | ||
|
||
You can use the `CallerMemberName` attribute to avoid specifying the member name as a `String` argument to the called method. By using this technique, you avoid the problem that Rename Refactoring doesn't change the `String` values. This benefit is especially useful for the following tasks: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
link to the APIs? if you want to use a different name than the default class name, you can link like this:
CallerMemberName
``` | ||
|
||
>[!WARN] | ||
With the initial release of F# 4.1, multicase struct unions have isues if the cases are of the same type. This has since been fixed and is pending an update. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
typo: isues
wrong note formatting. it should be WARNING not WARN and next line also starts with >
@@ -116,5 +137,14 @@ Discriminated unions work well if the nodes in the tree are heterogeneous. In th | |||
|
|||
When this code is executed, the value of `result` is 5. | |||
|
|||
## Common Attributes | |||
|
|||
The following attributes are commonly seen in Discriminated Unions: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lowercase discriminated unions?
## See Also | ||
[F# Language Reference](index.md) | ||
|
||
[Namespaces](namespaces.md) | ||
|
||
[F# RFC FS-1009 - Allow mutually referential types and modules over larger scopes within files](https://github.com/fsharp/fslang-design/blob/master/FSharp-4.1/FS-1009-mutually-referential-types-and-modules-single-scope.md) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we're now standardizing in no lines in between the links in the see also section
see here for an example: https://github.com/dotnet/docs/blob/master/docs/framework/interop/compiling-an-interop-project.md (you add a space in front and 2/3 in the end)
|
||
### Converting between Reference Tuples and Struct Tuples | ||
|
||
Because Reference Tuples and Struct Tuples have a completely different underlying representation, they are not implicitly convertable. That is, code such as the following will not compile: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
convertable -> convertible
will not -> won't
|
||
Tuples are compiled into objects of one of several generic types, all named `System.Tuple`, that are overloaded on the arity, or number of type parameters. Tuple types appear in this form when you view them from another language, such as C# or Visual Basic, or when you are using a tool that is not aware of F# constructs. The `Tuple` types were introduced in .NET Framework 4. If you are targeting an earlier version of the .NET Framework, the compiler uses versions of [System.Tuple](https://msdn.microsoft.com/library/5ac7953d-acdc-4a58-bfb7-c1f6406c0fa3) from the 2.0 version of the F# Core Library. The types in this library are used only for applications that target the 2.0, 3.0, and 3.5 versions of the .NET Framework. Type forwarding is used to ensure binary compatibility between .NET Framework 2.0 and .NET Framework 4 F# components. | ||
|
||
### Compiled Form of Struct Tuples | ||
|
||
Struct tuples (e.g., `struct (x, y)`), are fundamentally different from reference tuples. They are compiled into the `System.ValueTuple` type, overloaded by arity, or the number of type parameters. They are equivalent to [C# 7 Tuples](../../csharp/tuples.md) and VB.NET 15 Tuples, and interoperate bidirectionally. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
e.g. -> for example
@@ -0,0 +1,22 @@ | |||
// | |||
// Will not compile! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
will not -> It won't
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
GitHub didn't track this for some reason, but I addressed this
If you are only using tuples from F# and not exposing them to other languages, and if you are not targeting a version of the .NET Framework that preceded version 4, you can ignore this section. | ||
## Interoperation with C# Tuples | ||
|
||
C# 7 and VB.NET 15 introduced tuples to their respective languages. Tuples in C# and are structs, and are equivalent to struct tuples in F#. If you need to interoperate with C# uses tuples, you must use struct tuples. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
VB.NET 15 -> Visual Basic 2017?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall, this looks great.
I left a couple suggestions on wording that make one explanation more clear.
|
||
You must specify an explicit default value for each optional parameter. You can't apply Caller Info attributes to parameters that aren't specified as optional. | ||
|
||
The Caller Info attributes don't make a parameter optional. Instead, they affect the default value that's passed in when the argument is omitted. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These two paragraphs are somewhat hard to parse. How about this change:
Caller Info attributes can only be applied to optional parameters. You must supply an explicit value for each optional parameter. The Caller Info attributes cause the compiler to write the proper value for each optional parameter decorated with a Caller Info attribute.
Update if I have any of the technical details wrong for the F# implementation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
|Method, property, or event|The name of the method, property, or event from which the call originated.| | ||
|Constructor|The string ".ctor"| | ||
|Static constructor|The string ".cctor"| | ||
|Destructor|The string "Finalize"| |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it Finalize, or Finalizer?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Finalize. At least, this is what's in the equivalent C# doc.
```fsharp | ||
let deadBeef = 0xDEAD_BEEF | ||
|
||
let deadBeefAsBits = 0b1101_1110_1010_1101_1011_1110_1010_1111 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The 2nd to last nibble should be 1110
, not 1010
.
|
||
let deadBeefAsBits = 0b1101_1110_1010_1101_1011_1110_1010_1111 | ||
|
||
let ssn = 012_345_6789 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does F# assign a special meaning when the first digit of a numeric literal is 0? If not, you may want to change the value used in this example.
@@ -96,6 +100,18 @@ The following example illustrates a derived class that overrides a base class me | |||
## Overloaded Methods | |||
Overloaded methods are methods that have identical names in a given type but that have different arguments. In F#, optional arguments are usually used instead of overloaded methods. However, overloaded methods are permitted in the language, provided that the arguments are in tuple form, not curried form. | |||
|
|||
## Optional Arguments | |||
|
|||
Starting with F# 4.1, you can also have C#-style optional arguments with a default parameter value in methods. This is to help facilitate interoperation with C# code. The following example demonstrates the syntax: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd leave off the comparison to C#. Other languages (notably C++, and Scala) also support optional arguments.
### Compiled Form of Struct Tuples | ||
|
||
Struct tuples (for example, `struct (x, y)`), are fundamentally different from reference tuples. They are compiled into the `System.ValueTuple` type, overloaded by arity, or the number of type parameters. They are equivalent to [C# 7 Tuples](../../csharp/tuples.md) and VB.NET 15 Tuples, and interoperate bidirectionally. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should System.ValueTuple
be a reference to the type in the API docs?
Adds F# 4.1 feature to the docs. #1677 tracks what is added.