SUBSTR() with replacement or lvalue performance issues

I

Ilya Zakharevich

[A complimentary Cc of this posting was sent to

Also, if you assign to the lval with a string of a different length,
the lval still remembers it's length to be the originally created one, not
the length of the string just assigned to it. So you can assign and
then immediately read and get a different thing than what you just
assigned. But I don't know that the alternative would be any less odd.

Let me guess: the alternative would be a sane behaviour?

perl -wle "sub edit($) {$_[0] = $_ for qw(123 456 789)}
$x = q(abc); edit substr $x, 1, 1; print $x"
a7895623c

[BTW, thanks for your explanation; I did not know about this bug...]

Yours,
Ilya
 
S

sln

I think it is your expectations that have problems. But you haven't
described what your expectations are, so it is hard to tell.

The lvals remember the offset and length. If the main string gets
rearranged, the lval doesn't try to change the offset and length in an
attempt to trace that rearrangement. Can you imagine the morass if they
did? Instead, it keeps the "window" the same and lets characters move
around beneath it.

Also, if you assign to the lval with a string of a different length,
the lval still remembers it's length to be the originally created one, not
the length of the string just assigned to it. So you can assign and
then immediately read and get a different thing than what you just
assigned. But I don't know that the alternative would be any less odd.

Xho

No I didn't have any expectations other than to try out the code from
that perlmonks link. Hey I'm happy Perl can even take references mid-string,
even though it was to an LVALUE.

It's was new to me. Sort of like taking the address of element
N in a character array ala C:
char A[] = "asfasjsadflfsdlk";
char* p = &A[5];
strncpy( p, "000", 2);
// now A is "asfas00adflfsdlk"

Dereferencing returns the string, thats good enough.

I don't pretend to understand how substr() does its LVALUE sub. However it
is, I'm sure its for good reason. Actually my original intention was to
NOT grow/shrink gigantic strings.


sln

----------------------

use strict;
use warnings;


my $str = "asdfasdf";
my $lvref = \substr($str, 0, 3);
$$lvref = "zzzzz";
print ref($lvref)." = $$lvref, length = ".length($$lvref)."\n";
print "str = $str, length = ".length($str)."\n\n";

$str = "asdfasdf";
$lvref = \(substr($str, 0, 3) = "12345");
print ref($lvref)." = $$lvref, length = ".length($$lvref)."\n";
print "str = $str, length = ".length($str)."\n\n";

$str = "asdfasdf";
substr($str, 0, 3) = "zzzzz";
print "str = $str, length = ".length($str)."\n";
substr($str, 0, 3) = "aaaaa";
print "str = $str, length = ".length($str)."\n";
substr($str, 0, 3) = "";
print "str = $str, length = ".length($str)."\n";
substr($str, 0, 3) = "aaaaa";
print "str = $str, length = ".length($str)."\n";

__END__

LVALUE = zzz, length = 3
str = zzzzzfasdf, length = 10

LVALUE = 123, length = 3
str = 12345fasdf, length = 10

str = zzzzzfasdf, length = 10
str = aaaaazzfasdf, length = 12
str = aazzfasdf, length = 9
str = aaaaazfasdf, length = 11
 
I

Ilya Zakharevich

[A complimentary Cc of this posting was sent to
What for? Why this should not work:

perl -wle "@a=(10..15); sub z2{$_[2]=0}; z2 map $_, @a; print for @a"
It does work. It just doesn't do what you want :)

Well, in my book it means that it does not work...
I think the current behavior is reasonable,

for what?
The current behavior is consistent with what other things that
conceptually *could* keep aliasing, but don't. Like push.

It is obvious that push, and assignements, should by default do copying.
(I think "Paradigm clash" of `perldoc overload' may be relevant here.)
Or subroutines.

Subroutines doing an extraneous copy is an unfortunate oversight by
Larry. When I discovered this, it was too late to fix; thus the need
for `lvalue' hack to disable this... Of course, lvalueness should
have been the default...
On the other hand, reverse does preserve aliasing.

a do block also preserves aliasing, but for some odd reason I'm not
allowed to assign to one directly.

Easily:

perl -wle "sub stomp($) {$_[0] = 123} $x = 'abc'; stomp do {$x}; print $x"
123

Anyway, do not you think that map() is just a sequence of do{}-blocks?

Thanks for your investigations,
Ilya
 

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,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top