value or reference inside foreach <expr>?

T

Todd

Hi,

I've met some questions regarding the copy @array or reference inside
for <expr>:

In the code snippets blow, 2 strange cases are using @array copies
rather than modifying original ones:

case5: sub foo1 (\@) { ++$_ for @$_[0] }
case9: sub foo5 (\@) { ++$_ for @{shift} }


Why are they different than others?


--The complete sample codes---

#! /bin/perl -l


{
my @a = 1..5;
++$_ for @a;
print "case1: ", @a;
}
{
my @a = 1..5;
++$_ for @{ \@a };
print "case2: ", @a;
}
{
my @a = 1..5;
my $r = \@a;
++$_ for @$r;
print "case3: ", @a;
}
{
my @a = 1..5;
my $r = \@a;
++$_ for @{$r};
print "case4: ", @a;
}
{
my @a = 1..5;
sub foo1 (\@) { ++$_ for @$_[0] }
foo1 @a;
print "case5: ", @a;
}
{
my @a = 1..5;
sub foo2(\@) { ++$_ for @{$_[0]} }
foo2 @a;
print "case6: ", @a;
}
{
my @a = 1..5;
sub foo3 (\@) { my $r=shift; ++$_ for @$r }
foo3 @a;
print "case7: ", @a;
}
{
my @a = 1..5;
sub foo4 (\@) { my $r=shift; ++$_ for @{$r} }
foo4 @a;
print "case8: ", @a;
}
{
my @a = 1..5;
sub foo5 (\@) { ++$_ for @{shift} }
foo5 @a;
print "case9: ", @a;
}

__END__

case1: 23456
case2: 23456
case3: 23456
case4: 23456
case5: 12345
case6: 23456
case7: 23456
case8: 23456
case9: 12345

-Todd
 
T

Todd

To make some clarification:

#! /bin/perl -l
use Data::Dumper;

@a = 1..5;

sub F1(@) { print Dumper shift; }
sub F2(\@) { print Dumper shift; }

F1 @a;
F2 @a;

$VAR1 = 1;

$VAR1 = [
1,
2,
3,
4,
5
];

So sub foo(\@) definitely passes a reference into the function in my
previous examples.

-Todd
 
T

Todd

Todd said:
In the code snippets blow, 2 strange cases are using @array copies
rather than modifying original ones:

case5: sub foo1 (\@) { ++$_ for @$_[0] }
case9: sub foo5 (\@) { ++$_ for @{shift} }

Now I see, `@$_[0]' is actually means `@{$_}[0]', but not `@{$_[0]}',
So case5 is not strange.

But I still don't understand case9:

sub foo5 (\@) { ++$_ for @{shift} }

Why it doesn't modify the origin array?

#! /bin/perl -l
{
my @a = 1..5;
sub foo5 (@) { ++$_ for @{shift} }
foo5 @a;
print "case9: ", @a;
}

__END__
case9: 12345


-Todd
 
J

John W. Krahn

Todd said:
In the code snippets blow, 2 strange cases are using @array copies
rather than modifying original ones:

case5: sub foo1 (\@) { ++$_ for @$_[0] }
case9: sub foo5 (\@) { ++$_ for @{shift} }

Now I see, `@$_[0]' is actually means `@{$_}[0]', but not `@{$_[0]}',
So case5 is not strange.

But I still don't understand case9:

sub foo5 (\@) { ++$_ for @{shift} }

Why it doesn't modify the origin array?

Because @{shift} is the same as @shift so you are modifying the @shift
array.

See the "Scalar value constructors" section of perldata:

perldoc perldata


Syntactically {shift} is the same as 'shift' which is also why barewords
as hash keys don't require quotes around them.



John
 
T

Todd

John said:
Because @{shift} is the same as @shift so you are modifying the @shift
array.
Syntactically {shift} is the same as 'shift' which is also why barewords
as hash keys don't require quotes around them.

In documents I see in `@{...}', the `{...}' is treated as a BLOCK, but
now it seems even `{' presents, The interpreter still checks if is the
`@{<simple-idendifier>}' case.

I listed some cases:

@{shift} ==means==> @shift
@{shift;} ==means==> $r=shift; @$r

Even `do' is a keyword of lanuages, the one blow still not interpreted
as a BLOCK:

@{do{shift}} --- Actually, i'm trying to figure out what it is?
@{do{shift};} --- Same as above
@{do{shift;}} --- Failed to compile



-Todd
 
T

Todd

So i got the intentions:

To use BLOCK inside expression:

@{;shift}
@{;do{shift}}

This is the hint from perldoc.

But not the ones below:

@{shift;} -- still good, but challange the compiler
@{do{shift};} -- Wow, the compiler is defeated this time. Not
recognize it as a BLOCK!
@{do{shift;}} -- Defeated also!, Even further, Not knowing how to
do with it, then give syntax error....


-Todd
 
T

Todd

John said:
Syntactically {shift} is the same as 'shift' which is also why barewords
as hash keys don't require quotes around them.

shift is not a bareword, it's an built-in function name. Does this
still make sense?

-Todd
 
J

John W. Krahn

Todd said:
In documents I see in `@{...}', the `{...}' is treated as a BLOCK,

In Perl many operators are overloaded to do different things in
different contexts.

perldoc perlsyn
[ SNIP ]
Simple statements

The only kind of simple statement is an expression
evaluated for its side effects. Every simple statement
must be terminated with a semicolon, unless it is the
final statement in a block, in which case the semicolon is
optional. (A semicolon is still encouraged there if the
block takes up more than one line, because you may
eventually add another line.) Note that there are some
operators like `eval {}' and `do {}' that look like
compound statements, but aren't (they're just TERMs in an
expression), and thus need an explicit termination if used
as the last item in a statement.
[ SNIP ]
Compound statements

In Perl, a sequence of statements that defines a scope is
called a block. Sometimes a block is delimited by the
file containing it (in the case of a required file, or the
program as a whole), and sometimes a block is delimited by
the extent of a string (in the case of an eval).

But generally, a block is delimited by curly brackets,
also known as braces. We will call this syntactic
construct a BLOCK.

However in the expression:

push @{ $hash{ q{no block here} } }, { this => qq{is}, qw{ NOT a block }
=> qr{.} };

The braces are used for a hash key, as quoting delimiters, to
dereference an array, and to create an anonymous hash, but none of these
uses constitutes a block.


John
 
J

John W. Krahn

Todd said:
shift is not a bareword, it's an built-in function name. Does this
still make sense?

If it is used in context as a function, then yes. If it is used in
context as a bareword then it is a bareword.


John
 
F

Florian Kaufmann

The braces are used [SNIP] to dereference an array [SNIP] but none of these
uses constitutes a block.

After reading Chapter "Using a BLOCK as a Variable Name" ("Programming
Perl") again I would say that there is indeed one block. The book
makes an example how to dereference the contents of a block:

push( @{$arrayref}, $filename )

Thus the curly braces indeed constitute a block, and its the @, not
the braces, which dereferences the reference to the array. I think
this is analogous to your example.

Flo
 
M

Michele Dondi

After reading Chapter "Using a BLOCK as a Variable Name" ("Programming
Perl") again I would say that there is indeed one block. The book
makes an example how to dereference the contents of a block:

push( @{$arrayref}, $filename )

Thus the curly braces indeed constitute a block, and its the @, not
the braces, which dereferences the reference to the array. I think
this is analogous to your example.

I was about to say: nope! But I tried the following and it does work:

C:\temp>perl -wMstrict -e "@{my @x}"
Useless use of a variable in void context at -e line 1.
Can't use string ("0") as an ARRAY ref while "strict refs" in use at
-e line 1.

C:\temp>perl -wMstrict -e "@{my @x; \@x}"
Useless use of a variable in void context at -e line 1.

C:\temp>perl -wMstrict -e "print @{my @x=qw/a b c/; \@x}"
abc
C:\temp>perl -wMstrict -e "print @{my @x=qw/a b c/; \@x}; print @x"
Global symbol "@x" requires explicit package name at -e line 1.
Execution of -e aborted due to compilation errors.

So it seems that the curlies in the dereferencing do actually define a
block. (I would have thought that they could only handle a single
expression, and to use a do() to put there several statements.)
However I would say that its @ { } which dereferences the reference.


Michele
 
T

Todd

Michele said:
So it seems that the curlies in the dereferencing do actually define a
block. (I would have thought that they could only handle a single
expression, and to use a do() to put there several statements.)
However I would say that its @ { } which dereferences the reference.

As i said before, the 2 ones blow are treated as BLOCK:

@{;shift}
@{;do{shift}}


#! /bin/perl -l

@a = qw/1 2 3/;

sub f1 (\@) { ++$_ for @{;shift}; }
f1 @a;
print @a;

sub f2 (\@) { ++$_ for @{;do{shift}}; }
f2 @a;
print @a;

__END__
234
345

`@{barword}' can also treated as `@{;barword}', also `@{;"barword"}'.
So it still can be treated as a BLOCK.

But well, `@{shift}' is a special case which Michele has mentioned
previously.

-Todd
 
T

Todd

`@{barword}' can also treated as `@{;barword}', also `@{;"barword"}'.
So it still can be treated as a BLOCK.

#! /bin/perl -l

$, = q/ /;
@a = qw/global array/;
{
my @a = qw/local array/;
print @{a};
print @{;a};
print @{"a"};
print @{;"a"};
}

__END__
local array
global array
global array
global array

Checking these results, i know there is really no BLOCK semantics in
`@{a}'. So Michele does hold the truth by his first sense. :)

-Todd
 
F

Florian Kaufmann

So {} can have quite a lot of different semantics:
- block
- anonymous hash
- hash subscript
- hash slice
- ??? ( the @{a} thingy )

Who has the exact rules when the curly braces have which semantics?

Flo

#! /bin/perl -l
$, = q/ /;
@a = qw/global array/;
%h = (1=>a,2=>b);
{
my @a = qw/local array/;
print @a;
print @{a}; # same thing. No dereferencing involved. {} is not a
block.
print @{;"a"}; # @{ } dereferences the symbolic reference
"a" (global a). {} is a block.
print @{;\@a}; # @{ } dereferences the hard reference \@a (local
a). {} is a block.
print $h{1}; # {} is a hash subscript
print @h{1,2}; # {} is a hash slice
}
 

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

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,584
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top