Pooh program example 10-object-closure-stack.p

Test 10-object-closure-stack.p

Source of programm

# 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


Standard output for 10-object-closure-stack.p

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 is 

Trace 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