Front page | perl.perl6.users |
Postings from September 2017
Re: What is P6 for P5 `use Term::ReadKey`?
From: Trey Harris
September 13, 2017 20:36
Re: What is P6 for P5 `use Term::ReadKey`?
Message ID: CALKJ+Etfn4Y4Fu7fC2dQoiR6_+01-f_bYjMn=koCbfoqFuTiBA@mail.gmail.com
On Sat, Sep 9, 2017 at 3:55 PM ToddAndMargo ToddAndMargo@zoho.com
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
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
L1 is an “ordinary method” (denoted, obviously enough, with the declarator
method), which as described in the Typesystem
<https://docs.perl6.org/language/typesystem#Methods> doc, “defines objects
of type Method <https://docs.perl6.org/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(...).
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).
Now let’s turn to the *return values,* which are what functional
programmers are usually looking at first. They’re marked by --> (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 <https://docs.perl6.org/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*; 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.
(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).
The 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
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
<https://docs.perl6.org/type/IO::CatHandle> and $*IN
<https://docs.perl6.org/language/variables#index-entry-%24%2AIN> 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 <https://docs.perl6.org/> signatures may be
frustrating at first, but it’s well worth it, and pays dividends.