Pooh program example 10-object-closure-stack.p
# Object oriented programming with closures: stack class. sub makestack( ) # instance data of the stack object. stack = [] # work by currying (poor mans currying in javascript that is). # return the constructor function # the constructor gets capture of the instance data, so do the methods returned by constructor. # .. or in OO terminology: the object costructor returns the factory method for the object interface (now factory gets object state as closure) # now all this is not very educational per see ;-( but its a good test case to look if closures are working. return sub ( method ) if method eq 'pop' return sub () if size( ~arg outer.stack ) == 0 println( ~msg 'Error: empty stack' ) return Null else println( ~msg 'pop: has [ size( ~arg outer.stack ) ] elements' ) return pop ( ~array outer.stack ) end end elsif method eq 'push' return sub ( top ) push( ~array outer . stack ~top top ) println( ~msg 'push: has [ size( ~arg outer.stack ) ] elements' ) end end end end # ------------------------------------------ # make stack returns a list of function objects, by calling these objects we modify the object data which is the data of the closure stack := makestack( ) dopush := stack( ~method 'push' ) dopop := stack( ~method 'pop' ) dopush( ~top 1 ) dopush( ~top 2 ) dopush( ~top 3 ) i = 1 while i <= 4 println ( ~msg 'pop: result is [ dopop() ]' ) i = i + 1 end
push: has 1 elements push: has 2 elements push: has 3 elements pop: has 3 elements pop: result is 3 pop: has 2 elements pop: result is 2 pop: has 1 elements pop: result is 1 Error: empty stack pop: result isTrace output for 10-object-closure-stack.p
040|... := makestack( )... 006| stack = [ ] 016| return sub (~method) 040|stack := makestack( ):-> sub 042|... := stack:-> sub ( ~method 'push' )... 017| if (method:'push' eq 'pop'):false 027| else if (method:'push' eq 'push'):true 028| return sub (~top) 031| end # if 042|dopush := stack:-> sub ( ~method 'push' ):-> sub 043|... := stack:-> sub ( ~method 'pop' )... 017| if (method:'pop' eq 'pop'):true 018| return sub () 026| end # if 043|dopop := stack:-> sub ( ~method 'pop' ):-> sub 045|dopush:-> sub ( ~top 1 )... 029| push( ~array outer.stack:[ ] ~top top:1 )... 030| println( ~msg 'push: has ' .. size( ~arg outer.stack:[ -> 1 ] )... 030| println( ~msg 'push: has ' .. size( ~arg outer.stack:[ -> 1 ] ):1 .. ' elements' )... 046|dopush:-> sub ( ~top 2 )... 029| push( ~array outer.stack:[ -> 1 ] ~top top:2 )... 030| println( ~msg 'push: has ' .. size( ~arg outer.stack:[ -> 1, -> 2 ] )... 030| println( ~msg 'push: has ' .. size( ~arg outer.stack:[ -> 1, -> 2 ] ):2 .. ' elements' )... 047|dopush:-> sub ( ~top 3 )... 029| push( ~array outer.stack:[ -> 1, -> 2 ] ~top top:3 )... 030| println( ~msg 'push: has ' .. size( ~arg outer.stack:[ -> 1, -> 2, -> 3 ] )... 030| println( ~msg 'push: has ' .. size( ~arg outer.stack:[ -> 1, -> 2, -> 3 ] ):3 .. ' elements' )... 050|i = 1 051|while (i:1 <= 4):true 052| println( ~msg 'pop: result is ' .. dopop:-> sub ( )... 019| if (size( ~arg outer.stack:[ -> 1, -> 2, -> 3 ] )... 019| if (size( ~arg outer.stack:[ -> 1, -> 2, -> 3 ] ):3 == 0):false 021| else 023| println( ~msg 'pop: has ' .. size( ~arg outer.stack:[ -> 1, -> 2, -> 3 ] )... 023| println( ~msg 'pop: has ' .. size( ~arg outer.stack:[ -> 1, -> 2, -> 3 ] ):3 .. ' elements' )... 024| return pop( ~array outer.stack:[ -> 1, -> 2, -> 3 ] )... 024| return pop( ~array outer.stack:[ -> 1, -> 2, -> 3 ] ):-> 3 024| end # if 052| println( ~msg 'pop: result is ' .. dopop:-> sub ( ):-> 3 .. '' )... 053| i = (i:1 + 1):2 054|end 051|while (i:2 <= 4):true 052| println( ~msg 'pop: result is ' .. dopop:-> sub ( )... 019| if (size( ~arg outer.stack:[ -> 1, -> 2 ] )... 019| if (size( ~arg outer.stack:[ -> 1, -> 2 ] ):2 == 0):false 021| else 023| println( ~msg 'pop: has ' .. size( ~arg outer.stack:[ -> 1, -> 2 ] )... 023| println( ~msg 'pop: has ' .. size( ~arg outer.stack:[ -> 1, -> 2 ] ):2 .. ' elements' )... 024| return pop( ~array outer.stack:[ -> 1, -> 2 ] )... 024| return pop( ~array outer.stack:[ -> 1, -> 2 ] ):-> 2 024| end # if 052| println( ~msg 'pop: result is ' .. dopop:-> sub ( ):-> 2 .. '' )... 053| i = (i:2 + 1):3 054|end 051|while (i:3 <= 4):true 052| println( ~msg 'pop: result is ' .. dopop:-> sub ( )... 019| if (size( ~arg outer.stack:[ -> 1 ] )... 019| if (size( ~arg outer.stack:[ -> 1 ] ):1 == 0):false 021| else 023| println( ~msg 'pop: has ' .. size( ~arg outer.stack:[ -> 1 ] )... 023| println( ~msg 'pop: has ' .. size( ~arg outer.stack:[ -> 1 ] ):1 .. ' elements' )... 024| return pop( ~array outer.stack:[ -> 1 ] )... 024| return pop( ~array outer.stack:[ -> 1 ] ):-> 1 024| end # if 052| println( ~msg 'pop: result is ' .. dopop:-> sub ( ):-> 1 .. '' )... 053| i = (i:3 + 1):4 054|end 051|while (i:4 <= 4):true 052| println( ~msg 'pop: result is ' .. dopop:-> sub ( )... 019| if (size( ~arg outer.stack:[ ] )... 019| if (size( ~arg outer.stack:[ ] ):0 == 0):true 020| println( ~msg 'Error: empty stack' )... 021| return Null 021| end # if 052| println( ~msg 'pop: result is ' .. dopop:-> sub ( ):Null .. '' )... 053| i = (i:4 + 1):5 054|end 051|while (i:5 <= 4):false 054|end # finish loop