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; }