in reply to Half-serious quest for prefix anonymous refs taking

This looks like a job for prototypes. No, really :).

use strict; use warnings; use Data::Dumper; sub mkcref (@) { my @closed = @_; return sub { @closed}; } sub mkaref (@) { return [@_]; } sub mkhref (%) { if ( @_%2 ) { warn "Odd number of elements in mkhref"; return { @_, undef }; } else { return {@_}; } } my $foo = mkaref 1,2,3,qw(a b c); print Dumper $foo; my $bar = mkhref a => 1, b => 2, 3; print Dumper $bar;

I left it off mksref, because I wasn't sure how it should behave. It's an odd one.


TGI says moo

Replies are listed 'Best First'.
Re^2: Half-serious quest for prefix anonymous refs taking
by blazar (Canon) on May 30, 2008 at 09:37 UTC
    I left it off mksref, because I wasn't sure how it should behave. It's an odd one.

    I personally believe it should either complain if anything but exactly one argument is passed to it, or try to do something smart in that case, as I tried to, in my example. Another possibility would have been for it to return \[@_] but that would leave with two levels of indirection which is not consistent with the one argument case; further, it would amount to mksref mkaref LIST, so it doesn't make much sense.

    Another possibility that springs to mind is the following: if there were an anonymous (circumfix) scalar ref constructor, it would impose scalar context to its arguments. Thus it should behave as follows:

    sub mksref { my $x = +(@_)[-1]; \$x }
    This looks like a job for prototypes. No, really :).

    I can't see how prototypes could help there:

    sub mkcref (@) { my @closed = @_; return sub { @closed}; } sub mkaref (@) { return [@_]; }

    The @ prototype does not do anything useful, since it just says that the arguments are an arbitrary list, which is the default anyway.

    sub mkhref (%) { if ( @_%2 ) { warn "Odd number of elements in mkhref"; return { @_, undef }; } else { return {@_}; } }

    There's not a % prototype that I know of. There's a \% one which does something entirely different. If there were I believe it should simply do the evenness check you're doing yourself.

    Said this, my own version of mkhref() did something different: took a list and returned a hashref with the elements of that list as keys, and undef values. Given that these subs are supposed to be prefix alternatives to the circumfix [ ], { } and sub { } constructors, and to the non existant scalar ref one, my sub is certainly stupid and yours does the Right Thing™. But in the same vein, I would leave to perl to do its job of checking (if warnings are enabled) evennes:

    sub mkhref { {@_} }
    --
    If you can't understand the incipit, then please check the IPB Campaign.

      Update: As blazar so kindly pointed out, the (@) prototype is indeed meaningless. It just goes to show how useful it is to reread the docs every once in a while. I'd filed away the fact that prototypes let you do cool stuff and omit parens. Which they do, but not in the way that I understood it at the time I first read the docs.

      Reread the docs from time to time. It's amazing what you can learn!

      Back to my regularly scheduled foolishness...


      The % and @ prototypes do the same thing--eat an entire list. Your suggestion that it should check for evenness is very good. It's in my battered old copy of Perl in a Nutshell, it works, but I don't see it in perlsub--interesting...

      I used the % prototype despite its identicalness with @ just to clearly show my intentions--that is mkhref wants a hash. I'm not sure about that decision now, since it turns out to be a partially documented feature :).

      The prototypes allow you to skip your parentheses, which makes the sub act more like a built-in. Since you said you wanted a built-in, I thought I'd fake it as well as can be done.

      mkaref( 1..9 ); # becomes mkaref 1..9;

      In a module, I'd have mkhref check for warnings, with $^W. If on, it should carp, that way the error refers to the "right" line of code.

      sub mkhref (%) { if ( @_%2 ) { carp "Odd number of elements in mkhref" if $^W; return { @_, undef }; } else { return {@_}; } }


      TGI says moo

        The prototypes allow you to skip your parentheses, which makes the sub act more like a built-in. Since you said you wanted a built-in, I thought I'd fake it as well as can be done.

        I personally believe you'll find that you don't need prototypes at all, to allow one to skip parens:

        However I did hope it was clear enough that my "quest" is not for builtin (looking) functions, because in that case I can write them myself full well, but for builtin (hypothetical) syntax.

        --
        If you can't understand the incipit, then please check the IPB Campaign.