This is quite tricky, because there are a few things here that F# does implicitly.
First, the ->
syntax is really just a shortcut for do yield
, so the following translates as:
[ for i in 0 .. 5 -> i ]
= [ for i in 0 .. 5 do yield i ]
This explains why you cannot do -> yield!
because the translation would result in:
[ for i in 0 .. 5 -> yield! [i * 4; i] ]
= [ for i in 0 .. 5 do yield (yield! [i * 4; i]) ]
You would have yield!
nested inside yield
, which makes no sense.
The second tricky thing is the syntax with just do
. This is a recent change in F# that makes writing list generators easier (which is fantastic for domain-specific languages that construct things like HTML trees) - the compiler implicitly inserts yield
so the code translates as:
[ for i in 0 .. 5 do i ]
= [ for i in 0 .. 5 do yield i ]
The interesting thing is that this works with multiple yields as well:
[ for i in 0 .. 5 do
i
i*10 ]
= [ for i in 0 .. 5 do
yield i
yield i*10 ]
This is another difference between ->
and do
. With ->
, you can only yield one thing. With do
, you can yield multiple things.
I imagine that there is very little reason for using ->
nowadays. This was in the language before the implicit yield
and so it was useful in earlier versions of F#. You probably do not really need that anymore when do
makes things as easy.