tags:

views:

59

answers:

1

A Purely theoretical question on Tcl.

Following this question I was thinking on what would be the best way to implement anonymous functions in Tcl.

The end result should be allowing a developer to pass a full proc as an argument to anohter proc:

do_something $data {proc {} {input} {
    puts $input;
}};

which would be similar to javascript's

do_something(data, function (input) {
    alert(input);
});

now, naturally this will not work OOTB. I was thinking on something of this sort:

proc do_something {data anon_function} {
    anon_run $anon_function $data
}
proc anon_run {proc args} {
    set rand proc_[clock clicks];
    set script [lreplace $proc 1 1 $rand];
    uplevel 1 $script;
    uplevel 1 [concat $rand $args];
    uplevel 1 rename $rand {}; //delete the created proc
}

This works. But I was hoping to get suggestions for a better pattern then this, as it's not very elegant and not really using cool Tcl features. Mostly I'd like to get rid of manually calling anon_run.

+8  A: 

In Tcl 8.5, you can use the apply command.

proc do_something {data anon_function} {
    apply $anon_function $data
}
do_something $data {{input} {
    puts $input
}}

Of course, if you're structuring your callbacks as command prefixes (recommended!) then you can do this:

proc lambda {arguments body} {
    # We'll do this properly and include the optional namespace
    set ns [uplevel 1 namespace current]
    return [list ::apply [list $arguments $body $ns]]
}

proc do_something {data command} {
    {*}$command $data
}

do_something $data [lambda {input} {
    puts $input
}]

If you're using 8.4 or before, you need the code from the Tcler's Wiki as a substitute, but be aware that those solutions are only semantically equivalent (at best); they're not performance-equivalent.

Donal Fellows
Also note, unlike Javascript it doesn't do closures. Closures are semantically tricky in Tcl because they really don't fit with Tcl's datatype model, and lambda terms as above make this problem particularly obvious (it's not a big problem with procedures; merely a Simple Matter of Programming).
Donal Fellows
I appreciate the detailed and well explained answer.
Nir Levy