shotgunefx has asked for the wisdom of the Perl Monks concerning the following question:

I came across something with substr that struck me as odd.
The value from a substr assignment is not what character(s) were removed but what you assigned it to.
This strikes me as weird and somewhat useless. I would think (and thought) it would work like chop and return the deleted characters.

Is this a feature or a bug? I didn't see anything about what it should return in Programming Perl, but in Perl in a Nutshell it states...
"You can also specify a replacement string in the fourth parameter to replace the substring. The original extracted substring is still returned."

Am I reading this wrong?
#!/usr/bin/perl -w # Example perl 5.6.1 my $string = '012345679ABCDEFGHIJKLMNOPQRSTUV'; print $string,"\n"; my $result = substr($string,2,6) = ''; print $result,"\n"; # Result is 9ABCDE print $string,"\n";


-Lee

"To be civilized is to deny one's nature."

Replies are listed 'Best First'.
Re: Bug with substring return value?
by Dog and Pony (Priest) on Apr 13, 2002 at 11:37 UTC
    Try:
    my $result = substr($string,2,6,''); print $result,"\n"; # Result is 234567
    perldoc -f substr:
    An alternative to using substr() as an lvalue is to specify the replacement string as the 4th argument. This allows you to replace parts of the EXPR and return what was there before in one operation, just as you can with splice().

    I agree that the assignment way is pretty weird and contraintuitive, but I guess there is a reason... such as the possibility to use both ways depending on what you want to acheive?

    Update: I just realized that it makes a bit more sense when you think about this:
    $x = $y = 42;
    Which sets first $y to 42, then $x to the value of $y. In which case, you set the substring to a value, then that value is propagated to the next variable. And when you assign a substring to an empty string, it shrinks, and then the substring from position 2 to 7 is returned (which is now what was in positions 8 to 13). Heh. Still pretty weird anyways, but there is method to the madness. :)
    You have moved into a dark place.
    It is pitch black. You are likely to be eaten by a grue.
      This allows you to replace parts of the EXPR and return what was there before in one operation

      But that's not what this is doing. I'm getting the assigned value or I'm missing something deceptively obvious.
      update
      I had my stupid hat on today.


      -Lee

      "To be civilized is to deny one's nature."
        Ok, here is what I think is happening (according to the examples above):
        $y = 42; $x = $y; substr( $string, 2, 6 ) = ''; $result = substr( $string, 2, 6 );
        The other ways of writing it, $x = $y = 42; and your example are just shorthand ways.

        And perldoc specifically mentions the way when you use a fourth argument instead as an alternative where you can get the replaced values back, unlike the assignment way.


        You have moved into a dark place.
        It is pitch black. You are likely to be eaten by a grue.
Re: Bug with substring return value?
by Juerd (Abbot) on Apr 13, 2002 at 17:33 UTC

    in Perl in a Nutshell it states... "You can also specify a replacement string in the fourth parameter to replace the substring. The original extracted substring is still returned."

    The Nutshell book is right, but you don't use the fourth parameter. You use three parameters, and use substr as an lvalue that can be assigned to.

    # Begin of assignment substr( # Start of substr call, using substr as lvalue $string, # First argument 2, # Second argument 6 # Third argument ) # Anything after this is not part of the substr call = # Assignment operator ''; # Righthand operand of the assignment operator # End of assignment. An assignment returns the assigned value, # '' in this case.
    What you want is:
    substr( # Start of substr call, returning the old stuff $string, # First argument 2, # Second argument 6, # Third argument '' # Fourth argument: replacement text );
    You could have found out by reading substr's entry in perlfunc, which begins with all ways of calling it:
    substr EXPR,OFFSET,LENGTH,REPLACEMENT
    substr EXPR,OFFSET,LENGTH
    substr EXPR,OFFSET

    - Yes, I reinvent wheels.
    - Spam: Visit eurotraQ.
    

      Yeah. I realized that after a couple gentle knocks on the head from Dog_and_Pony. I was just way to tired. I swore I had 4 arguments before I wrote the post. :)

      -Lee

      "To be civilized is to deny one's nature."