в чем разница между '->' и 'do' в a для l oop, в F # - PullRequest
4 голосов
/ 29 апреля 2020

Я могу сделать это:

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

или

[ for i in 0 .. 5 do i ]

, но пока я могу это сделать:

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

Я не могу этого сделать :

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

почему это так? как они трактуются по-разному?

1 Ответ

9 голосов
/ 29 апреля 2020

Это довольно сложно, потому что есть несколько вещей, которые F # делает неявно.

Во-первых, синтаксис -> на самом деле является просто сокращением для do yield, поэтому следующее переводится как:

  [ for i in 0 .. 5 -> i ] 
= [ for i in 0 .. 5 do yield i ]

Это объясняет, почему вы не можете сделать -> yield!, потому что перевод приведет к:

  [ for i in 0 .. 5 -> yield! [i * 4; i] ]
= [ for i in 0 .. 5 do yield (yield! [i * 4; i]) ]

Вы бы вложили yield! внутрь yield, что не имеет смысла.

Второй хитрый момент - это синтаксис с do. Это недавнее изменение в F #, которое облегчает написание генераторов списков (это фантастика c для домен-специфических c языков, которые конструируют такие вещи, как HTML деревья) - компилятор неявно вставляет yield, поэтому код переводится как :

  [ for i in 0 .. 5 do i ]
= [ for i in 0 .. 5 do yield i ]

Интересно то, что это работает и с несколькими выходами:

  [ for i in 0 .. 5 do 
      i
      i*10 ]

= [ for i in 0 .. 5 do 
      yield i 
      yield i*10 ]

Это еще одно различие между -> и do. С -> вы можете получить только одну вещь. С do вы можете получить несколько вещей.

Я полагаю, что сейчас очень мало причин для использования ->. Это было на языке до неявного yield и поэтому было полезно в более ранних версиях F #. Возможно, вам это больше не нужно, когда do упрощает задачу.

...