Pooh program example 10-object-closure-point.p
# Object oriented programming with closures: point class
sub makepoint( x, y )
  # the object state here are the constructor arguments (x, y)
  # very similar to object by closure
  # an advantage of object-by closure over object as hash (ala javascript)
  # when you type the code, the instance method has to be defined as local of enclosing scope;
  # so you can't misspell the member names.
  # return factory method that returns object methods  - both factory and object methods get capture of the object state 
  return sub( method ) 
      if method eq 'move'
         return sub( dx, dy )
            outer . x = outer . x + dx
            outer . y = outer . y + dy
         end
      elsif method eq 'print'
         return sub()
           println( ~msg 'position x = [ outer.x ] y = [  outer.y ]' )
         end
      elsif method eq 'x-pos'
         return sub()
            return outer.x
         end
      elsif method eq 'y-pos'
         return sub()
             return outer . y
         end
      end
  end
end
# make point object
point := makepoint( ~x 42 ~y 10 )
# show position of point
point( ~method 'print') () 
point( ~method 'move') ( ~dx 10 ~dy 10 )
# show position of point after having moved it.
point( ~method 'print') () 
# call accessor methods.
println( ~msg 'horizontal postion [ point( ~method 'x-pos') () ] vertical position [ point( ~method 'y-pos') () ]' )
position x = 42 y = 10 position x = 52 y = 20 horizontal postion 52 vertical position 20Trace output for 10-object-closure-point.p
039|... := makepoint( ~x 42 ~y 10 )... 014| return sub (~method) 039|point := makepoint( ~x 42 ~y 10 ):-> sub 042|point:-> sub ( ~method 'print' )... 015| if (method:'print' eq 'move'):false 020| else if (method:'print' eq 'print'):true 021| return sub () 031| end # if 042|point:-> sub ( ~method 'print' ):-> sub ( )... 022| println( ~msg 'position x = ' .. outer.x:42 .. ' y = ' .. outer.y:10 .. '' )... 044|point:-> sub ( ~method 'move' )... 015| if (method:'move' eq 'move'):true 016| return sub (~dx , ~dy) 019| end # if 044|point:-> sub ( ~method 'move' ):-> sub ( ~dx 10 ~dy 10 )... 017| outer.x = (outer.x:42 + dx:10):52 018| outer.y = (outer.y:10 + dy:10):20 047|point:-> sub ( ~method 'print' )... 015| if (method:'print' eq 'move'):false 020| else if (method:'print' eq 'print'):true 021| return sub () 031| end # if 047|point:-> sub ( ~method 'print' ):-> sub ( )... 022| println( ~msg 'position x = ' .. outer.x:52 .. ' y = ' .. outer.y:20 .. '' )... 050|println( ~msg 'horizontal postion ' .. point:-> sub ( ~method 'x-pos' )... 015| if (method:'x-pos' eq 'move'):false 020| else if (method:'x-pos' eq 'print'):false 024| else if (method:'x-pos' eq 'x-pos'):true 025| return sub () 031| end # if 050|println( ~msg 'horizontal postion ' .. point:-> sub ( ~method 'x-pos' ):-> sub ( )... 026| return outer.x:52 050|println( ~msg 'horizontal postion ' .. point:-> sub ( ~method 'x-pos' ):-> sub ( ):52 .. ' vertical position ' .. point:-> sub ( ~method 'y-pos' )... 015| if (method:'y-pos' eq 'move'):false 020| else if (method:'y-pos' eq 'print'):false 024| else if (method:'y-pos' eq 'x-pos'):false 028| else if (method:'y-pos' eq 'y-pos'):true 029| return sub () 031| end # if 050|println( ~msg 'horizontal postion ' .. point:-> sub ( ~method 'x-pos' ):-> sub ( ):52 .. ' vertical position ' .. point:-> sub ( ~method 'y-pos' ):-> sub ( )... 030| return outer.y:20 050|println( ~msg 'horizontal postion ' .. point:-> sub ( ~method 'x-pos' ):-> sub ( ):52 .. ' vertical position ' .. point:-> sub ( ~method 'y-pos' ):-> sub ( ):20 .. '' )...