Beefy Boxes and Bandwidth Generously Provided by pair Networks
go ahead... be a heretic
 
PerlMonks  

Lexical::Alias & subroutines

by Jenda (Abbot)
on May 19, 2003 at 12:15 UTC ( [id://259129]=perlquestion: print w/replies, xml ) Need Help??

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

I've tried to use Lexical::Alias 0.03 because I'd like to be able to do something like:

sub foo { alias $_[0] => my $byRef; ... $byRef += $result; }
but it seems Lexical::Alias doesn't work in subroutines. Is this a bug or the expected behaviour?
use strict; use warnings; use Lexical::Alias; my $orig = 1; my $alias = 99; alias $orig => $alias; print "$orig = $alias\n"; sub foo { my $orig = 1; my $alias = 99; alias $orig => $alias; print "foo(): $orig = $alias\n"; } foo();
prints:
1 = 1 foo(): 1 = 99
but I believe it should print:
1 = 1 foo(): 1 = 1

My Perl is

This is perl, v5.8.0 built for MSWin32-x86-multi-thread (with 1 registered patch, see perl -V for more detail) Copyright 1987-2002, Larry Wall Binary build 805 provided by ActiveState Corp. http://www.ActiveState. +com Built 18:08:02 Feb 4 2003
running under Win2k Server.

P.S.: IMHO, it would be better if the parameters to alias() were the other way around (I assign an alias to a variable, not a variable to an alias.) and if the alias was my()d automaticaly. So that I could write:

sub foo { alias $byRef => $_[0]; ...
I think this would make more sense.

Jenda
Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live.
   -- Rick Osborne

Replies are listed 'Best First'.
Re: Lexical::Alias & subroutines
by japhy (Canon) on May 19, 2003 at 13:41 UTC
    Someone else has pointed out this bug, too. I need to look at the source (the icky C source) to figure out what's wrong. It could be a bug... it probably has to do with the way I walk the pad in the module.

    As far as changing the order of the parameters, I suppose I could make the module take an argument of "v=a" (variable to alias) or "a=v" (alias to variable).

    As far as automagic my(), this is not a source filter, Jenda, it's merely an XS module that does some fancy footwork.

    Maybe I'll look at Variable::Alias... have you? Update: ick (sorry BrentDax)... that's just a tie-based module. It won't help me solve my problem.

    _____________________________________________________
    Jeff[japhy]Pinyan: Perl, regex, and perl hacker, who'd like a job (NYC-area)
    s++=END;++y(;-P)}y js++=;shajsj<++y(p-q)}?print:??;

      Thanks for the info :-)

      I should invest some time in learning about source filters and later try to create a filter on top of your module that would allow me to write this as much as I'd like it as possible :-)

      P.S.: It'd be cool if you found a way to bypass the error in Perl, but I'm afraid I can't help you in this. My C skills are minimal.

      Jenda
      Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live.
         -- Rick Osborne

      Edit by castaway: Closed small tag in signature

        Lexical::Alias 0.04 will be coming to CPAN shortly. Two tiny changes -- a $SWAP global you can set to 1 if you want to send the arguments to the functions in the reversed order you specified, and a note about the 5.8.0 bug.

        _____________________________________________________
        Jeff[japhy]Pinyan: Perl, regex, and perl hacker, who'd like a job (NYC-area)
        s++=END;++y(;-P)}y js++=;shajsj<++y(p-q)}?print:??;

Re: Lexical::Alias & subroutines
by japhy (Canon) on May 19, 2003 at 14:08 UTC
    It works in devperl 5.9.0, so I'm guessing it was a bug hidden deep with the bowels of Perl?

    _____________________________________________________
    Jeff[japhy]Pinyan: Perl, regex, and perl hacker, who'd like a job (NYC-area)
    s++=END;++y(;-P)}y js++=;shajsj<++y(p-q)}?print:??;

Re: Lexical::Alias & subroutines
by BrowserUk (Patriarch) on May 19, 2003 at 13:05 UTC

    Update: I'm blind, can't read. (Ignore the contents of this post other than to -- it.). I, as jd points out, completely screwed this one up.

    This is just a scoping issue. If you have a lexical at the outer scope and you declare a lexical at the inner scope (as in your example) the inner scope only sees the new version not the old. As you did the aliasing at the outer level and not the inner, the inner lexical isn't aliased. The outer will still be so once you return.

    You could either, not declare the inner lexicals of the same name, OR alias the inner copy of $alias to $orig, and you would get the results you are expecting.

    Like halley, I'm not quite sure why you would want to do this. $_[0] is already an alias for the first parameter passed. If that parameter is a reference, then using it as an lvalue will always affect the thing it refers to.

    If the idea is to give a meaningful name to the parameter without copying the reference (a very cheap operation anyway) then you could go with defining a constant

    use constant BYREF=>0; sub something{ $_[BYREF] = 1000 if $_[BYREF] > 1000; ... }

    The win is minimal unless the sub is being called zillions of times, but using a defined CONSTANT cost nothing at runtime and is much cheaper than allocating a lexical and then calling a sub to alias it to $_[0], which is much more expensive that just assigning the ref to an local-scope lexical.


    Examine what is said, not who speaks.
    "Efficiency is intelligent laziness." -David Dunham
    "When I'm working on a problem, I never think about beauty. I think only how to solve the problem. But when I have finished, if the solution is not beautiful, I know it is wrong." -Richard Buckminster Fuller
      This is just a scoping issue. If you have a lexical at the outer scope and you declare a lexical at the inner scope (as in your example) the inner scope only sees the new version not the old. As you did the aliasing at the outer level and not the inner, the inner lexical isn't aliased. The outer will still be so once you return.
      Nope, you're missing the point. He did exactly the same thing inside the sub as outside, independently... Yet it works outside the sub, but not inside. I agree that that is very unexpected behavior. I'd call it a bug.
      use Lexical::Alias; @a = (5); my $x = 1; alias($a[0],$x); print "$x\n"; # prints 5 sub foo { my $y = 2; alias($a[0],$y); print "$y\n"; # prints 2 } foo();

      jdporter
      The 6th Rule of Perl Club is -- There is no Rule #6.

      Of course it is possible to use the $_[CONST] (I do it myself from time to time), the problem is that the scope of the CONST is too wide. The constant is "global", defined in a package, so all subroutines in that package might use it, even if it doesn't make sense there. And if I had two functions that have the "conceptualy same" parameter on a different place I'd have to define two constants with similar names, which could be very confusing.

      Besides with the alias you can/could do something like

      sub foo { alias ($_[0] eq 'whatever' ? $_[1] : $_[2]) => my $x; ... }
      How's that written with constants?

      Another case when I'd love to have a lexical alias is when the function gets an array or hash reference, I do want to modify the array/hash, but do not like to have to dereference it all the time:

      sub foo { my ($aref) = @_; alias @$aref => my @ary; ... do something with @ary }
      You are right about the speed issues, but that's not the point. Readability is the main concern here.

      P.S.: Thinking about it some more. It's better that the alias() doesn't my() the variable.

      Jenda
      Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live.
         -- Rick Osborne

      Edit by castaway: Closed small tag in signature

        In your first example

        sub foo { my $x = $_[0] eq 'whatever' ? $_[1] : $_[2]; ... }

        Seems just as effective. But in your second, I agree. I've looked enviously at the perlsub examples of using globs to avoid the need to dereference refs and wished for a way to do the same thing with lexicals. Maybe Diotalevi's Lexical::TypeGlob would work for that? I haven't gotten around to playing with it yet.


        Examine what is said, not who speaks.
        "Efficiency is intelligent laziness." -David Dunham
        "When I'm working on a problem, I never think about beauty. I think only how to solve the problem. But when I have finished, if the solution is not beautiful, I know it is wrong." -Richard Buckminster Fuller
Re: Lexical::Alias & subroutines
by halley (Prior) on May 19, 2003 at 12:25 UTC
    Just curious, but why is the following so ugly that you would resort to making some kind of alias?
    sub foo { my $byRef = shift; ... }

    --
    [ e d @ h a l l e y . c c ]

      Shifting makes $byRef a copy of the variable passed to the sub. Jenda indicated he wants to modify the argument passed to the sub so he needs an alias. $_[0] is an alias but he'd like to work with it using a more friendly name.

      90% of every Perl application is already written.
      dragonchild

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others browsing the Monastery: (4)
As of 2024-04-24 06:43 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found