in reply to Re: passing subroutine references
in thread passing subroutine references

I would not call that a better fix. Adds unnecessary complexity and just confuses things. If you do insist that you do not want to have to pass the $move_disk around, it's cleaner to do it like this:

{ my $move_disk; sub hanoi { $move_disk = pop(@_); goto &_hanoi; # (almost) equivalent to _hanoi(@_) } sub _hanoi { my ( $n, $start, $end, $extra ) = @_; if ( $n == 1 ) { $move_disk->( 1, $start, $end ); } else { _hanoi( $n - 1, $start, $extra, $end ); $move_disk->( $n, $start, $end ); _hanoi( $n - 1, $extra, $end, $start ); } }; } hanoi( 3, 'A', 'B', 'C', sub {print "(@_)\n"} );

Jenda
Enoch was right!
Enjoy the last years of Rome.

Replies are listed 'Best First'.
Re^3: passing subroutine references
by ikegami (Patriarch) on Sep 19, 2009 at 13:37 UTC

    Your solution to getting rid of complexity is to get rid of a local and add goto &_hanoi;?

    Even a beginner needs to know local, whereas they wouldn't know goto &_hanoi;, and it adds debugging complexities at next to no benefit.

    And at what cost? You've added a global var, you've made the private recursive function public, and you've nested the main function (which seems innocent, but I've found it to cause is to confuse me time and time again).

    I beg to differ. I think you've taken 4 steps back.

      Global? There ain't any global sir. Neither there is any nested function. And _hanoi(@_); would work just as well, while your tricks with local are unavoidable. Besides the problem is not the local itself, but the typeglob handling.

      What debugging complexities are you speaking of?

      Jenda
      Enoch was right!
      Enjoy the last years of Rome.

        Global? There ain't any global sir.

        Global to all calls to hanoi. External? Non-local? Yet highly coupled.

        And _hanoi(@_); would work just as well

        That's what I said.

        while your tricks with local are unavoidable.

        How is localising a var "a trick"? Dealing with package vars is a necessity in Perl, and the first thing you need to know is how to localise them.

        It is avoidable, but it's messy and requires a trick to avoid a memory leak.

        my $_hanoi; # \ Messy line break $_hanoi = sub { # / ... $_hanoi->(...); # Relatively messy syntax ... }; $_hanoi->(...); undef $_hanoi; # Messy hack to avoid mem leak.

        Using local actually cleans up a whole of mess.

        Besides the problem is not the local itself, but the typeglob handling.

        "The typeglob handling" makes "setting a typeglob" sound falsely ominous. It's a manufactured problem.

        What debugging complexities are you speaking of?

        The removal of a stack frame creates lying stack traces, not just to users but to debugging tools.

Re^3: passing subroutine references
by joe76 (Novice) on Sep 20, 2009 at 17:02 UTC

    but is it really that expensive to do in my original code? aren't we just passing an address to the code, not the code itself?

      Honestly, I don't know how big a waste of memory it is. When it comes to recursive functions, having a big state can be a problem. It's a good idea to avoid a large state unless you can show it's not a problem rather than the other way around. Factoring out unchanging variables is an easy and low-cost way of reducing the size of the state.

      It would be a bigger problem in another language where the stack has a limited size. Perl dynamically allocates each stack frame on the heap, so it's not limited like in C.

      No it's not. We are of course passing just the reference.

      Jenda
      Enoch was right!
      Enjoy the last years of Rome.