References in foreach loop variable 
Author Message
 References in foreach loop variable

I wrote the following code:

foreach $$i (1..3) {
    print $$i;

Quote:
}

But when I tried to run it, perl complained:
Can't use an undefined value as a symbol reference at - line 1.

$i = \$foo;
foreach $$i (1..3) {
    print $$i;

Quote:
}

And when I tried to run this, perl complained:
Not a GLOB reference at - line 2.

I finally tried:

$i = 'foo';
foreach $$i (1..3) {
    print $i;

Quote:
}

This gave me what I had expected in the first place.  I understand (sort
of) why the first attempt failed, and why the third attempt was
successful, but can't figure out why the second attempt failed.

--

|\ e i t h   /-| r n e r          

                 When all else fails, duct tape it.|
                       ----------------------------'



Tue, 12 Oct 1999 03:00:00 GMT  
 References in foreach loop variable

Hello -

Quote:

>I wrote the following code:
>foreach $$i (1..3) {
>    print $$i;
>}
>But when I tried to run it, perl complained:
>Can't use an undefined value as a symbol reference at - line 1.

>$i = \$foo;
>foreach $$i (1..3) {
>    print $$i;
>}
>And when I tried to run this, perl complained:
>Not a GLOB reference at - line 2.
>I finally tried:
>$i = 'foo';
>foreach $$i (1..3) {
>    print $i;
>}
>This gave me what I had expected in the first place.  I understand (sort
>of) why the first attempt failed, and why the third attempt was
>successful, but can't figure out why the second attempt failed.

(The following answer is predicated on the assumption that you meant
"print $$i;", not "print $i;", in the third example.)

OK, going at it in a slightly different order (and ... don't take it the
wrong way ... there's a chance you may be surprised at why the third one
succeeded!) -

In foreach $$i (), the expression $$i has to be a scalar lvalue.

If $i doesn't contain anything (your first example), then the expression
$$i is a dereferencing of nothing, which doesn't work.

If $i contains a string, such as 'foo', then $$i can be something.
Specifically, it can be a scalar (as per the initial $) whose name is
the string contained in $i.  This is a symbolic reference.  This means
that (here) $$i is basically equivalent to $foo.  (Think of this: "A
dollar sign, followed by the character string 'foo' or the name of a
variable which contains that character string, being evaluated
as $foo").  (And remember that it doesn't work with my() variables
or under 'use strict'.)

The $$i symbolic reference, in turn, means that in third example, the
values 1,2,3 are assigned successively to $foo.  If you replace "print
$$i" with "print $foo", you'll see what I mean.  (The reason I suggested
above that you might be surprised by this is that, if you expected the
first one to work, you might not have realized what was going on with
the symbolic reference in the third one.)

If $i contains neither nothing nor a plain string, but, instead, a
hard reference, then Perl checks to see whether it is the right type of
reference for the occasion.  In the case of your second example, it
isn't - it's a scalar reference, where only a glob reference will do.

If it were a glob reference:

$i = \*foo;

then you'd get "123" again - but, as in the third example, the
assignment would be to $foo.  The effect is the same, but the two
examples actually work differently, and illustrate the difference
between hard and symbolic references.

Hoping this isn't too dense, fuzzy, long, wide....

David Black



Wed, 13 Oct 1999 03:00:00 GMT  
 References in foreach loop variable


Quote:
>If it were a glob reference:

>$i = \*foo;

>then you'd get "123" again - but, as in the third example, the
>assignment would be to $foo.

That's not _quite_ right.   Trying

$i = \*foo;
foreach $$i (1..3) { print $$i };

prints

*main::foo*main::foo*main::foo

whereas

$i = \*foo;
foreach $$i (1..3) { print $$$i };

prints

123

Perhaps you can explain that  -  I can't.

Mike Guy



Fri, 15 Oct 1999 03:00:00 GMT  
 References in foreach loop variable

Hello -

Quote:


>>If it were a glob reference:

>>$i = \*foo;

>>then you'd get "123" again - but, as in the third example, the
>>assignment would be to $foo.
>That's not _quite_ right.   Trying
>$i = \*foo;
>foreach $$i (1..3) { print $$i };
>prints
>*main::foo*main::foo*main::foo

Your right - I was using "get" in a slipshod way, not
properly related to the code.

Quote:
>whereas
>$i = \*foo;
>foreach $$i (1..3) { print $$$i };
>prints
>123
>Perhaps you can explain that  -  I can't.

This is more a report on further examination than an
explanation.

If you change the examples above to  foreach $$$i (1..3),
then eveything works "as expected" (with respect
to degrees of indirection, numbers of $'s, etc.).
$i is a typeglob ref,
$$i is a typeglob,
$$$i is the scalar member of that typeglob.

It's the fact that foreach $$i (1..3) (with two $'s) also
works that seems to be the anomaly.

Anyway, for what it's worth, here's some tinkering and a
few further comments.

#!/usr/local/bin/perl -w

# It's interesting that, given this:

$j = \*bar;

# each of these prints 'z':

foreach $bar        ('z') { print "$bar\n" }
foreach ${bar}      ('z') { print "$bar\n" }
foreach ${*bar}     ('z') { print "$bar\n" }
foreach ${\*bar}    ('z') { print "$bar\n" }
foreach ${$j}       ('z') { print "$bar\n" }
foreach $$j         ('z') { print "$bar\n" }
foreach ${$$j}      ('z') { print "$bar\n" }
foreach $$$j        ('z') { print "$bar\n" }

__END__

Dare I suggest that this is a case of implicit
dereferencing?  If it is, it may even be documented
somewhere... (Right now, the only "actually-there-
is-some" example I can find in the Camel has to do
with file handles.)

Pursuing implicit deref theory:

     foreach $$j ()

$j is dereferenced, yielding a typeglob (*bar), and then the
first $ constrains the variable to the scalar member of
that typeglob.

Or - perhaps the deferencing is as it appears (explicit),
and foreach(), requiring a scalar lvalue, implicitly constrains the
typeglob expression to its scalar member.  That would mean that
foreach() was, in effect, supplying its own left-most $ on the loop
variable.  But if that's what happening, then why isn't foreach willing
to do it with things like:

     foreach *bar ()  # syntax error

In short, I can see what's happening, and (having tinkered
with it) can predict which expressions will do what, but
I still do not entirely understand where the functional
equivalence between $$j and $$$j, as foreach() variable
expressions, is coming from.

Comments and/or Camel page numbers welcome :-)

David Black



Sat, 16 Oct 1999 03:00:00 GMT  
 References in foreach loop variable

#!/usr/local/bin/perl -w
=head

I've puzzled through the matter of the relation between
typeglobs and typeglob references, initially in connection
with an earlier thread (References in foreach loop variables),
in an attempt to understand why, given:

$i = \*foo;

these two loop specifiers produce identically behaving loops:

foreach $$i ...
foreach $$$i ...

I would be very happy if anyone with insight into this would look
over the following, which is my current understanding of it, and
comment/correct/pat on shoulder :-)

Thanks -

David Black

=cut

# PART I

$bar = 'abc';

# Testing the equivalence of these two assignments:

*myglob1 = *bar;
*myglob2 = \*bar;

print $myglob1, $myglob2;  # prints 'abcabc'

# So, for aliasing purposes, the right-hand can be a typeglob
# or a typeglob reference.

# Explanation:

# Assigning a reference to a typeglob only aliases
# the member specified (e.g., *glob = \$foo; now $glob == $foo

# (And yes, I know that != doesn't really work on arrays.)

# Therefore, assigning \*bar to *myglob "only" aliases the
# "*" member - which is the glob itself.

# Therefore, it has the same effect as assigning *bar to *myglob.

# PART II

# Given:

$k = \*foo;

# then these two loops are equivalent:

foreach $$k ('x') { print $foo };  # prints x
foreach $$$k ('x') { print $foo }; # prints x

# In the first, the loop variable is a typeglob reference.
# In the second, it's a typeglob.

# But foreach() uses aliasing, so (see Part I) aliasing whatever
# temporary glob is holding the 'x' to $$k has the same effect
# as aliasing it to $$$k.

# Inside either loop, however, $$k is treated (where the difference
# matters) as a glob ref, and $$$k is treated as the scalar member
# of that glob:

foreach $$k ('x') { print "$$k $$$k" };  # prints *main::foo x
__END__



Sun, 17 Oct 1999 03:00:00 GMT  
 References in foreach loop variable


Quote:
> (The following answer is predicated on the assumption that you meant
> "print $$i;", not "print $i;", in the third example.)

Yes... that's what I meant.  I knew I should have cut-and-paste.

Quote:
> In foreach $$i (), the expression $$i has to be a scalar lvalue.

> If $i doesn't contain anything (your first example), then the expression
> $$i is a dereferencing of nothing, which doesn't work.

If we pull this out of the foreach:

$$i = 2;

Generates the error:
Can't use an undefined value as a SCALAR reference at - line 1.

However:

$$i[0] = 2;

..is successful.

Perl dynamicly creates the annonymous array
referenced by $i.  It would stand to reason that perl would dynamicly
create the anonymous scalar referenced by $i in '$$i = 2', since
"references of an appropriate type simply spring into existance if you
dereference them in a context that assumes they exist" (p. 248).

Quote:
> If $i contains neither nothing nor a plain string, but, instead, a
> hard reference, then Perl checks to see whether it is the right type of
> reference for the occasion.  In the case of your second example, it
> isn't - it's a scalar reference, where only a glob reference will do.

Now that's the point that has me baffled.  Why does it need to be a
glob ref rather than a scalar ref?  Consider the following two
programs:

$i = *foo;
$foo = 1;
print $$i;
print $foo;

$i =\$foo;
$foo = 1;
print $$i;
print $foo;

These both give the same end result (and they work the same if the
assignment on the second line is to $$i).  This seems to say that
the glob and the hard ref can be used interchangeably (assuming you
don't want to muck around in symboltables).  What is special about the
foreach loop that it's control variable cannot be found through a hard
reference to a scalar?  

My gut seems to be telling me that the problem lies in the fact that
perl does some sort of glbo assignment on the control variable (to
allow assignment to the control variable to change the original
value), but I can't quite put it into words.

Quote:
> Hoping this isn't too dense, fuzzy, long, wide....

"This one's just right", said Goldylocks.

--

|\ e i t h   /-| r n e r          

                 When all else fails, duct tape it.|
                       ----------------------------'



Sun, 17 Oct 1999 03:00:00 GMT  
 References in foreach loop variable

Hello -

Anyone following this, see my posting on "globs, refs, aliases,
foreach - have I got the idea?".  (Keith, I'll mail you a copy :-)

David Black



Sun, 17 Oct 1999 03:00:00 GMT  
 References in foreach loop variable

Hello -

As I said in my last post, see my yet other post for some more
reflections on this....  But also, here are a couple of
further comments in this thread.

Quote:

>If we pull this out of the foreach:
>$$i = 2;
>Generates the error:
>Can't use an undefined value as a SCALAR reference at - line 1.

This appears to have been changed in 5.004beta or thereabouts:

candle:~/hacking/perl$ perl -w
$$i = 2;
print $$i;
^D
2

(5.003_95)

Quote:
>> If $i contains neither nothing nor a plain string, but, instead, a
>> hard reference, then Perl checks to see whether it is the right type of
>> reference for the occasion.  In the case of your second example, it
>> isn't - it's a scalar reference, where only a glob reference will do.
>Now that's the point that has me baffled.  Why does it need to be a
>glob ref rather than a scalar ref?  Consider the following two
>programs:

[ ... ]

Quote:
>My gut seems to be telling me that the problem lies in the fact that
>perl does some sort of glbo assignment on the control variable (to
>allow assignment to the control variable to change the original
>value), but I can't quite put it into words.

Aliasing, I think.  (See other post :-)

David Black



Mon, 18 Oct 1999 03:00:00 GMT  
 
 [ 10 post ] 

 Relevant Pages 

1. Don't know how to reference array position from a foreach loop

2. Weird behavior when using foreach loop and references

3. my variables in foreach loops

4. foreach loop variable localizing

5. Variable evaluation in foreach / for loops??

6. allowed index variables in foreach loops

7. global my() variable used in foreach() loop loses its value

8. special variable for foreach loops?

9. Splice in foreach loop, then quit loop: legal?

10. foreach loop works, for loop not

11. Save output from foreach loop outside loop?

12. Help: a beginner cannot make for/foreach loop running

 

 
Powered by phpBB® Forum Software