in reply to Re^2: The & prototype and code references in scalars.
in thread The & prototype and code references in scalars.

Another way:

sub testit{ print 'hi' } sub doit (&) { $_[0]->() } $codeRef = \&testit; doit { &$codeRef };

update (after BrowserUk's response below) -

My suggestion adds next to nothing, since wrt to sub stacks, $ref->() is just syntactic sugar for &$ref or vice versa. The notation doit \&{ $subref } seems to be the right thing to do:

#!/usr/bin/perl use Carp qw(cluck); sub testit{ cluck 'hi',$/ };; sub doit (&) { print $_[0],$/;$_[0]->() };; $codeRef = \&testit;; doit { &$codeRef }; __END__ CODE(0x955737c) hi at coderef.pl line 3 main::testit called at coderef.pl line 6 main::__ANON__() called at coderef.pl line 4 main::doit('CODE(0x955737c)') called at coderef.pl line 6
#!/usr/bin/perl use Carp qw(cluck); sub testit{ cluck 'hi',$/ };; sub doit (&) { print $_[0],$/;$_[0]->() };; $codeRef = \&testit;; doit \&{ $codeRef }; __END__ CODE(0x9f4c11c) hi at coderef.pl line 3 main::testit() called at coderef.pl line 4 main::doit('CODE(0x9f4c11c)') called at coderef.pl line 6

Replies are listed 'Best First'.
Re^4: The & prototype and code references in scalars.
by LanX (Saint) on Feb 18, 2010 at 00:11 UTC
    hmm it even works when passing parameters 8)

    DB<11> $codeRef= sub { print @_ } DB<12> sub doit (&) { $_[0]->("para") } DB<13> doit { &$codeRef } para

    But one should check about the costs of the extra call level ... maybe not too big.

    Cheers Rolf

      I might be off topic, but, wouldn't that probably lead to more obscuring of data which might be a good thing in OOP concept of closures-mediated security?

      Prototype checking has been disabled in both the following examples...

      my $coderef = sub {shift;}; my $val=$coderef->("Hello from down under"); sub doit{ print shift, $/; } &doit($val);
      or another more succinct way of achieving the same
      my $coderef = sub {shift;}; sub doit{ print shift, $/; } &doit($coderef->("Hello from down under"));
      Update: Added the following code demonstration to clarify what I mean:

      suppose I don't want the constructor to be directly modified from outside the package namespace of a class, so I return a reference to a closure from the constructor which can be indirectly accessed via an instance method of the class.

      #Closured.pm #!/usr/local/bin/perl -cw use strict; use warnings; package Closured; sub new{ our $self; my $closure = sub { shift; if(@_){ $self = shift; } return $self; }; bless $closure; return $closure; #returning a codeRef instead } sub name{ &{$_[0]}; } 1;
      #using the Closured class... use strict; use warnings; use Closured; my $object = Closured->new("Hisham"); #try to feed a constructor direc +tly. print $object,$/; #the constructor retruns a code ref. print $object->name("BioHisham"), "\n"; #Feed via an instance method
      #Output Closured=CODE(0x18449ac) BioHisham


      Excellence is an Endeavor of Persistence. Chance Favors a Prepared Mind.
        I'm not sure what you mean, BUK needs the (&) prototype as syntactic sugar to avoid writing the sub statement to get a coderef like in doit sub {...code ...}

        But "disabling prototype checking" leads to another solution of his problem 8)

        DB<8> sub doit (&) { $_[0]->("para") } DB<9> $codeRef= sub { print @_ } DB<10> doit {print @_} para DB<11> &doit($codeRef) # disable checking para

        Cheers Rolf

Re^4: The & prototype and code references in scalars.
by BrowserUk (Patriarch) on Feb 18, 2010 at 00:22 UTC

    Yes, but you're effectively making nested subroutine calls that way, which for small subs can mean a 25% to 30% performance hit


    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.