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

I am trying to work my way through perlboot. I thought I had got my head around bless, but please don't take that for granted. At the point where it is first used, I have a problem. The code I have copied in from the tutorial is:
use strict; { package Animal; sub speak { my $class = shift; print "a $class goes ", $class->sound, "!\n"; } } { package Horse; our @ISA = qw(Animal); sub sound { "neigh" } } my $name = "Mr. Ed"; my $horse = \$name; bless $horse, Horse; $horse->speak;
I have added the first and last lines. This gives an error
Bareword "Horse" not allowed while "strict subs" in use at C:\Data\per +lbootqry.pl line 17. Execution of C:\Data\perlbootqry.pl aborted due to compilation errors.
Taking out Strict gives a different error: a Horse=SCALAR(0x1829afc) goes neigh! While this isn't a syntax error, it's not what I was expecting from reading the tutorial. Advice on what I'm doing wrong would be greatly appreciated.

It may be explained later in the tutorial, but something that bothers me is that all the sounds are subs. I would expect them to be scalars, but when I tried changing them I got nowhere. If all will become clear in due course, that's great, but if I'm heading for more confusion, please could someone point me in a more profitable direction?

Regards,

John Davies

Replies are listed 'Best First'.
Re: Code from perlboot not working as expected
by kennethk (Abbot) on May 17, 2010 at 13:19 UTC
    The short answer is change bless $horse, Horse; to bless $horse, 'Horse'; and it will behave as expected.

    bless takes the package name in as a string. Without strict, the bareword would be interpreted into that context. Unfortunately, a good link to explain this escapes me at the moment.

      Thanks. Putting in the single quotes means I can leave Strict in. But I'm afraid it doesn't clear the SCALAR part of the output. If anyone can help in that direction, I'd love to know more.

      Regards,

      John Davies
        Ahh, I missed that part of the OP - sorry. That's happening because the first object in @_ when you invoke a method via an object is the object, not the package name. Thus your $class variable contains the scalar reference and when you print $class you stringify that reference. One way of handling that is to use ref. Something like:

        my $self = shift; my $class = ref($self) || $self;

        If $self contains a blessed reference, ref will return the package name. If it contains a string, ref will return undef and hence the || will return the original string.

        I personally prefer perltoot to perlboot. But both are certainly worth working through.

        $class is a reference to the object and I believe that's what you get when you print out a reference. Just dereference it (note the double $): print "a $$class goes ", $class->sound, "!\n"; Kevin Sigl
Re: Code from perlboot not working as expected
by JavaFan (Canon) on May 17, 2010 at 13:17 UTC
    You are combining the class methods with object methods. The subs you've given were introduced when perlboot is still talking about class methods. After it introduces objects, it's changing the subs accordingly.
      I'm afraid I still don't see what I've done wrong. The code I have used comes in three blocks, but it all fits in a single screen on my browser. The relevant section is
      A horse is a horse, of course of course, or is it?
      and I see nothing in it about class versus object methods, nor any suggestion that the code needs to change. The only change I have made (apart from the two lines mentioned previously) is the "our", which the tut seemed to indicate I should put in. But I've tried taking it out and taking Strict out, and with all four combinations I still get the SCALAR reference in the output. If you could give me any further clues, I'd be most grateful. In case it's system dependent, I'm using ActiveState v5.10.0 on Losedows XP Home.

      Regards,

      John Davies
        Eh, no, that's not the only change. The big, fundamental change is that you are taking subs that are intended to be called as class methods, (Class -> subname), but call them as object methods ($obj = bless $ref, Class; $obj -> subname). Big difference. A difference that's about to be introduce around the point you copied and pasted from perlboot. The fact you don't quote the second argument to bless cause the strict error; the fact you call a class method as an object method gives you the funny animal name.