Skip to content

Instantly share code, notes, and snippets.

@OJ
Created January 10, 2010 13:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save OJ/273516 to your computer and use it in GitHub Desktop.
Save OJ/273516 to your computer and use it in GitHub Desktop.
let rec nums = seq { yield 1
for n in nums do yield n+1 }
How does this work?
First thing to remember is that seq is a lazy sequence. It's an IEnumerable under the hood I believe. It'll only evaluate those values which you actually attempt to access. When you take the first element of the sequence, it'll return 1 (I'll assume you know the yield keyword already). The next time you hit the sequence it knows, thanks to yield, that it bypasses the first yield statement and makes it ways to the for loop. That loop iterates over the already-evaluated values in the sequence, which in our case is just 1. So the second item in the sequence is a yield of 1 + 1, whichi s 2. So yes, the two elements of the evaluated sequence are now 1 and 2. When you next access the sequence to get the next value, you are returned to the point where the yield statement was last called and hence we're back in the for loop. The loop has already taken the value of 1 from the previous iteration, but now the sequence contains the value of 2, and that is used in the next iteration of the for loop. So you end up with 2+1.
Yield is the kicker here. It doesn't reparse the entire sequence each time time, it just picks up where it left off.
A quick run through:
1) ask for the first element of nums and we get 1, and internally we've yielded on the first statement so we have a "saved" cursor at that statment
2) ask for the second element of nums, we go back to the yield and execute the next statement. This starts off a "cursor" which begins by taking the first element of nums, the value 1, and again yielding, this time with 1 + 1. This becomes the second value of the sequence
3) ask for the third value, we go back to the second yield statement where our cursor has already gone past the first element of the list and execute again on the second element. This gives us 2, then yields 2 + 1. This value becomes the third element in the sequence.
And so on/so forth.
Does that help? :)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment