Passing literal with reference?

D

dorno

Passing variables to a subroutine by reference is covered in depth by any
of the books. Like this...

myroutine(\$var1, \@array1, \%hash1);

sub myroutine {
my($scalar, array, hash) = @_;
}

All the variables get to the subroutine intact and no problem.

But if I want to change the $scalar to a literal, like so.

myroutine("myvariable", \@array1, \%hash1);

It hoses the call and attaches the literal as a member of the array.

To make it work I have to...

my $var1 = "myvariable";
myroutine(\$var1, \@array1, \%hash1);

which takes it back to square one. No problem there, it works, but I was
wondering if there is a way to pass a bare literal with other references?
There has to be - in fact with Perl there is probably a dozen ways. But
my trying and reading hasn't found it yet. This is one of those things
that the more I try the behinder I get.

Thanks any

dorno
 
P

Paul Lalli

Passing variables to a subroutine by reference is
covered in depth by any of the books. Like this...

myroutine(\$var1, \@array1, \%hash1);

sub myroutine {
my($scalar, array, hash) = @_;

Presumably, you meant $array and $hash. . .
}

All the variables get to the subroutine intact and no problem.

But if I want to change the $scalar to a literal, like so.

myroutine("myvariable", \@array1, \%hash1);

It hoses the call and attaches the literal as a member of the array.

To make it work I have to...

my $var1 = "myvariable";
myroutine(\$var1, \@array1, \%hash1);

which takes it back to square one. No problem there, it works, but I was
wondering if there is a way to pass a bare literal with other references?
There has to be - in fact with Perl there is probably a dozen ways. But
my trying and reading hasn't found it yet. This is one of those things
that the more I try the behinder I get.

I do not believe you can create a reference to a literal, regardless
of what you want to do with it. I have to ask.... what are you
*trying* to do? That is, what problem are you trying to solve, the
solution to which you've decided is to pass a reference to a literal?

There are three usual reasons one passes a reference to a variable to
a subroutine, rather than the actual variable itself:
1) You wish to make changes to the variable within the subroutine, but
don't want to be stuck with difficult-to-interpet code like
$_[0] = 'newvalue';
2) The variable is a hash or array, and so will be "flattened" into @_
if it's passed directly, rendering you unable to use the actual hash/
array's values.
3) For efficiency, so you don't have to make a copy of a huge value
every time you call the subroutine.

In this case, (1) doesn't apply because you can't "change" a literal
anyway. (2) doesn't apply, because you're talking about a scalar
value. So the only thing I can think is that you're trying to gain an
imperceptable efficiency improvement by avoiding the copy of the
string. Is that correct?

Paul Lalli
 
P

Paul Lalli

Passing variables to a subroutine by reference is covered in depth by any
of the books. Like this...

myroutine(\$var1, \@array1, \%hash1);

sub myroutine {
my($scalar, array, hash) = @_;

}

All the variables get to the subroutine intact and no problem.

But if I want to change the $scalar to a literal, like so.

myroutine("myvariable", \@array1, \%hash1);

It hoses the call and attaches the literal as a member of the array.

I should have also asked: What do you mean by this? How is the call
"hosed"? How is it "attached as a member of the array"? If this is
your call, and your subroutine still starts out as:
my ($scalar, $array, $hash) = @_;
then $scalar has the value "myvariable", $array has a reference to
@array1, and $hash has a reference to $hash1.

What is the problem with this example?

Paul Lalli
 
D

dorno

Presumably, you meant $array and $hash. . .

Yep. A typo on my part. Comes from recreating a problem on my machine
at the office that is really happening on my PC at home.
I do not believe you can create a reference to a literal, regardless
of what you want to do with it. I have to ask.... what are you
*trying* to do? That is, what problem are you trying to solve, the
solution to which you've decided is to pass a reference to a literal?

I had a feeling that a literal couldn't be referenced. But... Perl has so
many ways to do stuff that I never imagined could be done that I was
hoping.

Anyway, if I can make my request somewhat more clear.

Passing \$var, \@array and \%hash keeps the entire batch from being
flattened. Works fine and they come out in the subroutine seperate and
ready to go.

But sometimes, instead of $var, I just want to pass a literal instead of
initalizing a variable and then passing that. In that case, the whole
batch is partially "flattened" with "literal" becoming part of whatever
is next in the parameter string, in this case @array. It isn't a show
stopper but is rather an inconvenience. A lot of times one of my calls
has multiple scalars and a single hash or array and the parameters never
change. So I either have to suck them out of the array they have been
flattened into, or build a my $var1, my $var2, etc and pass them that way.
Or put the scalars into an array and pass that properly.

The other problem is that if I code the subroutine to handle a referenced
set of parameters, a flattening of the parameters blows the code Unless I
test and handle both (or three, or four...) cases in which case the
handling routine usually would become more complex than the subroutine
itself.
value. So the only thing I can think is that you're trying to gain an
imperceptable efficiency improvement by avoiding the copy of the
string. Is that correct?

Not really efficiency in runtime, rather efficiency in reading the code
later. A glance at callroutine('Swords','Short','Bronze','100');
is easier to grasp than looking at
callroutine(\$table,\$size,\$type,\cost); then scrolling up to the
variable list and checking out what each parameter is supposed to be.

Actually, it is more along the lines of even though I have been using Perl for
several years in a simplistic mode (i.e. enough to make Linux work), I am
trying to actually learn how to code in Perl properly.

Thanks
dorno
 
P

Paul Lalli

Anyway, if I can make my request somewhat more clear.

Passing \$var, \@array and \%hash keeps the entire batch from being
flattened. Works fine and they come out in the subroutine seperate
and ready to go.

But sometimes, instead of $var, I just want to pass a literal
instead of initalizing a variable and then passing that. In that
case, the whole batch is partially "flattened" with "literal"
becoming part of whatever is next in the parameter string, in this
case @array.

No, it really really doesn't. Can you show an example where you think
this is happening? Here's my counter example:
$ perl -le'
sub myroutine {
my ($s, $a, $h) = @_;
print "Scalar: $s";
print "Array: @$a";
print "Hash: ", join (", ", map { "$_ => $h->{$_}" } keys %$h);
}

my @a = (1..5);
my %h = (a => 1, b => 2, c => 3, d => 4, e => 5);
myroutine("string", \@a, \%h);
'
Scalar: string
Array: 1 2 3 4 5
Hash: e => 5, c => 3, a => 1, b => 2, d => 4

Paul Lalli
 
G

Gunnar Hjalmarsson

Paul said:
I do not believe you can create a reference to a literal, regardless
of what you want to do with it.

Why do you say that? The code below prints "myvariable" just as I would
have expected:

sub myroutine {
my $ref = shift;
print $$ref;
}

myroutine( \'myvariable' );
 
P

Paul Lalli

Why do you say that? The code below prints "myvariable" just as I would
have expected:

sub myroutine {
my $ref = shift;
print $$ref;
}

myroutine( \'myvariable' );

..... and I stand humbly corrected.

Thanks, Gunnar.

Paul Lalli
 
D

Dr.Ruud

dorno schreef:
Passing variables to a subroutine by reference is covered in depth by
any of the books. Like this...

myroutine(\$var1, \@array1, \%hash1);

The \$var1 is somewhat exceptional, normally you just do

myroutine( $var1, \@array1, \%hash1);



For example:

$ perl -Mstrict -wle'
sub f {$_[0] = reverse $_[0]}
my $x = q(abc);
f $x; # changes $x
print $x;
f q{xyz};
'
cba
Modification of a read-only value attempted at -e line 2.
 
P

Paul Lalli

That did it.

My problem was that I was always using double quotes,
myroutine(\"myvariable");

There is no difference in this case between single and double quotes.
They do the exact same thing. To illustrate:
#!/usr/bin/env perl
use strict;
use warnings;
myroutine(\'foobar');
myroutine(\"foobar");
sub myroutine {
my $ref = shift;
print $$ref . "\n";
}
__END__
foobar
foobar
I didn't think to try single quotes, but...
The Programming Perl, Perl Cookbook, and others all use double
quotes in their examples. Not as an example of referencing a
literal, but as a way to pass a literal.

Do you understand the difference between double and single quotes?
Double quotes interpolate variables and character escapes. Single
quotes do not. That's it.
Now that I know the answer, I still have not found an example
in all my Perl books. Apparently passing a literal reference
in a mixed string of parameters is not done by Perl gurus.

It's not done for the reason you keep trying to do, because as I'm now
stating for the third time in this thread, the problem you keep trying
to solve does not exist. Passing a literal directly into a subroutine
does not cause it to magically get attached to any subsequent value
passed in. You still have not showed any example of code where you
think this is happening.

Paul Lalli
 
D

Dr.Ruud

dorno schreef:
I still have not found an example in all
my Perl books. Apparently passing a literal reference in a mixed
string of parameters is not done by Perl gurus. Or else they
consider it so simple that no verbage need be wasted on the topic.

I remember there are some places in the Perl documentation where
references to a literal are mentioned. For example as a way to define
PI, or the size of an IO-buffer.
 
B

Brad Baxter

Anyway, if I can make my request somewhat more clear.

Passing \$var, \@array and \%hash keeps the entire batch from being
flattened.

No, passing references keeps hashes and arrays from being flattened.
A scalar, be it a reference or not, will not be "flattened" any
further.
So just pass the darn scalar. :)

show_me( "Hello", [ "cruel" ], { 'world' => '.' } );
sub show_me {
my( $scalar, $aref, $href ) = @_;
print "$scalar, $aref->[0] ", %$href, "\n";
}
The other problem is that if I code the subroutine to handle a referenced
set of parameters, a flattening of the parameters blows the code Unless I
test and handle both (or three, or four...) cases in which case the
handling routine usually would become more complex than the subroutine
itself.

You're trying too hard. :)
 
M

Mirco Wahab

Brad said:
No, passing references keeps hashes and arrays from being flattened.
A scalar, be it a reference or not, will not be "flattened" any
further.
So just pass the darn scalar. :)

What if the "scalar" is, say 316,21 MB in size?
Would you still send it down to subroutines 'as it is'?

Regards

M.
 
P

Peter Makholm

Mirco Wahab said:
What if the "scalar" is, say 316,21 MB in size?
Would you still send it down to subroutines 'as it is'?

Yes, I think so.

From 'perldoc perlsub':

Any arguments passed in show up in the array @_. Therefore, if you
called a function with two arguments, those would be stored in $_[0]
and $_[1]. The array @_ is a local array, but its elements are aliases
for the actual scalar parameters. In particular, if an element $_[0]
is updated, the corresponding argument is updated (or an error occurs
if it is not updatable).

So Perl actually uses call-by-reference already. Of course the
standard idioms copies the values to new variables.

//Makholm
 
B

Brad Baxter

What if the "scalar" is, say 316,21 MB in size?
Would you still send it down to subroutines 'as it is'?

Would I? If I knew it would be that big, no. But the OP is,
I think, dealing with a different conundrum, e.g., he says,

"But sometimes, instead of $var, I just want to pass a literal instead
of
initalizing a variable and then passing that."

It is unlikely that he is planning to pass a 316 MB literal.
So I say again, just pass the darn thing. I will go out on
a limb and venture to say that the number of times a scalar
is passed to a subroutine vs. the number of times a reference
to a scalar is passed is about, oh, 1_000_000_000:1

Give or take.
 
U

Uri Guttman

BB> It is unlikely that he is planning to pass a 316 MB literal.
BB> So I say again, just pass the darn thing. I will go out on
BB> a limb and venture to say that the number of times a scalar
BB> is passed to a subroutine vs. the number of times a reference
BB> to a scalar is passed is about, oh, 1_000_000_000:1

BB> Give or take.

ever realize that perl objects are references and are always passed to
methods? i think that evens out the ratio a bit. and it isn't how often
a scalar is passed around but how often large ones are passed. in one
system of mine, i generally pass around scalar refs since that data may
get copied from @_ and passed around even more. it makes sense to pass
scalar refs then to keep the copying overhead to a minumum.

uri
 
B

Brad Baxter

BB> It is unlikely that he is planning to pass a 316 MB literal.
BB> So I say again, just pass the darn thing. I will go out on
BB> a limb and venture to say that the number of times a scalar
BB> is passed to a subroutine vs. the number of times a reference
BB> to a scalar is passed is about, oh, 1_000_000_000:1

BB> Give or take.

ever realize that perl objects are references and are always passed to
methods? i think that evens out the ratio a bit. and it isn't how often
a scalar is passed around but how often large ones are passed. in one
system of mine, i generally pass around scalar refs since that data may
get copied from @_ and passed around even more. it makes sense to pass
scalar refs then to keep the copying overhead to a minumum.

Yes, I do realize that about objects, and I expected someone to
mention it.
However, I suspect that many more of those are references to hashes,
arrays
or whatnot than are references to scalars, so I don't really think it
evens
out the ratio much. (The "ratio" being, of course a figment for
expression
purposes. :)) I don't doubt for a minute that many people pass
references
to scalars when it makes sense to do so. But I still believe that far
and
away, simple scalars are passed more than anything else. I didn't
think it
was that debatable. :) In particular, when was the last time
(outside of
this thread) that you saw someone pass a literal as \"Hello, world?"
 
U

Uri Guttman

BB> Yes, I do realize that about objects, and I expected someone to
BB> mention it. However, I suspect that many more of those are
BB> references to hashes, arrays or whatnot than are references to
BB> scalars, so I don't really think it evens out the ratio much.
BB> (The "ratio" being, of course a figment for expression
BB> purposes. :)) I don't doubt for a minute that many people pass
BB> references to scalars when it makes sense to do so. But I still
BB> believe that far and away, simple scalars are passed more than
BB> anything else. I didn't think it was that debatable. :) In
BB> particular, when was the last time (outside of this thread) that
BB> you saw someone pass a literal as \"Hello, world?"

i have done it. not often but i did know it worked and was surprised to
see someone here claim it didn't. the problem with references to
literals is that the data is readonly and can blow up if the sub tries
to modify it.

uri
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top