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  

Reply via email to