Hacker News new | past | comments | ask | show | jobs | submit login

I'm used to calling these "Generators", as in a "Generator Function". We could use Forth's defining words to build a pretty succinct version of this type of functionality. Generators will be called by executing their address ("xt" in Forth parlance), and will leave a flag on the stack indicating whether the generator had another element available. If this flag is true, the element produced will be underneath.

To start with, let's create a word called "count" which produces a generator which will count from 1 to infinity:

  : count ( -- 'gen )
  	noname create 0 , latestxt
  	does> ( -- value? flag )
  	dup @ 1+ dup >r swap ! r> true
  ;
Then we build another generator which slices the first N elements of another generator, so that we can do things without going into an infinite loop:

  : slice ( 'gen count -- 'gen )
  	noname create , , latestxt
  	does> ( -- value? flag )
  	dup @ 0= if drop false exit then
  	dup dup @ 1- swap !
  	cell+ @ execute
  ;
Finally, let's implement "map", so that we can apply a word to every element produced by the generator:

  : map ( 'gen 'func -- )
  	2>r
  	begin
  		i' execute
  		if   i execute
  		else 2rdrop exit
  		then
  	again
  ;
Now the Forth stack gives us a nice, fluent way of chaining these building blocks together. Let's start with that infinite counter, slice off the first 10 elements and print them out by mapping them to the number printing word ".":

  count 10 slice ' . map
And we get:

  1 2 3 4 5 6 7 8 9 10
Spiffy, hunh?



Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact

Search: