Here are the full release notes for F# 1.9.2.7.
The following syntax forms
expr := ... | e1.[range1] | e1.[range1,range2] range := e2..e3 | ..e3 | e2.. | *
expr := ...
| e1.[range1]
| e1.[range1,range2]
range := e2..e3
| ..e3
| e2..
| *
represent slicing from a 1D or 2D data structures that supports associative lookup on ordered keys. In practice these forms can be used with
For example:
let s1 = "abcdef" s1.[*] = s1 s1.[0..] = s1 s1.[1..] = "bcdef" s1.[2..] = "cdef" s1.[5..] = "f" s1.[6..] = "" let m1 = matrix [ [ 1.0; 2.0; 3.0; 4.0; 5.0; 6.0 ]; [ 10.0;20.0;30.0;40.0;50.0;60.0 ] ] m1.[*,*] = m1 m1.[0..,*] = matrix [ [ 1.0; 2.0; 3.0; 4.0; 5.0; 6.0 ]; [ 10.0;20.0;30.0;40.0;50.0;60.0 ] ] m1.[1..,*] = matrix [ [ 10.0;20.0;30.0;40.0;50.0;60.0 ] ] m1.[*,1..] = matrix [ [ 2.0; 3.0; 4.0; 5.0; 6.0 ]; [ 20.0;30.0;40.0;50.0;60.0 ] ]) The primary restriction is that the syntax can't yet be used to extract a vector from a matrix, e.g.
let s1 = "abcdef"
s1.[*] = s1
s1.[0..] = s1
s1.[1..] = "bcdef"
s1.[2..] = "cdef"
s1.[5..] = "f"
s1.[6..] = ""
let m1 = matrix [ [ 1.0; 2.0; 3.0; 4.0; 5.0; 6.0 ];
[ 10.0;20.0;30.0;40.0;50.0;60.0 ] ]
m1.[*,*] = m1
m1.[0..,*] = matrix [ [ 1.0; 2.0; 3.0; 4.0; 5.0; 6.0 ];
m1.[1..,*] = matrix [ [ 10.0;20.0;30.0;40.0;50.0;60.0 ] ]
m1.[*,1..] = matrix [ [ 2.0; 3.0; 4.0; 5.0; 6.0 ];
[ 20.0;30.0;40.0;50.0;60.0 ] ])
m1.[1,*] m1.[*,1] are not yet valid syntactic forms. These would have to map to different operators.
m1.[1,*]
m1.[*,1]
Technically speaking, the above represent calls to the Microsoft.FSharp.Core.Operators operators
val (.[..]) : ^src -> 'idx option -> 'idx option -> ^res val (.[..,..]) : ^src -> 'idx1 option -> 'idx1 option -> 'idx2 option -> 'idx2 option -> ^res i.e.
val (.[..]) : ^src -> 'idx option -> 'idx option -> ^res
val (.[..,..]) : ^src -> 'idx1 option -> 'idx1 option -> 'idx2 option -> 'idx2 option -> ^res
e1.[e2..e3] == (.[..]) e1 (Some e2) (Some e3) e1.[e2..] == (.[..]) e1 (Some e2) None e1.[..e3] == (.[..]) e1 None (Some e3)
e1.[e2..e3] == (.[..]) e1 (Some e2) (Some e3)
e1.[e2..] == (.[..]) e1 (Some e2) None
e1.[..e3] == (.[..]) e1 None (Some e3)
The implementation of (.[..]) requires:
member GetSlice : 'idx option * 'idx option -> 'res
An Item property on the return type of the GetSlice function:
member Item : 'idx -> 'elem with get
Similar conditions are used for the 2D lookup operator.
Calls to members (but not let-bound functions or function values) may use named arguments. For example
System.Console.WriteLine(format="Hello {0}",arg0="World")
System.Console.WriteLine("Hello {0}",arg0="World")
System.Console.WriteLine(arg0="World",format="Hello {0}")
Named arguments may not be used with the curried arguments of a member (only the initial set of "tupled" arguments).
Named arguments must appear after all other arguments, so the following is not allowed:
System.Console.WriteLine(arg0="World","Hello {0}")
The names of members may be listed in signature types and on the types used for abstract members, e.g.
static member ThreeArgs : arg1:int * arg2:int * arg3:int -> int abstract TwoArgs : arg1:int * arg2:int -> int
static member ThreeArgs : arg1:int * arg2:int * arg3:int -> int
abstract TwoArgs : arg1:int * arg2:int -> int
Members (but not let-bound functions) may have optional arguments. These must come at the end of the argument list, though this is not currently checked. An optional argument is marked with a ? before its name. Inside the member the argument has type option<argType>. On the callside the argument typically appears to have type argType, though there is a way to pass a value of type option<argType> if necessary (see below).
let defaultArg x y = match x with None -> y | Some v -> v type T() = static member OneNormalTwoOptional (arg1, ?arg2, ?arg3) = let arg2 = defaultArg arg2 3 let arg3 = defaultArg arg3 10 arg1 + arg2 + arg3 static member TwoOptional (?arg1, ?arg2) = let arg1 = defaultArg arg1 3 let arg2 = defaultArg arg2 10 arg1 + arg2
let defaultArg x y = match x with None -> y | Some v -> v
type T() =
static member OneNormalTwoOptional (arg1, ?arg2, ?arg3) =
let arg2 = defaultArg arg2 3
let arg3 = defaultArg arg3 10
arg1 + arg2 + arg3
static member TwoOptional (?arg1, ?arg2) =
let arg1 = defaultArg arg1 3
let arg2 = defaultArg arg2 10
arg1 + arg2
In a signature optional arguments appear as follows:
static member OneNormalTwoOptional : arg1:int * ?arg2:int * ?arg3:int -> int static member TwoOptional : ?arg1:int * ?arg2:int -> int
static member OneNormalTwoOptional : arg1:int * ?arg2:int * ?arg3:int -> int
static member TwoOptional : ?arg1:int * ?arg2:int -> int
Callers may specify optional arguments either:
T.OneNormalTwoOptional(3)
T.OneNormalTwoOptional(3,2)
T.OneNormalTwoOptional(arg1=3)
T.OneNormalTwoOptional(arg1=3,arg2=1)
T.OneNormalTwoOptional(arg2=3,arg1=0)
T.OneNormalTwoOptional(arg2=3,arg1=0,arg3=11)
T.OneNormalTwoOptional(0,3,11)
T.OneNormalTwoOptional(0,3,arg3=11)
T.OneNormalTwoOptional(arg1=3,?arg2=Some(1))
T.OneNormalTwoOptional(?arg2=Some(3),arg1=0,arg3=11)
T.OneNormalTwoOptional(0,3,?arg3=Some(11))
Optional arguments can't be used in member constraints. They can be used in interface and abstract members. The compiled representation of optional arguments is fragile, in the sense that the addition of further optional arguments to a member signature will result in a compiled form that is not binary compatible with the previous compiled form.
Recall that F# automatically implements comparison and hash semantics for tuple, record and discriminated union types (only). Now F# will also implement Object.GetHashCode and Object.Equals for these types. For example:
> let x = box (1,2);;
val x : obj
> x.GetHashCode();;
val it : int = 5
> let x2 = box (1,2);;
val x2 : obj
> x2.GetHashCode();;
> x2.Equals(x);;
val it : bool = true
Other Language enhancements
Library additions
Library minor changes
Bugs fixed:
About 8 days ago I gave a presentation at the Microsoft Faculty Summit , rounding off a major trip to
Don Syme's WebLog on F# and Other Research Projects mentions F# 1.9.2.7 released! . The quick summary.
Though I managed to sneak away for some vacation time this week, it's clearly been a busy time for the