RE: [tcltk-perl] Change the way that %-subs are handled.
Brought to you by:
hobbs
From: Jeff H. <je...@Ac...> - 2004-04-21 18:57:30
|
> my $sub = sub { > my ($X, $Y) = (Tcl::Ev('X'), Tcl::Ev('Y')); > print "X: $X Y: $Y\n"; > }; > $mw->bind('<Motion>', \\'XY', $sub); OK, I've manage to make this work, so the above would be written as: my $sub = sub { print STDERR "CALLBACK (@_)\n"; }; $mw->bind('<Motion>', [$sub, Tcl::EV('%X', '%Y'), '<Motion>']); and that would end up printing out something like: CALLBACK (440 532 <Motion>) I think this is a much cleaner way to operate. It allows you to declare the %-subs you want, like you do in Tcl, and it passes them to your sub. The only limitation is that the Tcl::EV(...) must come first in the args set, although that is just a convenience for now. The core pieces of the code to make this work in Tcl.pm are: in Tcl.pm:call(): elsif ($ref eq 'ARRAY' && ref($arg->[0]) eq 'CODE') { # We have been passed something like [\&subroutine, $arg1, ...] # Create a proc in Tcl that invokes this subroutine with args my $events; if ($#$arg >= 1 && ref($arg->[1]) eq 'Tcl::EV') { $events = splice(@$arg, 1, 1); } $args[$argcnt] = $interp->create_tcl_sub(sub { splice @_, 0, 3; # remove ClientData, Interp and CmdName $arg->[0]->(@_, @$arg[1..$#$arg]); }, $events); } in Tcl.pm: sub create_tcl_sub { my ($interp,$sub,$events,$tclname) = @_; unless ($tclname) { # stringify sub, becomes "CODE(0x######)" in ::perl namespace $tclname = "::perl::$sub"; } unless (exists $anon_refs{$tclname}) { $anon_refs{$tclname}++; $interp->CreateCommand($tclname, $sub); } if ($events) { $tclname = "$tclname " . join(' ', @{$events}); } return $tclname; } sub EV { my @events = @_; return bless \@events, "Tcl::EV"; } and then we can get rid of all the other Ev ref stuff. While this might not be "ideal", I find it much more logical and easier to work with than the previous solution. You could auto-prepend each %, but I think it's good to keep the logical connection of %-sub there. Note that this also changes/corrects the call to code refs that take args to called subroutines to pass args from Tcl first, before the args that were given in perl. In somewhat related changes, code and variables created in Tcl from Perl go into the ::perl namespace in Tcl. Jeff |