Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does F# compiler support foreach optimization in the same way as C# compiler does

Tags:

.net

f#

This is a detailed answer about how C# compiler optimizes foreach in the cases when IEnumerator<T> is a mutable struct.

Does F# compiler perform the same optimization?

like image 856
V.B. Avatar asked Jan 13 '16 19:01

V.B.


People also ask

What does FX -> Y mean?

f:x↦y means that f is a function which takes in a value x and gives out y.

Does Y equal FX?

Remember: The notation "f (x)" is exactly the same thing as "y". You can even label the y-axis on your graphs with "f (x)", if you feel like it.

What does f mean in math?

more ... A special relationship where each input has a single output. It is often written as "f(x)" where x is the input value.

What does f say about f?

Given a function f, the derivative f' can be used to get important information about f. For instance, f is increasing when f'>0. The second derivative gives useful concavity information.


1 Answers

AFAICT It seems F# treats valuetype enumerators in a similar manner as C#:

Here is a disassembled snippet of IL code from a simple C# program that uses foreach over an IEnumerable<T>

.locals init (
    [0] valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<int32>,
    [1] int32 v
)
IL_0025: ldloca.s 0
IL_0027: call instance bool valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<int32>::MoveNext()

Note that local 0 is a valuetype and that it uses ldloca.s to load the address of the struct.

Compare it with F#

.locals init (
    [0] class [mscorlib]System.Collections.Generic.List`1<int32> ra,
    [1] valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<int32>
)
IL_000e: ldloca.s 1
IL_0010: call instance bool valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<int32>::MoveNext()

This code also uses valuetype to declare local 1 and ldloca.s to load the address of the struct.

As a side note: Later F# version does actually do an optimization that C# don't do. Because it's a common pattern in F# to iterate over F# lists that are immutable data structures it's ineffective to iterate using enumerators. So F# has a special case for lists and applies a more efficient algorithm in that case. In C# iterating over F# lists would fallback to enumerators.

It would be possible to implement a special handling for IList types as well but since it's possible someone has implement IList in a "funny" way it's a potentially breaking change to implement such an optimization.

like image 107
Just another metaprogrammer Avatar answered Oct 01 '22 04:10

Just another metaprogrammer