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

I have the following problem that I need help with. I have a module with the following function in it:
sub GetSSNameFromFile( $\$\$ ) { my $s_InputFile = $_[ 0 ]; my $rs_OutputFile = $_[ 1 ]; my $rs_RecurseLabel = $_[ 2 ]; my $s_SSDataDir = "$ENV{ SSDIR }\\data"; ++$$rs_RecurseLabel; ...
It is called with the following code:
GetSSNameFromFile( $sFile, $sRealName, $sRecurseLabel );
where all parameters passed in are standard my scalars. When I run the code, I get the following error:
Modification of a read-only value attempted at D:\dlkusters\vsstools\v +sstools/VSS/Utils.pm line 102.
The line specified is the unary increment on $rs_RecurseLabel. What exactly is a read-only value in perl and why is $rs_RecurseLabel one? What am I doing wrong and how do I fix it?

I bow at the monastery alter for guidance...

Dave

Replies are listed 'Best First'.
(tye)Re: References, Prototypes, and read-only values
by tye (Sage) on Feb 28, 2001 at 01:09 UTC

    $rs_RecurseLabel isn't read-only, $$rs_RecurseLabel and $sRecurseLabel are. They could be for several reasons. How do you declare $sRecurseLabel?

    Also, if your prototype isn't seen by the calling code, this could cause lots of interesting problems. You should use the debugger (or debug print statements) to report what @_ looks like when that routine is called.

            - tye (but my friends call me "Tye")
Re: References, Prototypes, and read-only values
by arturo (Vicar) on Feb 28, 2001 at 01:11 UTC

    I'll admit to being stumped by this one. Your prototype forces the second and third arguments to start with $,and typically a read-only value is a constant (take a peek through perldoc perldiag for your exact error message (minus line numbers) and you'll see the typical scenario in which this error arises).

    I'm not going to cry 'perl bug!' though, because I'm just not *that* familiar with prototypes and how Perl does 'em. But what say you put in the following modification and see what happens:

    sub GetSSNameFromFile { my ($s_inputFile, $rs_OutputFile, $rs_recurseLabel) = @_; # as before $rs_recurseLabel++; # .. as before }
    Getting rid of the prototype might at least help track down the problem.

    Ooops, hold it! I didn't read the original code closely enough. You're trying to increment the thing to which $rs_recurseLabel *refers* Take a sack of salt with this one ... (but I'll still hold to "why put the prototype in?". In the chatterbox, tilly thoughtfully provided a link to this piece by Tom Christiansen, which is an illuminating document on Perl prototypes and their attendant gotchas))

(ichimunki) re: References, Prototypes, and read-only values
by ichimunki (Priest) on Feb 28, 2001 at 01:23 UTC
    Do you have "use strict;" at the top of this script? I can reproduce your error. But when strict is added I get a warning about a reference in the line with the increment. You probably have a numerical value in $rs_RecurseLabel, which is not valid in a reference such as $$rs_RecurseLabel.

    Addendum: As I play with this further, I see tye is correct. Something is goofy with the prototyping. You must declare prototyped subs before the code that calls them. When I put the calling code after the prototyped sub, the prototype automatically creates a reference to your variable and the read-only error goes away. When the sub is after the call, I can get your same error. Also, it is not idiomatic to modify parameters in place like this, especially with nothing in the function call to specify that the third parameter will be treated as a reference. You may want to explore a different approach, such as changing the value via a return value.
Re: References, Prototypes, and read-only values
by dkusters (Initiate) on Feb 28, 2001 at 02:44 UTC
    Well, after reading Tom Christiansen's thoughtful rant on prototypes, I'm inclined to agree with him. I fixed this problem, but the experience is worth telling. The real problem was not in the original code, but in a line in the GetSSNameFromFile subroutine. Near the end was the following line of code:
    GetSSNameFromFile( $s_ParentFileName, $$rs_OutputFile, $$rs_RecurseLabel );
    You see, this is a recursive function. The scalar $$rs_RecurseLabel is essentially a count of our current recurse depth. That explains why I'm incrementing it when I first enter into the function. But, the real problem I believe was caused by this call. I don't know exactly why, however. I simply switched from the implicit reference creation by the prototype to not using prototypes. I handle the references myself using hard references. This seems to fix the problem. One nicity of this approach is that the above code now becomes:
    GetSSNameFromFile( $s_ParentFileName, $rs_OutputFile, $rs_RecurseLabel );
    I just pass the hard reference.

    Thanks for the replies,

    Dave

      I believe the reason that the recursive call causes the error is that when you're inside the function, the function is not defined yet. Thus, the recursive call does not see the prototype and thus does not automatically pass the parameter by reference. (See also ichimunki's reply.)

      You could probably fix that and keep the prototype (if you wanted, though it's probably best to ditch the prototype anyway) by changing your recursive call from:

      GetSSNameFromFile ( $s_ParentFileName, $$rs_OutputFile, $$rs_RecurseLabel );
      To:
      GetSSNameFromFile ( $s_ParentFileName, $$rs_OutputFile, $rs_RecurseLabel );

      Don't quote me on that, though. I'm not 100% sure that would work (I didn't test it).

      bbfu
      Seasons don't fear The Reaper.
      Nor do the wind, the sun, and the rain.
      We can be like they are.

Re: References, Prototypes, and read-only values
by AgentM (Curate) on Feb 28, 2001 at 01:13 UTC
    Are you sure that you pass the recurselabel by reference (prototypes in perl guarantee next to nothing)? Perl would most likely not enjoy incrementing its internal references. Perhaps this is the problem? All we can do is really guess since it is unclear which value is actually passed. Be sure that you are using strict and the other diagnostic tools- perhaps even fire up that dusty perl debugger...
    AgentM Systems nor Nasca Enterprises nor Bone::Easy nor Macperl is responsible for the comments made by AgentM. Remember, you can build any logical system with NOR.