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

Someone I work with started using the following "idiom" for passing arguments into a hash reference. He declared a hash reference and dereferences it within the "my" statement.
use strict; sub odd_args { my($this, %$args) = @_; print $args->{x},"\n"; } odd_args(1, x => 2);

I don't think he should have done it that way, but strangely enough, it worked in perl 5.6.1. It fails in perl 5.8.0.

% perl5.6.1 qqq.pl 2 % /usr/local/bin/perl5.8.0 qqq.pl Can't declare hash dereference in my at qqq.pl line 4, near ") =" Execution of qqq.pl aborted due to compilation errors.

Does anyone know what happened between perl 5.6.1 to open and then close this loophole?

Replies are listed 'Best First'.
Re: Arg passing trick that fails in perl 5.8
by Abigail-II (Bishop) on Jan 10, 2003 at 18:02 UTC
    It's called a bug fix. From the Changes file:
    [ 13881] By: jhi on 2001/12/24 23:4 +7:53 Log: Subject: PATCH: Restore "Can't declare scalar dereference + in my" error From: Mark-Jason Dominus <mjd@plover.com> Date: Mon, 24 Dec 2001 18:14:48 -0500 Message-ID: <20011224231448.25826.qmail@plover.com> Branch: perl ! op.c t/op/eval.t

    This construct only worked from 5.005_62 until 5.7.2.

    Abigail

Re: Arg passing trick that fails in perl 5.8
by tadman (Prior) on Jan 10, 2003 at 15:51 UTC
    That is really odd, because it should be one or the other, but not both. For example:
    sub odd_args { my ($this, $args) = @_; print $args->{x},$/; } sub odd_args { my ($this, %args) = @_; print $args{x},$/; }
    Are you sure there wasn't a prototype?

    Update: As pfaut pointed out, this seems to be some kind of automatic casting that 5.6.1 could do, though I can see why this "feature" was removed.

      Is there any reason for the args to be created as a reference to a hash? If you just want to get at your arguments by name, it should just use a hash. There's no reason to use a reference. In this case, tadman's second option would be correct but that requires more changes to your code to remove the '->' dereference on all argument accesses.

      --- print map { my ($m)=1<<hex($_)&11?' ':''; $m.=substr('AHJPacehklnorstu',hex($_),1) } split //,'2fde0abe76c36c914586c';
      Are you sure there wasn't a prototype?

      There was no prototype. The sample code worked exactly as shown. I briefly considered using a prototype as a fix, but it wouldn't work. A reference prototype requires that you use a real "%" in the argument list and then converts that to a reference in the subroutine.

Re: Arg passing trick that fails in perl 5.8
by pfaut (Priest) on Jan 10, 2003 at 15:51 UTC

    Try splitting the declaration and assignment onto two lines.

    sub odd_args { my($this, $args); ($this, %$args) = @_; print $args->{x},"\n"; }

    This still works on 5.6.1 and I think should get around the problem on 5.8 although I can't test it.

    --- print map { my ($m)=1<<hex($_)&11?' ':''; $m.=substr('AHJPacehklnorstu',hex($_),1) } split //,'2fde0abe76c36c914586c';
Re: Arg passing trick that fails in perl 5.8
by pg (Canon) on Jan 12, 2003 at 01:33 UTC
    Very interesting observation, and this is actually documented in 5.8.1 perldelta.

    They were saying that this is actually a feature in earlier versions, but some sort of lost in 5.6.1 (at least in 5.6.1, but also could be in other versions around that time frame). Now they got it back for us :-)

    If you are interested in checking, go 5.8.1 perldelta, looking for "can't declare".
Re: Arg passing trick that fails in perl 5.8
by Aristotle (Chancellor) on Jan 12, 2003 at 02:08 UTC
    As pfaut hinted at - what's the problem with using a simple hash?
    sub not_at_all_odd_args { my($this, %args) = @_; print $args{x},"\n"; }
    This will work the same on any version of Perl 5.

    Makeshifts last the longest.

      There is nothing wrong with a simple hash in my book, but this particular programmer has developed a style where he will never use a simple hash or array when he can use a reference instead. He thinks it simplifies the syntax.