Unexpected alteration of array's content

N

nobull

This was new to me.

I guessed that because you didn't think the map() trick had a high
"blink factor".
Then I'm sorry to inform you that the idiom you prefer is still going
to cause a WTF moment for the casual reader. At least with a simple
assignment, it is intuitively obvious that something is being copied.
Not once you get used to it (I certainly blinked at the map example).

There is no reason for @{[@ar]} to become a familiar idiom. It doesn't
do anything that is often going to be necessary. It's not difficult to
decipher, but it still takes a blink.

Well _I_ encounter it often enough that I wanted a way to avoid the
ugliness of the explicit copy.

I was even moved to asked a question here
(<[email protected]>).
http://groups.google.com/[email protected]

This is something I rarely do!
I will do that, if I can find it.

Actually it's an interesting sub-thread of a rather less interesting
thread over in clp.moderated.

Unless you have MJD massively scored up [ doesn't everyone? :) ] you
could easily have missed it. It starts at:

From: Mark Jason Dominus <[email protected]>
Newsgroups: comp.lang.perl.moderated
Subject: Re: bug or gotcha?
Date: Mon, 29 Sep 2003 18:16:53 -0400
Message-ID: <[email protected]>
 
C

Charlton Wilbur

PG> My $element is an alias for the $_ variable. My $element is a
PG> moniker for the $_ variable. My $element is a new name for
PG> the $_ variable. My $element is a precise copy of the $_
PG> variable.

PG> Call $element any f'n thing you want. It is the $_ variable.


for (1..3)
{
for my $letter ('a'..'c')
{
print "$letter$_\n";
}
}

$_ is only used as an alias when there is no alias variable present.

PG> Friggin pay attention you bozos. Learn to read.

And in other posts you claim to be consistently polite and charming.

PG> I will remind you again including deceit in articles directed
PG> at me, serves only to annoy me. When your first sentence in an
PG> article is deceitful, that really pisses me off and leads me
PG> to ignore all else you say.

Someone who makes so many *errors* should be much slower to accuse
others of *deceit* -- or, is it the case that every time you say
something wrong, it is an *error*, but anyone else who says something
wrong is *deceitful*?

Charlton
 
R

Roy Johnson

Purl Gurl said:
My $element is an alias for the $_ variable.

Nope. $element is the loop variable, or $_ is the loop variable, but
not both simulataneously. The same response applies to "moniker", "new
name", "precise copy" (especially!), and any other way you try to
claim that the loop variable takes on the functionality or value of
$_.
Only $_ should do this, only $_ should have "write" permission.

Sorry, you've been overruled. It's not your language. The loop
variable, whatever it is, has "write" permission, because the loop
variable, regardless of its name, is an alias for the current element
of the loop.
Not localizing $element is illogical and leads to
confusion until a person realizes it is, de facto,
the perl core default $_ variable.

You're operating under the false assumption that there is only one
logical choice. It is perfectly logical to say that every loop
variable is an alias. You are aware, aren't you, that outside of a
loop, $_ is not generally an alias?
Do you really believe perl core discards all the functions
of $_ then creates a new set of identical functions for a
a named alias?

The functionality of aliasing is implemented for the loop structure,
not for the $_ variable. Inside a loop, if you do s/foo/bar/, it does
not apply to the loop variable, it applies to whatever $_ is. The loop
variable is not the new default argument for the many functions and
operators that $_ is.
My $element is $_ and $_ is my $element.

$_ is the default foreach loop variable, just like it's the default
argument for a lot of functions and operators. When you supply an
argument to length(), that doesn't make the argument relate in any way
to $_.

Aliasing is a property of foreach loops, and it is consistent,
regardless of what the loop variable is.

Hope this helps.
 
C

Charlton Wilbur

PG> You enjoy zero credibilty and enjoy a realistic reputation as
PG> being one of this group's well known trolls.

Coming from you, that's rather a compliment; though I suppose the
Google archive speaks for itself.

Charlton
 
C

Carlton Brown

Purl Gurl said:
Odd you should use this expression "best practices" when those with
good programming skills know use of local() is mandatory for many
programming circumstances. Without local() many tasks would be very
difficult to perform if not impossible.

In perl, 99% of the time you would use local(), my() is a better
choice than local(). local() overrides the concept of pure scoping.
It causes "inconsistency" that seems to disturb you so much. The only
reason you ever need local is if you've inherited code from some yog
who insisted on using the same variable name in an inner loop as the
outer loop, but wanted it to magically to revert to the outer loop
value once the inner loop is exited. It's quite convenient for
loops. In other places it's risky, and why take the risk when my()
does the same thing without the secret temporary copies?
Educating the orginal author on this notion is and was my goal.
This behavior of $_ and behavior of an alias to $_ is illogical;
there exists no behavioral difference between the two.

Read again my comments about an alias should not have "write" permission.

I confess to having a crisis of reading comprehension when I see you
simultaneously say that there exists no difference between the
behavior of $_ and a loop variable (a true fact), and therefore they
should behave differently (one having write permission, and one not).
If that were true, it would cease to be an alias, it would then be a
copy.

Perl 4 has already been down this road on loop behaviors and it was
decided that things shall be otherwise. Not much sense in wishing
that behavior would come back... that is true "cargo cultism" if you
are familiar with the story.

http://www.nthposition.com/places_cargo.html
 
R

Roy Johnson

Purl Gurl said:
This thread topic is not related to lexical scoping nor
has lexical scoping been mentioned by anyone but you.
Clearly you have a problem with drifting away from a
current topic. [...then...]
Clearly you know little or nothing about local() and
its usage with Perl programming. Your statement could
not be more wrong.

Clearly you are a troll. Not only do you hypocritically focus on
topics you berate him for talking about, you only address them to the
extent necessary for your personal attack. In particular, you do not
offer any corrections.
Less apparent to others but quite clear to me, you
are another Perl 5 Cargo Cultist.

Just another personal attack from the forum's resident crank/troll.

It is telling that you have not addressed any issues in your latest
few posts. Just attacked posters. Troll behavior.

The code on your website is also dysfunctional. Is that more of your
trolling, or a legitimate accident?
 
A

Anno Siegel

Roy Johnson said:

[ways to create an array copy]
There is no reason for @{[@ar]} to become a familiar idiom. It doesn't
do anything that is often going to be necessary. It's not difficult to
decipher, but it still takes a blink.

Reason or no, the use of [] to make an array copy, and of {} for a hash
copy, are pretty well established. When working with references it
is often necessary to de-couple one reference from another, and the
natural thing for an arrayref is to say "[@$ref]". From there it is
only a step to "@{[@ar]}".

Anno
 
R

Roy Johnson

Reason or no, the use of [] to make an array copy, and of {} for a hash
copy, are pretty well established.

There are reasons for those uses.
From there it is only a step to "@{[@ar]}".

A step with no reason. A misstep, as it were.

I'm not sure what point you're trying to make.
 
A

Anno Siegel

Roy Johnson said:
(e-mail address removed)-berlin.de (Anno Siegel) wrote in message
Reason or no, the use of [] to make an array copy, and of {} for a hash
copy, are pretty well established.

There are reasons for those uses.
From there it is only a step to "@{[@ar]}".

A step with no reason. A misstep, as it were.

I'm not sure what point you're trying to make.

Only that I don't share your dislike of "@{[@ar]}". If you want an anonymous
copy of an array, it's the way to go. Since that doesn't happen often,
there is no danger of it becoming an idiom. No big deal altogether.

Anno
 
R

Roy Johnson

I guessed that because you didn't think the map() trick had a high
"blink factor".

map() returns a list of arbitrary expressions, whereas grep returns
the elements it is processing, so it makes some sense that grep
returns lvalues while map does not. Incidentally, I didn't say the map
trick didn't have a high blink factor. It is at least as high as
@{[@foo]}.

Also incidentally, the blink factor is not synonymous with bad
programming, although there's definitely some overlap. Anything that
causes a reader to have to pause to decipher it has a blink factor.
Good programs reserve those for code that is doing something special.
Well _I_ encounter it often enough that I wanted a way to avoid the
ugliness of the explicit copy.

What makes an explicit copy "ugly"? Especially when it avoids the
overhead of slinging an entire array around?

Would you offer an example of a prudent and common use of @{[@foo]}}?
My impression is that its only use is as protection against loop
aliasing, and it's generally more economical and clear to copy one
scalar than the whole array.

I did find it, thanks.

Roy
 
R

Roy Johnson

Only that I don't share your dislike of "@{[@ar]}".

I think you may have mistaken my comments on this topic. There are two
points I was making:
1. there is no reason to use @{[@ar]} to solve the problem under
consideration
2. @{[@ar]} is odd enough that someone browsing the code will "blink"
when they hit it.

I think we agree on #2. Brian, on the other hand, suggested that it
was something to get used to (to the point that it is immediately
understood whenever encountered).
If you want an anonymous copy of an array, it's the way to go.

Yes, it is. However, making an anonymous copy of the array is not the
way to go to avoid modifying your array in a loop. There may be good
reasons for making an anonymous copy of an array, although I haven't
come up with any.

I can see wanting to do [@ar], and I can certainly see @$ref, but not
instantly dereffing a newly-created array ref.

If the question is how to avoid the side-effects of loop variable
modification, the answer is to make a local copy of the loop variable,
not to copy the entire array.
 
A

Anno Siegel

Roy Johnson said:
(e-mail address removed)-berlin.de (Anno Siegel) wrote in message
Only that I don't share your dislike of "@{[@ar]}".

I think you may have mistaken my comments on this topic. There are two
points I was making:
1. there is no reason to use @{[@ar]} to solve the problem under
consideration
2. @{[@ar]} is odd enough that someone browsing the code will "blink"
when they hit it.

I think we agree on #2. Brian, on the other hand, suggested that it
was something to get used to (to the point that it is immediately
understood whenever encountered).

Well, that is in the eye of the beholder. People get used to the
weirdest things, not limited to, but particularly in computer languages.
COBOL programmers used to put up with having to write a few hundred lines
of declarations before the first executable statement. No blink-effect
there, not after a few years of the same.

In one context, the "@{[ ... ]}" construct *is* idiomatic. It is regularly
used to interpolate arbitrary expressions into strings, as in

print "1 + 2 = @{[ 1 + 2 ]}\n";

The weirdness factor is even greater here, because there is only one
element in the inner array, but that's established Perl.
Yes, it is. However, making an anonymous copy of the array is not the
way to go to avoid modifying your array in a loop. There may be good
reasons for making an anonymous copy of an array, although I haven't
come up with any.

Well, string interpolation is one example. Another is a fix to a
misbehaving map or grep. "Oops, it's changing my array! Let's put
@{[ ... ]} around it." That comes close to the loop example.

I mentioned I didn't think it comes up often, but there are uses.
I can see wanting to do [@ar], and I can certainly see @$ref, but not
instantly dereffing a newly-created array ref.

If the question is how to avoid the side-effects of loop variable
modification, the answer is to make a local copy of the loop variable,
not to copy the entire array.

Why not? Once the blink reflex has worn off, it's a possible alternative.

I would probably not use it in a traditional loop (with a block body),
but with statement-modifying "for", as with "map" above, a local copy is
less easy to accommodate. A lot depends on context, and I can see contexts
where "@{[ ... ]}" is appropriate.

Anno
 
U

Uri Guttman

AS> In one context, the "@{[ ... ]}" construct *is* idiomatic. It is
AS> regularly used to interpolate arbitrary expressions into strings,
AS> as in

AS> print "1 + 2 = @{[ 1 + 2 ]}\n";


the scalar version also works but is uglier: "${\ 1 + 2 }. and it has a
bug because it provides list context. the Interpolate module supports
the use of $() for that. perl6 will also have $() and @() to do it as
builtins (they also will work outside strings and replace scalar()).

uri
 
A

Anno Siegel

Uri Guttman said:
RJ> I don't consider @{[...]} to be horrible, just mildly distasteful. It
RJ> gets worse depending on the size of the array.
AS> Yes. We're discussing the case where you don't want to do that for
AS> some reason.

and that reason is? i can't see any reason where a simple copy won't work.

Sure it will work. You may not want to avoid a temporary variable,
perhaps because there is no convenient block to put it in.
have a reference already then @{$ref} is fine. so where would @{[ blah
]} be needed except to interpolate?

AS> Well, abstractly speaking, when you want an anonymous copy of the list.
AS> More concretely... uh, I don't think you really want to know, there
AS> was nothing earth-shattering. Post a followup and I'll make an excerpt
AS> from the thread if you want one.

what is an anon copy? how would a regular copy not be anon? inquiring
minds want to know! :)

It's anonymous because it doesn't need a named variable to hold it.
AS> Thread drift...

this still doesn't explain the need for @{[blah]} which what i want to
know.

There is no absolute need. Even the use for interpolation is
qualified with "if you must interpolate an expression". We were
discussing possible uses. There aren't many, and none of them is
particularly compelling.

Anno
 
A

Anno Siegel

Uri Guttman said:
RJ> I don't consider @{[...]} to be horrible, just mildly distasteful. It
RJ> gets worse depending on the size of the array.
AS> Yes. We're discussing the case where you don't want to do that for
AS> some reason.

and that reason is? i can't see any reason where a simple copy won't work.

Sure it will work. You may want to avoid a temporary variable,
perhaps because there is no convenient block to put it in.
have a reference already then @{$ref} is fine. so where would @{[ blah
]} be needed except to interpolate?

AS> Well, abstractly speaking, when you want an anonymous copy of the list.
AS> More concretely... uh, I don't think you really want to know, there
AS> was nothing earth-shattering. Post a followup and I'll make an excerpt
AS> from the thread if you want one.

what is an anon copy? how would a regular copy not be anon? inquiring
minds want to know! :)

It's anonymous because it doesn't need a named variable to hold it.
AS> Thread drift...

this still doesn't explain the need for @{[blah]} which what i want to
know.

There is no absolute need. Even the use for interpolation is
qualified with "if you must interpolate an expression". We were
discussing possible uses. There aren't many, and none of them is
particularly compelling.

Anno
 
R

Roy Johnson

Brian McCauley said:
I don't see and either one is more or less readble than the
other. Double quotes are not the only interpolatative context. The
@{[...]} really comes into it's own in here-docs.

interpolating here-docs *are* a double-quote context, but I see your
point that interspersing them with cat operators would be clunky. My
preference would still be to set some variables before the here-doc,
and simply interpolate the variables. Then you've got symbolic names
instead of magic formulae.

There seems to be a contingent who believe that variables are Bad
Things.
Another is a fix to a misbehaving map or grep. "Oops, it's changing my
array! Let's put @{[ ... ]} around it."

This is the best example,

And is indeed the subject of this thread!

No, the subject of the thread is a foreach, which differs from map and
grep in that it doesn't return a list automatically. It is the
possibility that you want to return a modified form of the input
array, without modifying the original, combined with the fact that
you're never going to use the copy directly, that suggests an
anonymous copy.

Even so, as I said, I think the BLOCK form of map, or rewriting the
grep as a foreach would be better (more efficient and clear).
 

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,755
Messages
2,569,536
Members
45,020
Latest member
GenesisGai

Latest Threads

Top