@_ aliasing

M

Matija Papec

Is there a perl version which prints 5 in case when,
perl -le 'sub f {my $a = shift; $a=5} f(my $b=1); print $b'

I was almost sure that shift() should not break the aliasing.
 
B

Bart Van der Donck

Matija said:
Is there a perl version which prints 5 in case when,
perl -le 'sub f {my $a = shift; $a=5} f(my $b=1); print $b'
I was almost sure that shift() should not break the aliasing.

perl -le "sub f { $_=5 for shift } f(my $b=1); print $b"

should do.
 
P

Paul Lalli

Matija said:
Is there a perl version which prints 5 in case when,
perl -le 'sub f {my $a = shift; $a=5} f(my $b=1); print $b'

I can't imagine why such a thing would happen.
I was almost sure that shift() should not break the aliasing.

shift() isn't breaking any aliasing. @_ is aliased to the arguments of
f().
`my $a = shift;` says to remove the first element of @_ and return a
copy of it. This is no different than if you had said
my $a = $_[0];
$_[0] is an alias to the first argument of f(). $a is not. The only
difference between this and your statement is that your statement also
has the effect of removing the first element of @_.

If you want to change the argument to f(), change it directly:
$_[0] = 5;

Paul Lalli
 
X

xhoster

Matija Papec said:
Is there a perl version which prints 5 in case when,
perl -le 'sub f {my $a = shift; $a=5} f(my $b=1); print $b'

I was almost sure that shift() should not break the aliasing.

It is the assignment, not the shift, which is breaking the aliasing.

Xho
 
M

Matija Papec

X-Ftn-To: Paul Lalli

Paul Lalli said:
I was almost sure that shift() should not break the aliasing.

shift() isn't breaking any aliasing. @_ is aliased to the arguments of
f().
`my $a = shift;` says to remove the first element of @_ and return a
copy of it. This is no different than if you had said
my $a = $_[0];
$_[0] is an alias to the first argument of f(). $a is not. The only
difference between this and your statement is that your statement also
has the effect of removing the first element of @_.

If you want to change the argument to f(), change it directly:
$_[0] = 5;

Yes, no doubt about that, but I think that I've read somewhere how shift
keeps the "magic" when operating on @_.

btw, Bart showed something interesting,
perl -le "sub f { $_=5 for shift } f(my $b=1); print $b"

should be doing the same thing as,
perl -le "sub f { $_=5 for map $_, shift } f(my $b=1); print $b"

but it doesn't?
 
P

Paul Lalli

Matija said:
X-Ftn-To: Paul Lalli

Paul Lalli said:
If you want to change the argument to f(), change it directly:
$_[0] = 5;

Yes, no doubt about that, but I think that I've read somewhere how shift
keeps the "magic" when operating on @_.

Well, since your expected results clearly do not mesh with reality, it
would seem that either 1) What you read was incorrect, or 2) You are
misremembering or misunderstanding what you read. If you manage to
find the citation you're talking about, please feel free to post it
here for our examination...
btw, Bart showed something interesting,
perl -le "sub f { $_=5 for shift } f(my $b=1); print $b"

should be doing the same thing as,
perl -le "sub f { $_=5 for map $_, shift } f(my $b=1); print $b"

but it doesn't?

I don't understand why you're assuming they *should* do the same thing.
Let's stop using shortcuts and spell each of these out:
sub f {
foreach (shift @_){
$_ = 5;
}
}
In this one, $_ is an alias to each element of the list that foreach
iterates over. @_ contains a list of aliases to f()'s arguments.
shift() remove and returns the first element of @_. So the list that
foreach iterates over is the first element of @_. Therefore, $_ is an
alias to an alias to the first argument of f().

sub f {
foreach (map { $_ } shift @_) {
$_ = 5;
}
}

In this one, foreach is not iterating over the first element of @_.
Instead, you're using map() to generate a new list, which will be
composed of the values passed to it. Within the map block itself, $_
is an alias to the first element of @_. The list that map returns
however, is not an alias. It is this list that foreach is iterating
over.

Paul Lalli
 
M

Matija Papec

I don't understand why you're assuming they *should* do the same thing.
Let's stop using shortcuts and spell each of these out:
sub f {
foreach (shift @_){
$_ = 5;
}
}
In this one, $_ is an alias to each element of the list that foreach
iterates over.
ok.

@_ contains a list of aliases to f()'s arguments.
shift() remove and returns the first element of @_. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
ok.

So the list that
foreach iterates over is the first element of @_.

How so? Doesn't foreach iterate over already shifted value which was
previously _removed_ from @_?
IMO, if it's removed from @_, it doesn't belong to @_ anymore..? :)
sub f {
foreach (map { $_ } shift @_) {
$_ = 5;
}
}

In this one, foreach is not iterating over the first element of @_.

Yes, it does not iterate over @_; I wrote it as the more obvious
example of non @_ aliasing.
 
M

Matija Papec

Or possibly the magic of shift() you mean is that, at package
scope, it operates on @ARGV by default, but inside a sub, it
defaults to @_.

It could be, but that was a few years ago and my memory isn't doing me
the justice.
 
E

Eric Schwartz

Matija Papec said:
How so? Doesn't foreach iterate over already shifted value which was
previously _removed_ from @_?

Yes. Think of it this way: @_ an array of aliases. You can change @_
all you want, but its contents are still aliases. If you remove an
alias from @_, then you can still assign to it, and change the
original variable.

The tricky bit comes when you do

my $var = shift;

That assigns a *copy* of the first element of @_ to $var. So the
thing you assigned to $var is an alias, but $var is not.
IMO, if it's removed from @_, it doesn't belong to @_ anymore..? :)

But it did when the sub was called, and that's what matters.

-=Eric
 
M

Matija Papec

X-Ftn-To: Eric Schwartz

Eric Schwartz said:
Yes. Think of it this way: @_ an array of aliases. You can change @_
all you want, but its contents are still aliases. If you remove an
alias from @_, then you can still assign to it, and change the
original variable.

The tricky bit comes when you do

my $var = shift;

That assigns a *copy* of the first element of @_ to $var. So the
thing you assigned to $var is an alias, but $var is not.

Thanks, that makes sense. So the assignment actually breaks the "magic" as
Xho already pointed out.
 

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

Similar Threads

Code was not Working Please Help 1
MultiThreading 1
Minimum Total Difficulty 0
Command Line Arguments 0
Translater + module + tkinter 1
Mutability issue 1
My Status, Ciphertext 2
Python battle game help 2

Members online

No members online now.

Forum statistics

Threads
473,756
Messages
2,569,540
Members
45,025
Latest member
KetoRushACVFitness

Latest Threads

Top