5

I can do this:

[ for i in 0 .. 5 -> i ]

or

[ for i in 0 .. 5 do i ]

but, while I can do this:

[ for i in 0 .. 5 do yield! [i * 4; i] ]

I can't do that:

[ for i in 0 .. 5 -> yield! [i * 4; i] ]

why is that? how are the two treated differently?

Thomas
  • 10,933
  • 14
  • 65
  • 136
  • Does this answer your question? [list comprehension in F#](https://stackoverflow.com/questions/1888451/list-comprehension-in-f) – DaveShaw Apr 28 '20 at 22:09
  • So the takeaway from this link is that you can use -> when you just return a single value. But since they did a change in the compiler, was there a reason to keep -> instead of using ‘do’ for everything? Seems like -> is just one special case already covered by ’do’ – Thomas Apr 28 '20 at 23:04

1 Answers1

11

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.

Tomas Petricek
  • 240,744
  • 19
  • 378
  • 553