> On Apr 30, 2018, at 8:04 AM, ToddAndMargo <toddandma...@zoho.com> wrote:
> 
> Hi All,
> 
> I am confused.
> 
> With this sub:
> 
>    sub odd( $Num ) { return $Num % 2; }
> 
> 
> Why does this work:
> 
>     if odd $LineNum
>              { $PartsStr ~= '<font color="#006600">'; }  # Green
>        else  { $PartsStr ~= '<font color="#663366">'; }  # Purple
> 
> And this one throw an error:
> 
>     if $LineNum.odd
>              { $PartsStr ~= '<font color="#006600">'; }  # Green
>        else  { $PartsStr ~= '<font color="#663366">'; }  # PurpleNo
> 
>       No such method 'odd' for invocant of type 'Int'. Did
>       you mean 'ord'?
> 
> What is my misunderstanding?
> 
> 
> Many thanks,
> -T

Short answer: Defining a sub does not define a method. There is a work-around, 
though: `.&`

(Simple primer: A `sub` is named code that can be called on any bits of data 
you choose as arguments. In OO, a `method` is named code that is part of a 
class, and can only be called via an object of that class.)

Detail:
Perl 5 had built-in `functions`, i.e. subs that were provided by the base Perl 
language:
    $m = sin $x;
    $n = abs $y;
    push @z, 15;
See `perldoc perlfunc`, or https://perldoc.perl.org/perlfunc.html .

In Perl 6, the equivalent functions are implemented and available as *methods*, 
but are also exported as subs, to allow for fluidity between procedural and OO 
styles of programming (and also less stress for the Perl 5 coders wading into 
the Perl 6 pool):
    New method form:
        $m = $x.sin;
        $n = $y.abs;
        @z.push(15);
        @z.push: 15;
    Old functions still work though:
        $m = sin($x);
        $m = sin $x;
        $n = abs($y);
        $n = abs $y;
        push(@z, 15);
        push @z, 15;
Outside of this special case, an OO API that double-provides its methods as 
subs is usually a bad idea. You *can* do it, using the same trick as the Perl 6 
built-ins: add `is export` to your method definitions.
(But please don't, unless you are *sure* that the confusion and name-space 
pollution and collisions are justified by the definite needs of the API users.)

The reverse path is not provided for; you cannot define a sub and automatically 
get the method form. This is quite correct for OO design; to do otherwise 
implies that you are shoving new methods at run-time into the very top base 
class (the evil MONKEY-PATCHING)!
Not being able to call your sub via method-call-syntax, well, it only looks so 
glaringly inconvenient from the ground floor of language use.
...which is where most of us are!

So, a bit of syntax is provided, as a sop to us who insist that this:
    say MySumTwister( MyWickedSub( %h.keys.grep(*.so)».sqrt.sum ).abs );
would look better as:
    say %h.keys.grep(*.so)».sqrt.sum.MyWickedSub.abs.MySumTwister;
You *are* allowed to write it in method form (and keep the reader's eyes from 
having to jump back-and-forth) with `.&` instead of `.` , like so:
    say %h.keys.grep(*.so)».sqrt.sum.&MyWickedSub.abs.&MySumTwister;


This syntax is listed as "postfix .&", and can be found here:
    https://docs.perl6.org/language/operators#postfix_.&;

So. `.` calls a method, and `.&` calls a sub as if the sub were a method.

-- 
Hope this helps,
Bruce Gray (Util)

Reply via email to