Mark VY
Mark VY

Reputation: 1671

In Perl, why can't I bless a variable which contains a reference to a literal?

I've been trying to learn Perl for a few days, and am still frequently surprised and sometimes mystified at how and why it does things. Here is my latest puzzle: why are the following two blocks of code not equivalent?

my $thing = '';
bless \$thing; # class is implicit

versus

my $thing = \'';
bless $thing; # class again implicit

The second form says "Modification of a read-only value attempted" on the second line.

Upvotes: 3

Views: 697

Answers (2)

Sinan Ünür
Sinan Ünür

Reputation: 118128

\'' is a reference to a literal.

\$thing is a reference to $thing. The value of $thing is set to the empty string at the moment.

The reason for the error you are getting is the same as the reason the following will give you the same error:

my $thing = \5;
$$thing = 10;

bless modifies the thing to which its first argument refers. In this case, and in yours, $x refers to something that is not modifiable.

See perldoc perlobj:

Objects Are Blessed; Variables Are Not

When we bless something, we are not blessing the variable which contains a reference to that thing, nor are we blessing the reference that the variable stores; we are blessing the thing that the variable refers to (sometimes known as the referent). (emphasis mine)

If you want a class backed by a scalar, you can do this:

#!/usr/bin/env perl

use v5.10;

package MyString;

use strict; use warnings;

sub new {
    my ($class, $self) = @_;
    bless \$self => $class;
}

sub content { ${$_[0] }
sub length { length ${$_[0]} }

package main;

use strict; use warnings;

my $string => MyString->new("Hello World");

say $string->$_ for qw(content length);

Of course, you need to exercise discipline and not modify instance data through the backdoor as in $$string = "Bye bye cruel world".

Upvotes: 5

Borodin
Borodin

Reputation: 126722

The bless operator works through a reference: it is the referenced object that becomes blessed. Most often the referenced data is a hash, but as you've found it may also be a scalar or any other Perl data type

my $thing = '';
bless \$thing; # class is implicit

This is fine. You are setting $thing to an empty string (which is irrelevant here) and you are blessing it by passing a reference to it to bless

my $thing = \'';
bless $thing; # class again implicit

This sets $thing to a reference to a string constant, so the bless is then attempting to work on that constant which is impossible because, as the message says, it is read-only

In short, in the first case you are blessing the scalar variable $thing while in the second case you are trying to bless string constant '' which fails

Upvotes: 4

Related Questions