http://qs1969.pair.com?node_id=1153807


in reply to Readonly oddity

> ... with these versions of Perl and Readonly ... it (fails silently)
> the ... script breaks ... with Perl 5.14 and Readonly 1.03

The script with Perl 5.20/Readonly 2 looked broken to me too, but I now understand that instead of failing silently the older Perl/Readonly refused to run and probably issued an error message like:

Type of arg 1 to Readonly::Readonly must be one of [$@%] (not scalar a +ssignment) at monk_ro.pl line 8, near "'bar';" Execution of monk_ro.pl aborted due to compilation errors.

So allowing assignment to run and leave an undef value seems at first to be a new surprising feature (bug) with Readonly.

On looking closer at the problem the change is, as tangent suggested, more because of changes in Perl than in Readonly. With Perl 5.14 I get the same error whether I use Readonly 1.03 or 2. If I use Perl 5.22 then Readonly 1.03 gives the same silent/undef behavior as Readonly 2.

Readonly uses subroutine prototypes and there has been a change in subroutine prototype behavior with newer versions of Perl. As described in proto documentation, both 5.14 and 5.22 allow:

perl -Mstrict -we 'sub f(\$){}; f(my $x)'

Newer Perls also allow:

perl -Mstrict -we 'sub f(\$){}; f(my $x = 3)'

whereas in Perl 5.14 the above code gives the familiar looking error:

Type of arg 1 to main::f must be scalar (not scalar assignment) at -e +line 1, near "3)

The new behavior seems to me to be a reasonable extension from a language perspective but, even if Perl is causing the change, one result of the new proto behavior in Perl is a change in the behavior of Readonly that I understand to be undesirable even if it makes undocumented use of the module. I agree and understand the mistake could be easy to make.

In the original post the poster asked:

> Is this a known problem?

I did not see it listed under the CPAN/git module issues or anything in RT. There is an odd hint added to the documentation for Readonly 2 that wasn't in the older documentation.

Readonly $var;
...
Note that you can create implicit undefined variables with this function like so Readonly my $var; while a verbose undefined value must be passed to the standard Scalar, Array, and Hash functions.

So allowing for a Readonly scalar with a default value of undef is now documented as allowed. "Readonly my $var;" actually worked with Perl 5.14 and Readonly 1.03 too.

The original poster had two suggestions:

I played with patching Readonly.pm both ways and view either to be feasible. For somewhat complicated reasons that sort of boil down to extensive efforts by the Readonly code bending over backwards to be backward compatible, I am somewhat in favor of the first approach of issuing an error for this usage.

In summary, I feel a bug report for the module is merited by the problem but would be interested in feedback from other monks.

A sample patch for the problem for Readonly 2 is included for informational purposes. It passes the test suite but shouldn't be applied by anyone depending on the module.

*** lib/Readonly-orig.pm 2016-01-27 11:21:02.875021600 -0500 --- lib/Readonly.pm 2016-01-27 19:12:43.312714100 -0500 *************** *** 298,303 **** --- 298,305 ---- my $badtype = _is_badtype (ref tied ${$_[0]}); croak "$REASSIGN $badtype" if $badtype; croak "Readonly scalar must have only one value" if @_ > 2; + croak 'You meant $sca => $val not $sca = $val' + if @_ == 1 && defined ${$_[0]}; my $tieobj = eval {tie ${$_[0]}, 'Readonly::Scalar', $_[1]}; # Tie may have failed because user tried to tie a constant, +or we screwed up somehow.
Ron

Replies are listed 'Best First'.
Re^2: Readonly oddity
by SankoR (Prior) on Feb 01, 2016 at 22:43 UTC

    The haphazard syntax of Readonly (not to mention its dueling APIs) trips up more people and generates more email than any of you guys can imagine... An extra warning that perl itself no longer throws may help clear up some of the 'weird' things people run into so I'll take this patch.

    Generating a new fatal error though may 'break' a lot of code. Then again if they were using this incorrect syntax their code was already broken, right? ((sigh)) I'll push it to PAUSE as a dev build for a few weeks. At the end of February (or March), I'll make it stable along with the mutable clone stuff I wrote almost two years ago.

    Edit: Well! It's a minor change but I like giving credit where it's due so please feel free to submit a pull request here.