On 09/13/2017 01:36 PM, Trey Harris
wrote:
On Sat, Sep 9, 2017
at 3:55 PM ToddAndMargo toddandma...@zoho.com wrote:
On
09/09/2017 07:00 AM, Timo Paulssen wrote:
> This should be enlightening: https://docs.perl6.org/routine/getc
>
Problem: also from the link:
method getc(IO::Handle:D: --> Str:D)
multi sub getc (IO::Handle $fh = $*ARGFILES -->
Str:D)
This is very frustrating to me as it mean ABSOLUTELY
NOTHING
to me. Without an example, which the link does not
provide,
I have not the slightest idea what they are talking about.
So excuse my going
off-topic here, but I hear your frustration and think you’ll
find it valuable to learn what you need to know to not be
frustrated rather than hoping the docs will over time get
more verbose with sundry examples for each possible use of
language features (it probably won’t, for the most part).
If you’re coming
from Perl 5, which is mostly an explicit-type-less language,
or many other minimally or dynamically-typed languages,
these cryptic lines can be frustrating;
learning-by-example is usually the best way to “grok” a
feature intuitively.
I think it’s
important to learn to read them, rather than simply ask for
examples (as drove most of the P5 perldoc for builtins). To
explain why: in Haskell, a language which greatly influenced
Perl 6, the type declarations alone are often all the
Haskell programmer needs to fully understand a function;
prose or examples are entirely superfluous. The power of
well- and expressively-typed routines for documentation is
inarguable in efficiency, precision, and concision. The
downside is the necessary investment in overcoming the
learning curve required to read them.
To return to the
lines that frustrated you, let’s try to make them
understandable—or, at least, make them mean more to you than
“ABSOLUTELY NOTHING”. :-)
Let’s start at a
high level:
method getc(IO::Handle:D: --> Str:D) # L1
multi sub getc (IO::Handle $fh = $*ARGFILES --> Str:D) # L2
You see getc
defined twice here; they’re each distinct code (that are
documented once because they do much the same thing) due to
their declarators.
L1 is an “ordinary
method” (denoted, obviously enough, with the declarator method ),
which as described in the Typesystem doc, “defines
objects of type Method and binds them to the
provided name in the scope of a class.” An ordinary method
is usually called using dot syntax, i.e., $object.getc(...) .
Okay. Where did "$object" come from?
It would help if it was written out in long hand so as to explain
what the "." does. Still have to have an example to figure out
what is going on.
L2 is a “multisub”,
that is, a sub handled via “multi-dispatch” (in most
languages with the concept, called multimethod dispatch).
Multi-dispatch allows a single routine name to refer to
different code (“polymorphism”) on axes other than the
traditional object-oriented paradigm of “invocant” to
include number, type, definedness, and even value of
arguments at call time. (In this case, there being only one,
it may seem superfluous, but it allows for other modules to
introduce getc
variants of their own without having to invent new names or
muck about with namespaces.) Being a sub, it will be called
most often using normal sub-calling syntax, such as getc($x) .
Is $x called $object above?
Now let’s turn to
the return values, which are what functional
programmers are usually looking at first. They’re marked by
-->
--> means some kind of pointer to me. "returns" would be much
better wording for me, but at least
I know what they are getting at.
(though some old
documentation may use returns ).
Conveniently, both variants L1 and L2 return the same thing
(not uncommon, for multi routines): Str:D .
The Str
part is a reference to the string type Str. The :D
suffix says that the value is defined; in other
words, getc
will never return the undefined value. (A :U
suffix would indicate that the return is always undefined;
I would love a reference to all that Str:D stuff that defined that
kind of stuff.
Do you mean "can be undefined"? Always "undefined" would be
useless.
the default, a lack
of any suffix, can be made explicit with :_ ,
and means—as in Perl 5—that the return might or might not be
defined.)
That gets you to the
arguments of the two variants. Each are unary;
they take just one argument.
Okay, where?
(In the case of the
method, its arity depends on your definition of the invocant
being an argument; if you subscribe to the view that a
method’s invocant doesn’t count, then method getc
is a nullary, taking no argument. But the view that the
invocant counts as an argument is useful here, so let’s use
that definition, making the two both unary routines.)
Both routines’
single argument is of type IO::Handle .
They also both require definedness, but in different ways.
The method uses the :D
suffix we’ve already seen; in effect, that allows $my-handle.getc
to work provided $my-handle
has been set to a defined IO::Handle object. But if the
variable was declared with my IO::Handle $my-handle;
but never assigned to, $my-handle.getc
will not work; neither will IO::Handle.getc
(which would work if :D
weren’t included in the signature; one way of getting “class
methods” in Perl 6 is to create methods with :U
invocants).
he multisub L2 also
requires definedness, but does it in a different way. The IO::Handle $fh ,
by itself, doesn’t rule out an undefined argument being
assigned to the $fh
parameter, but the default value expressed by = $*ARGFILES
ensures that an omitted or undefined argument will cause $fh
to be assigned the value $*ARGFILES. (The $*
notation is used to refer to global variables; you can look
up the definition of $*ARGFILES
to see it is
An IO::CatHandle
that uses @*ARGS as source files, if it contains any
files, or $*IN otherwise
and you can also
look up IO::CatHandle and $*IN in the docs if you want to
know more).
The point of all
this is to not require exhaustive examples to show you
possible ways of calling getc ;
you just need to know how to unlock the code.
Putting it all
together, it tells you that these are valid examples:
my Str $chr = getc($*IN); # insist on STDIN, even if file arguments were given on the command line
$chr = "/dev/tty".IO.open.getc; # Insist not just on STDIN, but on the POSIX tty
Learning to read the
Perl
6 doc signatures may be frustrating at first, but it’s
well worth it, and pays dividends.
What in the world is "my Str $chr"?
If returning a type String, why are you using "chr". I though Perl
had no defined character type.
I can see that, I would still need examples. I was very puzzled
about what you meant
until your last two line, which made everything make sense.
How you got from
multi sub getc (IO::Handle $fh = $*ARGFILES --> Str:D)
to
chr = "/dev/tty".IO.open.getc;
is a complete mystery. How I am suppose to know
"(IO::Handle $fh = $*ARGFILES" means it wants a file handle?
This is what I "think" you just said:
method getc(IO::Handle:D: --> Str:D)
1) Requires an IO handle that can not be undefined
2) Returns a string an is never undefined.
example: my $Str = getc($*IN); # $*IN is STDIN
multi sub getc (IO::Handle $fh = $*ARGFILES --> Str:D)
1) "multi" means each sub's results are passed to the next
sub in line
2) Requires you create a handle for it ("filename".IO.open)
3) Returns a string an is never undefined.
example: my $Str = "/dev/tty".IO.open.getc;
and $*&# is just Yosemite Sam cussing.
Thank you for trying to break through the fog
-T
|