Odd word problem/SimpleCoroutineSupportForJ

From Rosetta Code

Here is a simplistic coroutine implementation for J.

Note that this version does not support switching between coroutine contexts -- that would have been an unnecessary complication for this task. (So, technically, it might be better to call this "coroutine inspired".)

<lang j>NB. u coroutine y NB. execute u in new coroutine context coroutine=: 1 :0

 stack=. 
 verb=. u
 noun=. y
 while. do. context=. verb noun
   select. (0 {:: context) * 1+*#stack
     case. 0 do.                   NB. yield
       stack=. stack, 1 { context
       verb=. (2 { context)`:0
       noun=.  3 {:: context
     case. 1 do.                   NB. return (with empty stack)
       1 {:: context return.
     case. 2 do.                   NB. return (with work remaining on stack)
       verb=. ({: stack)`:0
       noun=. 1 {:: context
       stack=. }: stack
     case. do.                     NB. (default)
       invalid coroutine 1 :'error.'
   end.
 end.

)

NB. u yield v y return. NB. 0 -- deferred result, will be executing: u v y yield=: 2 :0

 0; u ` v,< y

)

NB. return y return. NB. 1 -- immediate result: y return=: 3 :0

 1; y

)</lang>

The philosophy here, is: A noun represents code which has already been executed (it's the result of that code having been executed). A verb represents code which has not yet been executed.

A coroutine verb must return a result built by one of the two helper verbs return or yield. If yield is used, it must be supplied with two verbs and a noun. The coroutine context will stack u (the left verb) for later execution and it's argument will be the result of whatever verb was most recently executed by the coroutine context. Meanwhile the coroutine context will execute v (the right verb) right away and its argument will be the noun which was supplied to yield. Both u and v must be coroutine verbs (so they also must must provide a result prepared by return or yield).