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

I have some code which was generated from SCL to PERL. It produced the following line.
substr($DATE, 2, 5) = $YEAR . $MONTH;
My first thought was that this would do nothing. I was wrong it didn't do what was expected but it did do something. When put into this context
$YEAR = "2005"; $MONTH = "06"; $DATE = "20050608"; substr($DATE, 2, 5) = $YEAR . $MONTH; print $DATE; #output 202005068
I'm not asking how to fix it I just wont to know how its doing whats its doing now?

UPDATE
It wasn't so much what it was trying to do as how it was doing it. The orginal SCL code from the mainframe did the same and was wrong as well. Thanks to all for explaining what is happenning.

The joke is the SCL code was passing the resulting $DATE to a utility to get the days since 1900. It was failing, however the code was last run in 2002 and the ops. here think it failed then as well. Historic conversions don't you just love um.....

Replies are listed 'Best First'.
Re: What is substring working on here.
by BrowserUk (Patriarch) on Jun 09, 2005 at 15:15 UTC

    The code is using substr as an lvalue. That is, on the left-hand side of the assignent operator '='. What that does, is it replaces the substring denoted by the parameters to substr, by whatever is assigned.

    So, in your example, substr( '20050608', 2, 5 ) represents the sub string '..05060.'.

    The value being assign is '2005' . '05'

    The result is that dots in '20.....8' get replaced with '200506' giving '202005068'.

    But then, maybe the question you're asking is "Why is the code doing this?" -- in which case: Sorry, I have no idea, it doesn't seem to make much sense.

    Maybe it's a coding error and the intent would be clear from some more context?

    Example: It might be an (erronously coded) attempt to convert US-style date formats (month/day/year) to Euro-style (day/month/year), but without context there is no way to tell.


    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
    "Science is about questioning the status quo. Questioning authority".
    The "good enough" maybe good enough for the now, and perfection maybe unobtainable, but that should not preclude us from striving for perfection, when time, circumstance or desire allow.
Re: What is substring working on here.
by gellyfish (Monsignor) on Jun 09, 2005 at 15:11 UTC

    An lvalue substr as you have there replaces the specified characters in the target string with those that are being assigned, as you can see from your output - however I'm not so sure on the purpose of what it is actually doing in your example.

    /J\

      The two and three arugment forms of substr return an lvalue (something to which one can assign). When something is assigned to this particular lvalue, it triggers some code in perl's guts gets called which causes the original string to be modified.

      I've been told by an esteemed monk or two that the 4 argument form of substr is more efficient than using it as an lvalue.

      Replace
      substr($str, $start, $length) = $new_sub_str;
      with
      substr($str, $start, $length, $new_sub_str);
      for a performance boost.

      Its a mess from start to finish and investigation of the orginal code showed the SCL to be incorrect as well. I just didn't understand how this worked at all. Thanks for you help.
Re: What is substring working on here.
by robartes (Priest) on Jun 09, 2005 at 15:16 UTC

    As gellyfish correctly states, substr() is being used as an lvalue here, i.e. something you can assign to. In this case, you are replacing five characters (the third argument) of $DATE, starting at position two (the second argument, and counting from 0) with the concatenation $YEAR.$MONTH. Hence the output you observe.

    CU
    Robartes-