F# under the covers V
Doing some more detail work looking at patterns to be statically analysed, it's inevitable that you'll unearth some interesting behaviours, and here's another crop.
The obvious sink method
let ignore _ = () |
actually stores the argument (of generic type a
) in a local variable before returning -- Reflector tells us it looks like
internal static void ignore<a>(a _arg1) | |
{ | |
a local = _arg1; | |
} |
where in general there is one such local assigned for every argument; whereas a C# void method that just swallows its arguments
public static void AnotherUnitStub(int left, int right) | |
{ | |
} |
really does nothing with them, and just returns.
More interesting is the case of exceptions. There being no concept of a bottom type (like Scala's Nothing
), exceptions have to be handled with care by the compiler. Take the cases of two dead simple stub routines -- things that exist to satisfy the linker, but which haven't been written yet, and should fail if called.
let FailStub _ _ _ = failwith "an error" | |
let ThrowStub _ _ _ _ = | |
raise (new NotImplementedException("not yet implemented")) |
The Reflector derived C# equivalents are
public static d FailStub<a, b, c, d>(a _arg17, b _arg16, c _arg15) | |
{ | |
a local = _arg17; | |
b local2 = _arg16; | |
c local3 = _arg15; | |
return Operators.failwith<d>("an error"); | |
} | |
public static e ThrowStub<a, b, c, d, e>(a _arg21, b _arg20, c _arg19, d _arg18) | |
{ | |
a local = _arg21; | |
b local2 = _arg20; | |
c local3 = _arg19; | |
d local4 = _arg18; | |
return Operators.raise<e>(new NotImplementedException("not yet implemented")); | |
} |
Rather than throwing an exception “returning” a type that is a subclass of anything, the operation that wraps the actual throwing, however achieved, sports a generic return type that matches the return type of the function -- and when we explicitly specify the return type, the generic operation is set to that specific type. Meaning, of course, that a branch of a match
or an if
that results in an explicit exception will still match the type of the other clauses.
This behaviour is unchanged in the Feb 2010 CTP (1.9.9.9).