Beefy Boxes and Bandwidth Generously Provided by pair Networks
Do you know where your variables are?
 
PerlMonks  

Simple Pass By Reference

by tomazos (Deacon)
on Jul 25, 2005 at 23:50 UTC ( [id://478021]=perlquestion: print w/replies, xml ) Need Help??

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

This seems like something that should be simple, and I am most likely missing something.

I want to pass a my variable to a subrountine that then does something to it.

sub alter_var(???) { my $var_in_sub = ???; # alter $var_in_sub, eg $var_in_sub =~ s/a/b/g; } my $var_elsewhere = 'aaa'; alter_var($var_elsewhere); print $var_elsewhere; # should print 'bbb'

Any ideas as to what goes in the ??? bits? Essentially I want to make $var_in_sub an alias for $_[0].

Update: In the actual application the scalar is quite big, so I'd like to pass it by reference without copying the data.

I'd also like to use a meaningful name rather than $_[0] throughout the subroutine.

I'd also like to not have to reference (\$) and dereference ($$) all over the place.

I just want too much. :)

Lexical::Alias is what I want but I'm running 5.6.1, looks like 5.8.1+ is needed from the docs.

All bow to BrowserUK. Truly cool.

-Andrew.


Andrew Tomazos  |  andrew@tomazos.com  |  www.tomazos.com

Replies are listed 'Best First'.
Re: Simple Pass By Reference
by BrowserUk (Patriarch) on Jul 26, 2005 at 01:56 UTC

    Try this.

  • It uses a prototype to save you from explicitly taking a reference when you call the sub.
  • It assigns the reference to a localised glob to avoid the need for explicit dereferencing inside the sub.
  • It uses our to satisfy strict.

    Result: Efficient pass-by-reference without the pain of dereferencing.

    #! perl -slw use strict; sub modify (\$) { our $data; local *data = $_[ 0 ]; $data =~ s[this][that]g; return; } my $string = 'this & that;' x 10000; modify $string; print substr $string, 0, 24;

    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
    "Science is about questioning the status quo. Questioning authority".
    The "good enough" maybe good enough for the now, and perfection maybe unobtainable, but that should not preclude us from striving for perfection, when time, circumstance or desire allow.

      I would really drop the our and typeglob usage here. I feel like it's "overkill" for what [id://tomazos] is trying to do.

      The following is also an interesting solution, that is quite similar to [id://friedo]'s one, but uses prototype to move referencing backslash from main script into the function code.

      #!/usr/bin/perl use strict; use warnings; sub modify (\$) { my $string_ref = $_[0]; $$string_ref =~ s/a/x/g; } my $string = 'abc'; print "before `$string'\n"; # abc modify $string; print "after `$string'\n"; # xbc

      Anyway, probably it is best to leave the \ char inside the main script. In this way, it is immediately clear that you're passing a reference, and not the real scalar. In the latter case, you could be tempted to think that a return value is also expected from the modify() function, which actually is not.

        Sure, that's using referencing/dereferencing - which is fine, but I'd rather have a normal scalar name ($string rather than $$string_ref).

        In this example its trivial, but if you have a lot of variables around, its hard to keep track of whats a reference and whats not.

        -Andrew.


        Andrew Tomazos  |  andrew@tomazos.com  |  www.tomazos.com
Re: Simple Pass By Reference
by esskar (Deacon) on Jul 25, 2005 at 23:54 UTC
    sub alter_var { my $var_in_sub = $_[0]; $var_in_sub =~ s/a/b/g; $_[0] = $var_in_sub; } # or sub alter_var { $_[0] =~ s/a/b/g; }
      That duplicates the content of $_[0] doesn't it? (Your first example)

      I want to pass it by reference, and give it a meaningful identifier in the context of the subroutine. (ie not have to use $_[0] throughout the subroutine.) (Your second example)

      -Andrew.


      Andrew Tomazos  |  andrew@tomazos.com  |  www.tomazos.com
        You can use a simple scalar reference, then.

        sub alter_var { my $scalar_ref = shift; $$scalar_ref =~ s/a/b/; } my $scalar = "foobarbaz"; alter_var( \$scalar );

        For more, see perlreftut.

        Also note that esskar's second example, which works on $_[0] directly, will alter the scalar passed into the parameter list. (In this case, $_[0] is an alias, not a reference, so there is no need to dereference anything.)

Re: Simple Pass By Reference
by tlm (Prior) on Jul 26, 2005 at 04:02 UTC

    Pardon me for being so dense, but

    DB<1> sub altervar { $_[ 0 ] =~ s/a/b/g } DB<2> $var_elsewhere = 'aaa' DB<3> altervar( $var_elsewhere ) DB<4> p $var_elsewhere bbb
    This solution seems too trivial. What am I missing?

    Update: Thanks to BrowserUk++ for pointing out the requirement I missed.

    the lowliest monk

      From the OP's update:

      I'd also like to use a meaningful name rather than $_[0] throughout the subroutine.

      Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
      Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
      "Science is about questioning the status quo. Questioning authority".
      The "good enough" maybe good enough for the now, and perfection maybe unobtainable, but that should not preclude us from striving for perfection, when time, circumstance or desire allow.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others perusing the Monastery: (5)
As of 2024-04-20 01:01 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found