Nonads -- coroutine/generator alternative

Download Lab and class files here: Nonad.zip

(.ijs files must go into user/classes)

(ijt file is Lab file and must go to: system\extras\labs\personal to show up in Labs selector)

Nonads main property is that they wrap State information inside a function so that their return value is usually unaffected by their arguments. The name nonad implies 0 arguments. They combine 3 functions with the state, by convention, into a single function interface. Most of the code presented is helper functions to make creating nonads as easy as possible. The 3 functions are:

transform function: function in generative form that is almost always implemented either as: STATE =: transform STATE or STATE =: STATE transform y. This function takes care of maintaining/ persisting the STATE between calls.

output function: optional function to produce a result from the state that is different than the maintained permanent state to be recalled later. It is a convenient result the nonad user wants to receive on each call.

control function: this function is a constructor, that takes as parameters the 2 other functions and an initial state, describes how to combine them, and then wraps a functional interface to the computation (a verb) that can be used like any other verb in J.

The lab is very detailed. Here Core class definition:

coclass'no'
NB. see nonad.ijs for description.

coinsert 'base';'nonad'
function=: i.0
transform=: }.

create=: 3 : 0
  STATE=: y
)
destroy=: codestroy

cocurrent 'base'

Nonad=: 1 : 0 NB. core creator function.
lastobj =. y conew 'no'
function__lastobj =: u
if. 0=4!:0 <'function__lastobj' do.  NB. if gerund... if not, set transform to behead list
         '`function__lastobj transform__lastobj' =: function__lastobj 
        end.
lastobj 
)

Resume=: 2 : 0
  o =. u Nonad n
  c__o =. 3 : 'if. 0<#STATE do. (STATE=: transform STATE) ] function STATE end.' 
  'c' at o
)

Closure=: 2 : 0 NB. dyad u initial state n
  o =. u Nonad n
  c__o =. 3 : '] STATE=:  STATE function y ' 
  'c' at o
)

List =: 1 : 0
  o =. {. Nonad m
  resume__o =. 3 : 'if. 0<#STATE do. (STATE=: transform STATE) ] function STATE end.' 
  NB. if count of y is 0 or 1 (atom or null), call once.
  c__o=. 3 : 'if. (# y=.( 1:`]@.(*@:#) y))<#STATE do. resume"0 i. #y else. resume"0 i. #STATE end.'
  'c' at o
)

NotemptyA =: 1 : 'if. 0<#y do. u y end.'

DualNo =: 1 : 0 NB. creates a dyadic verb that is 4: Nf : getstate
u : ('STATE' OO (u GetO))
)

GetO =: 1 : 0   NB. takes a monadic wrapped nonad function, unpacks its locale and returns it 
NB. locale determined by xxxxx_localeNameOrNumber_ using last 2 _s
t=. > 5!:5 <'u'
p=.  , I. -. '_' i. t   NB. positions of '_'s
NB. assert. (2 <: #p )
p=. _2 {. p
< ( (>:@:{. p) +  i. ( 1: -~{. -~ {:) p) {t 
)

OO=:2 :0                        NB. m: string of method/field, y: locale number
NB. returns function that is either method or Get-field for the member
nm=. m ref n
if. 0=4!:0 < nm do. nm=.".bind nm return. end.
m at n
)

  ref=: 4 : 'x,''_'',(":>y),''_'''
  at=: 2 : '(m ref n)~' 

Links: http://www.jsoftware.com/jwiki/FrequentlyAskedQuestions/LexicalClosure

PascalJasmin/Nonads (last edited 2008-12-08 10:45:47 by )