Stories
Slash Boxes
Comments
NOTE: use Perl; is on undef hiatus. You can read content, but you can't post it. More info will be forthcoming forthcomingly.

All the Perl that's Practical to Extract and Report

The Fine Print: The following comments are owned by whoever posted them. We are not responsible for them in any way.
 Full
 Abbreviated
 Hidden
More | Login | Reply
Loading... please wait.
  • Don't those kinds of closures leak (anonymous recursive subs, that is), unless maybe you use maybe Scalar::Util::weaken or one of those combinator [perl.org] -type thingies (or some Devel::* module I think or something else)? Or do you really even care in this instance? :-)
    • I don't think they leak - there were some bugs with eval blocks and anonymous subs, but I think all those leaks have been closed now.

      This design is used a lot by IO::AIO (which is used in some people's production apps) and thus if it leaked we would find out about it darn fast.
      • I thought it happened whenever you had the my $sub; $sub = sub { ...$sub... }; construct, and that whenever that code got called, the reference count for $sub would never go to zero. Is what you're doing any different than this (leaks in 5.8), or did this sort of thing recently get fixed?:

        my $foo = sub {
          my $sub;
          $sub = sub {
            $sub;
          };
        };

        my $i;
        print "Start: ";
        <STDIN>;
        while (++$i) {
          my $f = $foo->();
          unless ( $i % 100_000 ) {
            print "$i: ";

        • That does indeed seem to leak, but it's fixed by adding weaken($sub) inside the anonymous sub, so that's no big deal to me. Thanks for the heads up though.
          • I know weaken() was one of the options, but I'm trying to become a functional weenie, so I'm starting to like the combinator approach (this example ripped and tweaked from the Moose source):

            sub U {
                my $f = shift;
                sub { $f->($f, @_) };
            }

            sub Y {
                my $f = shift;
                U(sub { my $h = shift; sub { $f->(U($h)->())->(@_) } })->();
            }

            # Now we need a recursive anonymous function
            my $fact = Y(sub {
              my $f = shift;
              sub {
                my $n = shift;

            • So here's a version that doesn't leak, that uses this approach, and isn't so darn cryptic:

              # wrap an anonymous function into a function that takes $func as the first
              # parameter so we can make use of it from within the call.
              sub wrap_func {
                  my $func = shift;
                  return sub { $func->($func, @_) };
              }
               
              ...
              # sometime later...
               
              $imap->message_info($i, wrap_func(sub {
                  my $sub = shift;
                  my $flags = shift;
                  my $headers = shift;
                  p

              • Well yes, you get away without the Y combinator here. wrap_func is a rather nondescript name, though, don’t you agree? A better one might be something like curry_self or apply_self_maker or some such, although it’s probably not obvious to someone without basic knowledge of functional programming why these names are in fact better. All of them sound similarly meaningless, though the better ones might even be a little scary. And to someone with functional programming knowledge, U would be just a

                • Your "fix" doesn't work.

                  wrap_func() took a function, and returned a new function that took the given $func as the first argument. Therefore, in my callback $sub is not "wrapped", so needs to be re-wrapped.