in reply to Passing anon sub as param

(1) To make traverse reusable. You can change the action taken for every node without editing traverse. You can make traverse do two different things without writing two different versions of it. As BrowserUK's mentioned in his post, "By passing a sub to the traverse routine you can make it do things other than just printing."

(2) Same answer as above. Both will work,

(3) The sub needs to be provided the node on which it is to perform an action. Normally, the node would have been passed as a parameter. This alternate way is a bit more concise and has less overhead.

Replies are listed 'Best First'.
Re^2: Passing anon sub as param
by punkish (Priest) on Jul 28, 2005 at 20:36 UTC
    (1) To make traverse reusable. You can change the action taken for every node without editing traverse. You can make traverse do two different things without writing two different versions of it.

    Hence, I could have done the following just as well --

    sub traverse { # do yer stuff _print($_); traverse(..); } sub _print { my ($node) = @_; print ' ' x $node->{dept}, $node->{c_id}, ': ', $_->{comm}, "\n"; }

    Which, I did, and it also works. Hence, passing an anon sub as a param seems to be just a fancy way of doing what I already know MTOWODI, no?

    --

    when small people start casting long shadows, it is time to go to bed

      I personally think that the anon-sub call back is just cleaner looking, but it has a number of other benefits. The biggest of those is that it doesn't break or force you to do ugly things if traverse is in another package.

      Other benefits: you don't clutter up your symbol table with global named functions that are only intended to be used in one place. Also: you can use traverse in different ways in the same application, rather than defining the callback globally.

      I also think that defining a fallback is cleaner in this case: you just check the $code arg for definedness, rather than probing the caller's package. Scope is nice and closed.

      How about I explain by example:
      traverse($in, 0, 0, sub {print ' ' x $_->{dept},'-',$_->{comm},"\n";}) +; ... later in the code... traverse($in, 0, 0, sub {$sth->execute($dept, $comm)});
      By the way, the sub doesn't have to be anon:
      sub _print { print ' ' x $_->{dept},'-',$_->{comm},"\n"; } traverse($in, 0, 0, \&_print);

      It's a feature, it has no side effects, so there's no reason to get rid of it, and there's every reason to keep it. If you don't want to explicitely specify it, create a wrapper:

      sub print_tree { push(@_, 0, 0, sub {print ' ' x $_->{dept},'-',$_->{comm},"\n";}); &traverse; } print_tree($in);

      Passing an action in allows the parent node to determine the action rather than the local node determining the action.


      Perl is Huffman encoded by design.