vec() in lvalue sub

S

s · reservoir

The subroutine is this:
sub mess_with_bits(\$$;$) : lvalue {
do {
eval {
${$_[0]} = ''
};
cluck $@ if $@;
} if (!defined ${$_[0]});
my $r = shift;
my $p = shift;
if (@_) {
my $o = vec($$r => $p, 1);
vec($$r => $p, 1) = shift;
return $o;
}
vec($$r => $p, 1);
}
But when I do this:
mess_with_bits($str, 17) = 1;
print mess_with_bits($str, 2), "\n"'
it prints 1.
 
S

s · reservoir

s said:
The subroutine is this:
sub mess_with_bits(\$$;$) : lvalue {
do {
eval {
${$_[0]} = ''
};
cluck $@ if $@;
} if (!defined ${$_[0]});
my $r = shift;
my $p = shift;
if (@_) {
my $o = vec($$r => $p, 1);
vec($$r => $p, 1) = shift;
return $o;
}
vec($$r => $p, 1);
}
But when I do this:
mess_with_bits($str, 17) = 1;
print mess_with_bits($str, 2), "\n"'
it prints 1.
For some reason, it prints 0 if I don't have
use feature qw(say);
 
L

Leon Timmermans

The subroutine is this:
sub mess_with_bits(\$$;$) : lvalue {
do {
eval {
${$_[0]} = ''
};
cluck $@ if $@;
} if (!defined ${$_[0]});
my $r = shift;
my $p = shift;
if (@_) {
my $o = vec($$r => $p, 1);
vec($$r => $p, 1) = shift;
return $o;
}
vec($$r => $p, 1);
}
But when I do this:
mess_with_bits($str, 17) = 1;
print mess_with_bits($str, 2), "\n"'
it prints 1.

No offense, but this is terrible code to read. The `do{} if` thing
doesn't make any sense at all, why not just use an if statement? Why do
you use an eval section? Also, please give your variables normal names.

Anyway, I can reproduce this (on 5.8.8). The value in the bitstring is 0,
but the function reports 1. Smells like a bug to me.

Regards,

Leon Timmermans
 
S

s · reservoir

The subroutine is this:
sub mess_with_bits(\$$;$) : lvalue {
   do {
     eval {
       ${$_[0]} = ''
     };
     cluck $@ if $@;
   } if (!defined ${$_[0]});
   my $r = shift;
   my $p = shift;
   if (@_) {
     my $o = vec($$r => $p, 1);
     vec($$r => $p, 1) = shift;
     return $o;
   }
   vec($$r => $p, 1);
}
But when I do this:
   mess_with_bits($str, 17) = 1;
   print mess_with_bits($str, 2), "\n"'
it prints 1.

No offense, but this is terrible code to read. The `do{} if` thing
doesn't make any sense at all, why not just use an if statement? Why do

It is terrible. I was going to rewrite it, but I never got around to
it.
Thanks for reminding me.
you use an eval section? Also, please give your variables normal names.

In case somebody tried mess_with_bits('', 17). It has to do with an
old
implementation of it that I never really fixed.
Anyway, I can reproduce this (on 5.8.8). The value in the bitstring is 0,
but the function reports 1. Smells like a bug to me.

Sent a report with perlbug.
 
S

s · reservoir

The subroutine is this:
sub mess_with_bits(\$$;$) : lvalue {
   do {
     eval {
       ${$_[0]} = ''
     };
     cluck $@ if $@;
   } if (!defined ${$_[0]});
   my $r = shift;
   my $p = shift;
   if (@_) {
     my $o = vec($$r => $p, 1);
     vec($$r => $p, 1) = shift;
     return $o;
   }
   vec($$r => $p, 1);
}
But when I do this:
   mess_with_bits($str, 17) = 1;
   print mess_with_bits($str, 2), "\n"'
it prints 1.

No offense, but this is terrible code to read. The `do{} if` thing
doesn't make any sense at all, why not just use an if statement? Why do
you use an eval section? Also, please give your variables normal names.

Anyway, I can reproduce this (on 5.8.8). The value in the bitstring is 0,
but the function reports 1. Smells like a bug to me.

Oddly enough, this works:

#!/usr/bin/env perl
use strict;
use warnings;
sub f(\$$;$) : lvalue {
do { eval { ${$_[0]} = '' }; warn $@ if $@; } if (!defined $
{$_[0]});
my $r = shift;
my $p = shift;
if (@_) {
my $o = vec($$r => $p, 1);
vec($$r => $p, 1) = shift;
return $o;
}
vec($$r => $p, 1);
}
sub say {
print @_, "\n";
}
my $str;
say f($str => 13);
f($str => 17) = 1;
my $t = f($str => 13);
say $t;
 
B

Ben Morrow

Quoth =?ISO-8859-1?Q?s_=B7_reservoir?= said:
The subroutine is this:
sub mess_with_bits(\$$;$) : lvalue {

lvalue subs do not always behave as one might expect, and are worth
avoiding. What's wrong with a more normal API?

Ben
 
S

s · reservoir

Big said:
In 5.8.5 it also reports 1....

As it does under 5.6.3, 5.7.3, 5.8.8, 5.9.4, and 5.10.0...
FWIW the "if (@_)" setting block never gets called (put a print
statement in it - it never happens). The first call only has 2
parameters. Hence $str is never set, and you are actually trying to

$str is should set - the ugly do if block assigns to it, not the if (@_).
access an unset variable, which probably explains the different result

Access to an unset variable gives a warning under -w, but it didn't.
in and not-in the debugger.

The if (@_) block is there to let you do this:
mess_with_bits($str, 1, 1);
and get back 0 while setting the second bit to 1.
I just copied most of it from my editor.
It is documented that you can't have a return in an lvalue sub (e.g.
http://search.cpan.org/dist/perl/pod/perlsub.pod#Lvalue_subroutines__)

Though in reality, you can - you just can't assign to it if it returns
from a return. I discovered that when I foolishly tried to do so.
 

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,755
Messages
2,569,537
Members
45,021
Latest member
AkilahJaim

Latest Threads

Top