L supports what might be called variously function pointers, bound method references and closures
via values of proc type. Values of proc type are created from a method name or a literal procedure and can then later
be 'deprocedured' using the normal method call syntax of parentheses plus an option list of parameters. Proc refs are
structurally typed.
Source:namespace Proc is
class Main is
void init() is
// create a random binary search tree:
var r = Tree.RandomTree;
// static proc ref:
// visit each node in pre-order calling a static method of
// this class at each node. This is roughly equivalent to a
// function pointer in C:
var p = void proc(Tree)(static_visit);
IO.Std.out.println( "visit " + r + " with static proc ref in pre-order" );
IO.Std.out.println( "proc is: " + p );
r.visit(p, Order.PRE);
// bound proc ref:
// visit each node in post-order calling a virtual method of
// this class at each node. Virtual method resolution is performed
// here when the proc ref is created. 'this' in the called procedure
// will reference the same object as 'this' at proc ref creation time.
p = void proc(Tree)(bound_visit);
IO.Std.out.println( "visit " + r + " with bound proc ref in post-order" );
IO.Std.out.println( "proc is: " + p );
r.visit(p, Order.POST);
// bound proc ref, procedure literal:
// visit each node in-order calling a literal procedure
// at each node. A literal procedure can be static or virtual
// depending on whether the method it is nested in is static or
// virtual. In this case the method is virtual:
p = void proc(Tree t) is
IO.Std.out.println( "literal visit from " + this + ": " + t.Value );
si;
IO.Std.out.println( "visit " + r + " with proc literal in order" );
IO.Std.out.println( "proc is: " + p );
r.visit(p, Order.IN);
// closure proc ref:
// visit each node in pre-order calling a literal proc with
// additional associated (read only) variables. This is a
// form of closure which is efficient when a small number of
// read only captured values is wanted:
// create some variables that will be captured by the closure:
var a = "A", b = "B", c = "C";
IO.Std.out.println( "visit " + r + " with closure proc ref in pre-order: " );
IO.Std.out.println( "proc is: " + p );
p = void proc(Tree t) use a, b, c is
IO.Std.out.println( "literal visit from " + this + "(" + a + "," + b + "," + c + "): " + t.Value );
si;
r.visit(p, Order.PRE);
// bound proc ref, object of different class:
// visit each node in pre-order calling a virtual method on an
// object of a different class. Virtual method resolution is
// performed here based on the the class of the supplied object and
// 'this' in the called procedure is bound to that object. This
// is an alternate form of closure suitable where captured state
// is larger or needs to be altered across calls
p = void proc(Tree)(new Other("A", "B", "C").visit);
IO.Std.out.println( "visit " + r + " with bound proc ref in post-order: " );
IO.Std.out.println( "proc is: " + p );
r.visit(p, Order.POST);
si
static void static_visit(Tree t) is
IO.Std.out.println( "static visit: " + t.Value );
si
void bound_visit(Tree t) is
IO.Std.out.println( "bound visit from " + this + ": " + t.Value );
si
String toString() is
return "Proc.Main";
si
si
class Other is
String a, b, c;
void init( String a, String b, String c ) is
this.a = a;
this.b = b;
this.c = c;
si
void visit( Tree t ) is
IO.Std.out.println( "visit from " + this + ": " + t.Value );
si
String toString() is
return "Other(" + a + "," + b + "," + c + ")";
si
si
enum Order is
PRE,
IN,
POST
si
class Tree is
int value;
Tree left, right;
void init( int v ) is
this.value = v;
si
static void insert( Tree ref into, int value ) is
if into == null then
into = new Tree(value);
elif value < into.value then
insert(into.left,value);
else
insert(into.right,value);
fi
si
void visit( void proc(Tree) p, Order o ) is
if o == Order.PRE then
p(this);
fi
if left != null then
left.visit(p, o);
fi
if o == Order.IN then
p(this);
fi
if right != null then
right.visit(p, o);
fi
if o == Order.POST then
p(this);
fi
si
get int Value is
return value;
si
String toString() is
var b = new StringBuffer();
b
.append( '(' )
.append( value );
if left != null then
b
.append( ',' )
.append( left );
fi
if right != null then
b
.append( ',' )
.append( right );
fi
b.append( ')' );
return b;
si
static get Tree RandomTree is
Tree result;
foreach var i; 1..5 do
insert(result, cast int(native.rand()) % 100);
od
return result;
si
si
si
visit (35,(21),(86,(49),(92))) with static proc ref in pre-order
proc is: void proc(LSPPage.P_29533_78.Proc.Tree) @7F53930FE430
static visit: 35
static visit: 21
static visit: 86
static visit: 49
static visit: 92
visit (35,(21),(86,(49),(92))) with bound proc ref in post-order
proc is: void proc(LSPPage.P_29533_78.Proc.Tree) @18CC0C8
bound visit from Proc.Main: 21
bound visit from Proc.Main: 49
bound visit from Proc.Main: 92
bound visit from Proc.Main: 86
bound visit from Proc.Main: 35
visit (35,(21),(86,(49),(92))) with proc literal in order
proc is: void proc(LSPPage.P_29533_78.Proc.Tree) @18CEC58
literal visit from Proc.Main: 21
literal visit from Proc.Main: 35
literal visit from Proc.Main: 49
literal visit from Proc.Main: 86
literal visit from Proc.Main: 92
visit (35,(21),(86,(49),(92))) with closure proc ref in pre-order:
proc is: void proc(LSPPage.P_29533_78.Proc.Tree) @18CEC58
literal visit from Proc.Main(A,B,C): 35
literal visit from Proc.Main(A,B,C): 21
literal visit from Proc.Main(A,B,C): 86
literal visit from Proc.Main(A,B,C): 49
literal visit from Proc.Main(A,B,C): 92
visit (35,(21),(86,(49),(92))) with bound proc ref in post-order:
proc is: void proc(LSPPage.P_29533_78.Proc.Tree) @18D0E88
visit from Other(A,B,C): 21
visit from Other(A,B,C): 49
visit from Other(A,B,C): 92
visit from Other(A,B,C): 86
visit from Other(A,B,C): 35
proc is: void proc(LSPPage.P_29533_78.Proc.Tree) @7F53930FE430
static visit: 35
static visit: 21
static visit: 86
static visit: 49
static visit: 92
visit (35,(21),(86,(49),(92))) with bound proc ref in post-order
proc is: void proc(LSPPage.P_29533_78.Proc.Tree) @18CC0C8
bound visit from Proc.Main: 21
bound visit from Proc.Main: 49
bound visit from Proc.Main: 92
bound visit from Proc.Main: 86
bound visit from Proc.Main: 35
visit (35,(21),(86,(49),(92))) with proc literal in order
proc is: void proc(LSPPage.P_29533_78.Proc.Tree) @18CEC58
literal visit from Proc.Main: 21
literal visit from Proc.Main: 35
literal visit from Proc.Main: 49
literal visit from Proc.Main: 86
literal visit from Proc.Main: 92
visit (35,(21),(86,(49),(92))) with closure proc ref in pre-order:
proc is: void proc(LSPPage.P_29533_78.Proc.Tree) @18CEC58
literal visit from Proc.Main(A,B,C): 35
literal visit from Proc.Main(A,B,C): 21
literal visit from Proc.Main(A,B,C): 86
literal visit from Proc.Main(A,B,C): 49
literal visit from Proc.Main(A,B,C): 92
visit (35,(21),(86,(49),(92))) with bound proc ref in post-order:
proc is: void proc(LSPPage.P_29533_78.Proc.Tree) @18D0E88
visit from Other(A,B,C): 21
visit from Other(A,B,C): 49
visit from Other(A,B,C): 92
visit from Other(A,B,C): 86
visit from Other(A,B,C): 35
site design and content copyright (C) jeek 1995-2010  
[
13132
]