Beefy Boxes and Bandwidth Generously Provided by pair Networks
"be consistent"
 
PerlMonks  

The & prototype and code references in scalars.

by BrowserUk (Patriarch)
on Feb 17, 2010 at 19:42 UTC ( [id://823796]=perlquestion: print w/replies, xml ) Need Help??

BrowserUk has asked for the wisdom of the Perl Monks concerning the following question:

I'm sure I've done this previously, but how escapes me just now:

sub testit{ print 'hi' };; sub doit (&) { $_[0]->() };; $codeRef = \&testit;; doit( $codeRef );; Type of arg 1 to main::doit must be block or sub {} (not scalar derefe +rence)

Thanks.


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.

Replies are listed 'Best First'.
Re: The & prototype and code references in scalars.
by Corion (Patriarch) on Feb 17, 2010 at 20:04 UTC

    You can always disable prototypes, but I'm not sure if that's what you meant:

    &doit( $codeRef );

      That works! I think I did something else though?

      Update: I found the example on the disk image DVD from my old machine;

      doit \&{ $codeRef };;

      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.

        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
Re: The & prototype and code references in scalars.
by cdarke (Prior) on Feb 17, 2010 at 20:18 UTC
    sub testit{ print 'hi' };; sub doit (\&) { $_[0]->() };; my $codeRef = \&testit;; doit( &$codeRef );
    or:
    sub doit2 (&) { $_[0]->() }; doit2( sub { print 'hi2' });
    I've a thing about prototypes, don't ya just love em!

      The first example isn't an option because the sub in question is in a module (threads::async()). Also it defeats the most common use case of an in-line bareblock.

      The latter doesn't help as I only have (multiple) coderefs at the place of use. I could use async{ $coderef->( ... ) };, but I'm not keen on the doubling of the call overhead.

      I just rediscovered async \&{ $codeRef };. I'm not sure if that's equally costly.


      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.
        We had this discussion recently¹, unfortunately you can't define a prototype which allows literal codeblocks and coderefs (resp. scalars) at the same time.

        You can allow alternatives with (\[&$]) but alas there is no ([&$]) 8(

        At least you can spare the curlies async \&$codeRef ; !

        Cheers Rolf

        ¹) update see coderefs and (&) prototypes

Re: The & prototype and code references in scalars.
by biohisham (Priest) on Feb 18, 2010 at 12:56 UTC
    I have this observation on when I read your post. First, the error I am getting seems to be different on my version, "perl 5.10.0 for MSWin32" when I run your code, I think the "not scalar dereference" or "not private variable" don't really reflect the same thing (that is debatable as I want to garner views on this from our revered monks).

    A "variable" can be any one of the Perl variables we know of and in this case perl thinks it is supposed to be "private" -When I read your post I thought you were making a private subroutine to another subroutine- and which you just happened to not dereference as it should have been. Whereas a "scalar" is a sigil-preceded entity so in your case perl thinks you're passing a scalar dereference which might not be clear enough of a message !.

    That's just an observation which I hope I can stand corrected and be clarified about.

    #replicating the Origianl Post (strictures on): my $coderef = sub {print "Hi There \n";}; sub doit(&){ &{$_[0]}; } doit($coderef); #accessing a code ref from within a subroutine #Without prototype-check disabling..
    #The same perl complaint is generated in the above code too C:\Documents and Settings\m>perl - sub testit{ print 'hi' };; sub doit (&) { $_[0]->() };; my $codeRef = \&testit;; doit( $codeRef );; __END__ Type of arg 1 to main::doit must be block or sub {} (not private varia +ble) at - line 4, near "$codeRef )" Execution of - aborted due to compilation errors.


    Excellence is an Endeavor of Persistence. Chance Favors a Prepared Mind.

      I didn't think that strictures or local versus global variables had, or could have any bearing on the matter. And in the great scheme of things it doesn't--other than the secondary diagnostic message.

      However, I think that your observation that the second part of the error message (not scalar dereference) (which I think is new from 5.10.0) is misleading, if not just plain wrong. In that what I was passing was a scalar containing a reference (to some code), not a dereference.

      But having seen the difference in the message you've received when the scalar containing the reference is a lexical, it suggests (perhaps), that the presence of the & prototype modifies what the code producing the message sees in some way.

      That is mildly confusing, but not hugely significant. As the messages identifying the source of the error are relatively new, perhaps they'll get honed as time goes on.


      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.
Re: The & prototype and code references in scalars.
by zentara (Archbishop) on Feb 18, 2010 at 13:35 UTC

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://823796]
Front-paged by keszler
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others cooling their heels in the Monastery: (1)
As of 2024-04-24 13:47 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found