Prototypes and anonymous subroutines

Discussion in 'Perl Misc' started by Brad Baxter, May 31, 2007.

  1. Brad Baxter

    Brad Baxter Guest

    In the synopsis of perlsub, it says the following:

    To define an anonymous subroutine at runtime:

    $subref = sub BLOCK; # no proto
    $subref = sub (PROTO) BLOCK; # with proto
    $subref = sub : ATTRS BLOCK; # with attributes
    $subref = sub (PROTO) : ATTRS BLOCK; # with proto and
    attributes

    Then later is this:

    Prototypes

    Perl supports a very limited kind of compile-time argument
    checking using function prototyping. If you declare

    sub mypush (\@@)

    then "mypush()" takes arguments exactly like "push()"
    does. The function declaration must be visible at compile
    time. The prototype affects only interpretation of new-
    style calls to the function, where new-style is defined as
    not using the "&" character. In other words, if you call
    it like a built-in function, then it behaves like a built-
    in function. If you call it like an old-fashioned subrou-
    tine, then it behaves like an old-fashioned subroutine.
    It naturally falls out from this rule that prototypes have
    no influence on subroutine references like "\&foo" or on
    indirect subroutine calls like "&{$subref}" or "$sub-
    ref->()".

    That last sentence seems somewhat contradictory to the
    synopsis, because if prototypes have no influence on indirect
    subroutine calls, then why be able to define them for anonymous
    subroutines? For example:

    > perl -le'sub n($$){print@_};n(1,2)'

    12
    .... as expected

    > perl -le'sub n($){print@_};n(1,2)'

    Too many arguments for main::n at -e line 1, at end of line
    .... as expected

    > perl -le'$an=sub ($$){print@_};$an->(1,2)'

    12
    .... as expected

    > perl -le'$an=sub ($){print@_};$an->(1,2)'

    12
    .... expected an error, but prototype ignored?

    > perl -le'sub n(\@){print$_[0][0]};n([1,2])'

    Type of arg 1 to main::n must be array (not single ref constructor) at
    -e line 1, at end of line
    .... as expected

    > perl -le'$an=sub (\@){print$_[0][0]};$an->([1,2])'

    1
    .... prototype ignored


    So a couple of questions:

    1. If prototypes are ignored for anonymous subroutines,
    why be able to define them?

    2. Am I missing a calling convention that does not ignore
    them?

    --
    Brad
     
    Brad Baxter, May 31, 2007
    #1
    1. Advertising

  2. Brad Baxter

    Greg Bacon Guest

    In article <>,
    Brad Baxter <> wrote:

    : So a couple of questions:
    :
    : 1. If prototypes are ignored for anonymous subroutines,
    : why be able to define them?

    You can make them work (see below), but maybe it was a speculative
    development path that deadended.

    : 2. Am I missing a calling convention that does not ignore
    : them?

    It's ugly, but consider

    $ perl -le 'BEGIN { *n = sub ($) { print @_ } } n(1,2)'
    Too many arguments for main::n at -e line 1, at end of line
    Execution of -e aborted due to compilation errors.

    Greg
    --
    I couldn't believe it. My book was used to define the ultimate geek, and
    suddenly my son thinks I'm really cool.
    -- W. Richard Stevens on Garth carrying UNP in Wayne's World
     
    Greg Bacon, May 31, 2007
    #2
    1. Advertising

  3. On May 31, 9:27 am, (Greg Bacon) wrote:
    > In article <>,
    > Brad Baxter <> wrote:
    >
    > : So a couple of questions:
    > :
    > : 1. If prototypes are ignored for anonymous subroutines,
    > : why be able to define them?


    Why bother defining them?

    > : 2. Am I missing a calling convention that does not ignore
    > : them?


    I believe it it because prototyping is a compile time feature. The
    anonymous subroutines examples you provided are assignment statements,
    and therefore get evaluated at runtime.
     
    Skye Shaw!@#$, May 31, 2007
    #3
  4. On May 31, 9:27 am, (Greg Bacon) wrote:
    > In article <>,
    > Brad Baxter <> wrote:
    >
    > : So a couple of questions:
    > :
    > : 1. If prototypes are ignored for anonymous subroutines,
    > : why be able to define them?
    >
    > You can make them work (see below), but maybe it was a speculative
    > development path that deadended.
    >
    > : 2. Am I missing a calling convention that does not ignore
    > : them?
    >
    > It's ugly, but consider
    >
    > $ perl -le 'BEGIN { *n = sub ($) { print @_ } } n(1,2)'
    > Too many arguments for main::n at -e line 1, at end of line
    > Execution of -e aborted due to compilation errors.
    >


    Hummm... BEGIN{} forces compile time evaluation, so the prototype is
    evaluated in this case.
     
    Skye Shaw!@#$, May 31, 2007
    #4
  5. Brad Baxter

    Brad Baxter Guest

    On May 31, 12:27 pm, (Greg Bacon) wrote:
    > In article <>,
    > Brad Baxter <> wrote:
    >
    > : So a couple of questions:
    > :
    > : 1. If prototypes are ignored for anonymous subroutines,
    > : why be able to define them?
    >
    > You can make them work (see below), but maybe it was a speculative
    > development path that deadended.
    >
    > : 2. Am I missing a calling convention that does not ignore
    > : them?
    >
    > It's ugly, but consider
    >
    > $ perl -le 'BEGIN { *n = sub ($) { print @_ } } n(1,2)'
    > Too many arguments for main::n at -e line 1, at end of line
    > Execution of -e aborted due to compilation errors.


    Ah, very interesting. Carried further (for no reason other than
    curiosity), I see

    > perl -le 'BEGIN { $an = sub ($) { print @_ }; *n=\&$an } n(1,2)'

    Too many arguments for main::n at -e line 1, at end of line
    Execution of -e aborted due to compilation errors.

    > perl -le 'BEGIN { $an = sub ($) { print @_ } } *n=\&$an; n(1,2)'

    12

    --
    Brad
     
    Brad Baxter, May 31, 2007
    #5
  6. Brad Baxter

    Brad Baxter Guest

    On May 31, 1:02 pm, "Skye Shaw!@#$" <> wrote:
    > On May 31, 9:27 am, (Greg Bacon) wrote:
    >
    > > In article <>,
    > > Brad Baxter <> wrote:

    >
    > > : So a couple of questions:
    > > :
    > > : 1. If prototypes are ignored for anonymous subroutines,
    > > : why be able to define them?

    >
    > Why bother defining them?


    Why bother documenting them? :)

    Which was the point I was working around to: if it's not
    a feature that can be reasonably used, perhaps it shouldn't
    be quite so prominently featured in the docs. As Greg
    mentioned, it may have been intended to work more simply
    for anonymous subs, but then dropped.

    Cheers,

    --
    Brad
     
    Brad Baxter, May 31, 2007
    #6
  7. Brad Baxter

    Brad Baxter Guest

    On May 31, 2:21 pm, Brad Baxter <> wrote:
    > > perl -le 'BEGIN { $an = sub ($) { print @_ }; *n=\&$an } n(1,2)'

    >
    > Too many arguments for main::n at -e line 1, at end of line
    > Execution of -e aborted due to compilation errors.
    >
    > > perl -le 'BEGIN { $an = sub ($) { print @_ } } *n=\&$an; n(1,2)'

    >
    > 12


    Of course, I meant:

    > perl -le 'my $an; BEGIN { $an = sub ($) { print @_ }; *n=$an } n(1,2)'

    Too many arguments for main::n at -e line 1, at end of line
    > perl -le 'my $an;BEGIN { $an = sub ($) { print @_ } } *n=$an; n(1,2)'

    12

    --
    Brad
     
    Brad Baxter, May 31, 2007
    #7
  8. On May 31, 5:27 pm, (Greg Bacon) wrote:
    > In article <>,
    > Brad Baxter <> wrote:
    >
    > : So a couple of questions:
    > :
    > : 1. If prototypes are ignored for anonymous subroutines,
    > : why be able to define them?
    >
    > You can make them work (see below), but maybe it was a speculative
    > development path that deadended.
    >
    > : 2. Am I missing a calling convention that does not ignore
    > : them?
    >
    > It's ugly, but consider
    >
    > $ perl -le 'BEGIN { *n = sub ($) { print @_ } } n(1,2)'
    > Too many arguments for main::n at -e line 1, at end of line
    > Execution of -e aborted due to compilation errors.


    Have encountered obscure edge cases where I've used this sort of
    thing. But they are rare.

    I've also abused prototypes (in a similar way to the way sort() does)
    as a poor-man's metadata by using the explicit prototype() function.
    For an example see String::Interpolate.
     
    Brian McCauley, May 31, 2007
    #8
  9. On May 31, 7:26 pm, Brad Baxter <> wrote:
    > On May 31, 1:02 pm, "Skye Shaw!@#$" <> wrote:
    >
    > > On May 31, 9:27 am, (Greg Bacon) wrote:

    >
    > > > In article <>,
    > > > Brad Baxter <> wrote:

    >
    > > > : So a couple of questions:
    > > > :
    > > > : 1. If prototypes are ignored for anonymous subroutines,
    > > > : why be able to define them?

    >
    > > Why bother defining them?

    >
    > Why bother documenting them? :)


    Because undocumented features a bad.
     
    Brian McCauley, May 31, 2007
    #9
  10. Brad Baxter

    Brad Baxter Guest

    On May 31, 5:47 pm, Brian McCauley <> wrote:
    > On May 31, 5:27 pm, (Greg Bacon) wrote:
    >
    >
    >
    > > In article <>,
    > > Brad Baxter <> wrote:

    >
    > > : So a couple of questions:
    > > :
    > > : 1. If prototypes are ignored for anonymous subroutines,
    > > : why be able to define them?

    >
    > > You can make them work (see below), but maybe it was a speculative
    > > development path that deadended.

    >
    > > : 2. Am I missing a calling convention that does not ignore
    > > : them?

    >
    > > It's ugly, but consider

    >
    > > $ perl -le 'BEGIN { *n = sub ($) { print @_ } } n(1,2)'
    > > Too many arguments for main::n at -e line 1, at end of line
    > > Execution of -e aborted due to compilation errors.

    >
    > Have encountered obscure edge cases where I've used this sort of
    > thing. But they are rare.
    >
    > I've also abused prototypes (in a similar way to the way sort() does)
    > as a poor-man's metadata by using the explicit prototype() function.
    > For an example see String::Interpolate.


    Fair enough. Thanks.

    --
    Brad
     
    Brad Baxter, Jun 1, 2007
    #10
  11. Brad Baxter

    Uri Guttman Guest

    >>>>> "GB" == Greg Bacon <> writes:

    GB> In article <>,
    GB> Brad Baxter <> wrote:

    GB> : So a couple of questions:
    GB> :
    GB> : 1. If prototypes are ignored for anonymous subroutines,
    GB> : why be able to define them?

    GB> You can make them work (see below), but maybe it was a speculative
    GB> development path that deadended.

    GB> : 2. Am I missing a calling convention that does not ignore
    GB> : them?

    GB> It's ugly, but consider

    GB> $ perl -le 'BEGIN { *n = sub ($) { print @_ } } n(1,2)'
    GB> Too many arguments for main::n at -e line 1, at end of line
    GB> Execution of -e aborted due to compilation errors.

    that can be done with a module and use as well. asssigning a code ref to
    a type glob is how exporting is done in general. and the prototype is
    available to the compiler from the use point onward to end of file. this
    is how exported subs with code blocks for an arg work as do others that
    take only 1 arg as you showed above. it is one of the few cases where
    prototypes are useful.

    uri

    --
    Uri Guttman ------ -------- http://www.stemsystems.com
    --Perl Consulting, Stem Development, Systems Architecture, Design and Coding-
    Search or Offer Perl Jobs ---------------------------- http://jobs.perl.org
     
    Uri Guttman, Jun 2, 2007
    #11
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Reporter
    Replies:
    3
    Views:
    485
    Mike Schilling
    May 12, 2007
  2. Arne Gödeke

    creating anonymous subroutines at runtime

    Arne Gödeke, Aug 25, 2004, in forum: Perl Misc
    Replies:
    15
    Views:
    183
    Anno Siegel
    Aug 26, 2004
  3. Replies:
    1
    Views:
    228
  4. Replies:
    29
    Views:
    216
  5. Replies:
    0
    Views:
    88
Loading...

Share This Page