Beefy Boxes and Bandwidth Generously Provided by pair Networks
Don't ask to ask, just ask
 
PerlMonks  

Re: Using perlclass 'methods'

by haj (Vicar)
on Jul 18, 2024 at 07:32 UTC ( [id://11160669]=note: print w/replies, xml ) Need Help??


in reply to Using perlclass 'methods'

A method in Perl always needs to be told on which object instance it should operate. Your call to ratio is missing that, it should be $self->ratio - and that's it. $self is a variable which is automatically available in a method and it holds the "current" object, which is what you want.

The error message is indeed cryptic for the modern Perl style you are using. It comes from the way Perl passes arguments to its subroutines (and methods): The object on which a method operates is simply passed as its first parameter. So, if you call ratio without the invocant, then the method will interpret the first parameter 26 as the object. The message would be clearer written as say Can't use string ("26") as an object. The current text and its reference to "strict refs" comes from an old feature of Perl which should not be used at all in new code... so maybe we could convince the Perl devs to change that text.

Edit: The code had a typo (self->ratio should read $self->ratio).

Replies are listed 'Best First'.
Re^2: Using perlclass 'methods'
by kikuchiyo (Hermit) on Jul 18, 2024 at 08:07 UTC

    This is not the correct explanation. Deparse helps:

    unexpected OP_METHSTART at /usr/share/perl5/B/Deparse.pm line 1674. unexpected OP_METHSTART at /usr/share/perl5/B/Deparse.pm line 1674. sub BEGIN { require v5.38.0; () } use warnings; use strict; no feature ':all'; use feature ':5.38'; use experimental ('class'); BEGIN {${^WARNING_BITS} = "\x55\x55\x55\x55\x55\x55\x55\x55\x55\x55\x5 +5\x55\x55\x55\x55\x55\x55\x55\x55\x51\x55"} use feature 'class'; { package Gear; ; sub ratio : method { XXX; return $chainring / $cog; } sub gear_inches : method { XXX; return ratio(*$rim + $tire * 2); } } say 'Gear'->new('chainring', 52, 'cog', 11, 'rim', 26, 'tire', 1.5)->g +ear_inches;

    (I had to modify the code a bit because I don't have 5.40)

    So it takes everything that comes after the method name as the argument, so the * is interpreted as a glob dereference.

    Note that B::Deparse also struggles with the new class feature.

      Thanks for the fix!

      This is also a showcase some quirks of the Perl language:

      • Parentheses are optional after method and subroutine calls. A method needs at least one parameter, and it was not provided with the $self-> syntax, so Perl picks up whatever comes next.
      • The * is a valid (but fortunately rarely used these days) sigil. It is not a multiplication here, but indicates a glob reference.
      • Really quirky: Spaces are allowed between a sigil and its identifier. So the identifier of * $rim is $rim, which is a symbolic reference.

      use v5.40.0 implies "strict refs", so Perl complains about *$rim even before trying to use it as the invocant of the method (as I originally thought).

Re^2: Using perlclass 'methods'
by bliako (Abbot) on Jul 18, 2024 at 09:07 UTC

    I don't have this new perl version to experiment. But I would expect that WITHIN a class calling a method name would automatically assume it is $self->ratio() (C++ and Java do that). If this is not the case, then why not dispensing the "usual" message: Undefined subroutine &main::ratio. It seems to me this class feature is half-baked and with old materials. And will lead to confusion in debugging.

      It seems to me this class feature is half-baked

      There is a reason why it is experimental. I understand the rationale given by those who have been advocating it but I only partially agree with it. There doesn't seem to be anybody suggesting that this new feature should be used in production.

      I am more than happy to keep using "classic" OOP and reach for one of the light frameworks available on CPAN on those occasions which warrant something a little more sugary.


      🦛

        oops sorry, i forgot it is experimental. Right.

      C++ and Java do that, but Python does not. Python was the main inspiration for Perl's OOP, and it also requires methods to be invoked via self, even within the class.

      Simple things first: It is not the message Undefined subroutine &main::ratio because we are not in package main but in a class Gear where the method is defined.

      Whether Perl could imply $self->ratio when a method is called without an invocant is an interesting question. I guess it is a real challenge to the interpreter: It needs to figure out that ratio is a method and not a sub. As far as I know, this is not possible today. Whether this insurmountable, I can't say. Perhaps we should open an issue for Perl?

      And... of course the class feature is half baked. It is rather new and will take time to mature. For this issue, it behaves like all other OO systems in Perl. It could do different because it has the class and method contexts which the other systems don't have. Perhaps it will, at some point in the future?

        Simple things first: It is not the message Undefined subroutine &main: +:ratio because we are not in package main but in a class Gear where t +he method is defined.

        I assumed that if it does not find ratio() as a method in class then it goes to main looks there. Given that a method always requires its object (e.g. $self->ratio()) then I thought the reasonable thing would be to assume that this is a sub in main. Fair enough. (also I missed the experimental bit, so we shall see). Edit: Oh but it does not know that the object is not preceeding the method, it asusmes that the object is there, that's why it looks further ahead in the multiplicative factors.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://11160669]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others cooling their heels in the Monastery: (5)
As of 2024-09-15 03:20 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    The PerlMonks site front end has:





    Results (21 votes). Check out past polls.

    Notices?
    erzuuli‥ 🛈The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.