On 04/30/2018 07:15 AM, Bruce Gray wrote:

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.


Thank you!


Okay, let me summarize to see if I understand it correctly:

.sub is a method call and I can't write them.  They come with Perl.

But I can simulate them with `.&`

so, this would work

sub  odd( $Num ) { return $Num % 2; }
sub even( $Num ) { return not $Num.&odd; }

Reply via email to