Hacker News new | past | comments | ask | show | jobs | submit login
Haskell to Perl 6 (perl6.org)
99 points by voihannena on Dec 8, 2018 | hide | past | favorite | 133 comments



Perl 6 is for people who are very smart and have a great spirit in seeking and having fun in programming, I really admire that. That's my thought after two failed attempts (each lasted about two days) to learn it in 2012 and 2014. I felt the use of sigils, syntax oddities and the cleverness were beyond my ability to master the language. I should mention in 1998 I used (modified it a little bit) Selena Sol's shopping cart script. Since then I have only written a few small Perl 5 scripts, am not familiar with recent development. To learn Perl 6 today, what kind of practice projects/applications, or approaches, one can use?


> Perl 6 is for people who are very smart and have a great spirit in seeking and having fun in programming

Not sure why you felt the need to include this. How did you come to this conclusion? Is this in comparison to Haskell, or what?


It was tongue in cheek, haha... I was only frustrated by my own inability to get the hang of Perl 6. As an old casual fan of Perl, I still want to take another shot at learning it very much.


The perl6intro website shows you the essentials of what you need and the ecosystem has matured a lot since 2014 as well as many good books being published. Laurent Rosenfield has a Think Perl6 book that you can buy in paper or read online for free. If you can already code, getting proficient in basic Perl6 is easy. Becoming a master is outside my current grasp.


Thanks for the recommendations.

One liners are fun, and life-saving. I am curious about this aspect compared to Perl 5. With Perl 6's new syntax and language features, can we still easily [ab]use one liners for fun and profit?


Cons:

* Rakudo -- the only P6 compiler for now (and likely many years, maybe forever) -- has a slow startup, around 0.1 seconds or so.

* Rakudo is still a work in progress. What's done is pretty solid but, for example, no one has implemented the `-a` awk/autosplit command line option (cf https://gist.github.com/raiph/1d0cbefcb3cfe45b0b906282e6e405...) and command line usage is currently `use strict;` by default so you have to declare variables with `my`.

* Pros

P6 makes for sweet oneliners...

25 one liners being written up this month: https://perl6.online/category/advent-calendar/

9 categories last updated a year ago: https://github.com/dnmfarrell/Perl6-One-Liners

https://www.google.com/search?q=perl6+oneliners https://www.google.com/search?q=perl6+one+liners


Personally, over time I fully expect it to beat P5 in mostly everything given enough time.


Perl 6 feels a bit "ad hoc" to me... It looks like it has very interesting features but it lacks the uniformity present in most languages...


Instead of "ad hoc", think of it as a multi-paradigm language.

From that viewpoint, I think there is a fair bit of beauty in being able to pick and choose your approach based on the problem at hand without worrying if that is an idiomatic choice dictated by language designers. P6 goes to great lengths to give you all the expressiveness you could hope for, regardless if you are doing functional, OOP, or dealing with concurrency etc...


Perl has never been about uniformity.

Perl is a great experiment in language design, or, rather, a battery of experiments. It's the opposite of a cleanly designed language.


No, it's designed. It's just not designed the way everyone expects a computer language to be designed. It was designed by a linguist. He produced a language with some of the flexibility (and messiness) of human languages, which is completely foreign as a goal to other languages.

One of the places this shows up to me is being able to say "it" (in essence). That is, we humans, when talking to each other, we say things like "Read in a line of input. If it looks like an XML tag, pass it to the XML handler function". But you can't talk to a computer that way. The computer says, in effect, "Read in a line of input from where? And put it where? And what do you mean 'if it ends in a newline'? If what ends in a newline?"

But in Perl, you can write it just like the humans say it, and Perl says, "Well, you didn't say where to read the input from, so I assume I should read it from the standard place (which is perfectly well defined in Perl). You didn't say where to put the line of input, so I'll put it in the default variable. You didn't say what to check to see if it looks like an XML tag, so I will check the default variable." The default variable, essentially, plays the role of "it" in human language.

And the whole language is like that. There are shortcuts that work most of the time, and precise ways of saying things that work when the shortcut isn't what you want. And what the shortcut does is well defined (in the docs; it can be very opaque in code).

None of this makes Perl an ideal language. But it has a perspective on language that is (as far as I can tell) unique among programming languages. It is only fair to judge the coherence of the design within the framework of what Perl is trying to be.


Except the resulting code will look nothing like “the humans say it”, and instead will be a cryptic charade requiring a ton of knowledge to decipher - ending up being neither natural language nor machine code.


The linguistic target Larry Wall aims at has little to do with uttering the line of code out loud..

The attempt to mirror human language is in the flexibility of the constructs. This is the much maligned There Is More Than One Way To Do It (TMTOWTDI) principle.

The language is designed to allow the programmer to express themselves in they way that makes the point best for their brains.

Now, this is almost a classical debate in programming at this point but it was really in high gear during the late 90s as Python's One Way approach quickly proved more useful for larger codebases, in contrast to the personalized anarchy of styles often found in a large Perl project.

Perl 6 changes the landscape of "personalizable programming language" considerably, making it less complex in some ways and more complex in others.

Whether or not TMTOWTDI is a boon or a bane to you is your choice. I find that having a language that is designed for personal expression is precisely the thing I want when I am reaching for scripting glue.


Hmm, interesting. TMTOWTDI is great for a small (one person) script, and One Way is better for a large (multi person) code base? That seems very plausible.


I think it is rather more related to team size than codebase size, really.

Think of how much can be done with a small group of people who all speak the same dialect / lingo. If everyone is on the same page WRT code style, then TMTOWTDI is just the magic that allowed you all to arrive on the same stylistic page.

Perl 6 is much better than Perl 5 in this because some of the styles that ossified in the Perl 5 dinosaur brains are truly grotesque to behold when deployed in the 21st century.


The downside of TIMTOWTDI is that the next person that comes along might not be as familiar with the alternate way you chose to implement something, which impedes understanding. That's never really an issue for a single person program, since they had to understand that feature it to initially write it, meaning they should understand it when they encounter it later (the vast majority of time at least. Forgetting skills from long ago happens).


> Except the resulting code will look nothing like “the humans say it”,

Actually, I find it maps rather directly to how a lot of people explain things. For example, "Examine each number, and as long as it's greater than 10 and odd, then pass it to the the work function."

    for my $number ( @numbers ) {
        next unless $number > 10;
        next unless $number % 2;
        work($number);
    }
Perl generally allows you to structure your code as you would explain how to accomplish something to another person. This can be beneficial or detrimental depending on how deep you go with this concept. A lot of becoming a good Perl programmer is learning where a sane line is for this, but each language usually has a similar feature which the user needs to decide where the sane point to stop is before taking it to an extreme that is detrimental.

There are definitely aspects of Perl that I think are better left untouched, and thankfully the community has pretty much come to consensus about the most problematic missteps the language allows.


One can write pretty much the same code in python/c++11/whatnot and it also feels quite natural to read:

   for number in numbers:
       if number <= 10: continue
       work(number)
Do you have a better example where the Perl syntax would shine?


You have clearly been able to read and translate the GP's code and confidently assert you've written "pretty much the same code".

> Do you have a better example where the Perl syntax would shine?

Unless you have "a ton of knowledge about Perl" your reply shows that it was a perfect example in response to the GGP.


Note: This is all in the context of Perl 5. You can assume the following works with little or no changes in Perl 6, along with probably 3+ other new ways to do it (which is actually one of my peeves about Perl 6).

There's a few things. Full word but lower precedence boolean operators (and, or, not) which allows for combining statements in a way that &&, || and ! doesn't always facilitate, but really shine in making boolean statements more readable. e.g.

    die "some problem" unless defined $some_var and not $some_var eq "foo";
But I think you somewhat missed my point. What you've done in your example, is easy to read, but you've either unconsciously or consciously switched the order of some statements so they are valid in the context of Python. This is trivial and easy with simple conditionals, but if they are complex it can hide the point of the statement, which is that this is a shortcut to the next loop iteration. I find putting the "verb" first can make for much easier understanding of what's going on when it gets more complex. A comparison of that might be something like the following:

    for my $item ( @items ) {
        # Standard barrage of tests
        next if test1($item) or test2($item) or test3($item)
            or test4($item) or test5($item);
        # If it's a special item, do a couple more tests
        next if test_guard($item) and ( subtest1($item) or subtest2($item) );
        # If it's an end marker, skip the rest
        last if is_last_processable($item);

        ...
    }
Even though the actions are condensed, I quickly know what the point of each one is, and what it does. Condensing them also allows me to comment each without feeling I'm cluttering the logic and making it more verbose than needed (too verbose, and you raise the likelihood related code will be off-screen or not as easily visually associated, which hampers comprehension), but event without the comments having the defining action start the line helps clarify intent. I imagine in Python, the continue statement would either be far to the right from larger conditionals, or moved to a more traditional scope underneath taking up an extra line, or split into multiple if statements. This is also a good example in Perl of where the community has come to a fairly good consensus that while you can make very complex postconditional statements, don't, as it defeats the purpose (just split it into multiple simple ones or use a traditional precontitional if formatted to be more readable, or some other technique such as computing portions of the condition separately and comparing them later).

Also, regarding if pre or post positioning, I feel that Perl allows the statements to be expressed as you might say them or think of them. That's the point of postconditionals in Perl. Also, like how you would express them verbally to someone, a postconditional only works on a single statement (it does not support blocks through braces). You wouldn't normally say "do X, do Y, do Z if A is true" and expect it to apply unambiguously to tasks X, Y and Z. On the flip side, a preconditional not only supports braces, it reqiures them, since the simple one statement case is easily handled through the postconditional. e.g.

    # Valid
    if ( $A ) {
        do_something();
    }
    if ( $A ) { do_something(); }
    do_something() if $A;
    
    # Invalid
    if ( $A ) do_something();
    { do_something(); } if $A;
This is an example of one of the places Perl not only allows you to use natural expressions to express yourself, but guides you away from odd or problematic ways of doing so (i.e. ambiguous speech patterns).

As for sigils, some people really dislike them, but I find the useful. I see them a little signifiers of the nouns in any statement (and the type of noun, of which there are only a few).

Finally, there's "context", which has a specific meaning in Perl, and is probably the most interesting and unique thing about the language. It can be very useful, but the complexities can sometimes cause interesting behavior that was unintended or non-obvious initially. That said, its also what makes a lot of the "magic" (really just the rules put into action) of the array and hash data types work, so it's not something that could feasibly be removed (and nor would I want it to be). Instead, knowledge of the problematic spots is acknowledged by the community, so we try to avoid those problems, and for the most part they are old problems (this is usually a function that may produce multiple values being using within the definition of a hash or array in list context, exemplified by decades old projects based on CGI.pm which has been deprecated).


Wow, the fact that Larry Wall was a linguist and (along with many others, I'm sure) applied those skills (about the nuances of human languages) to the design of Perl, really shines through in this comment. Thanks.


Lots of other languages have postfix conditionals.

On the readable boolean ops, all the Perl people recommend shying away from them except for a few specific constructs (do or die, eval or do, etc), since the weaker precedence rules make it really easy to shoot yourself on the foot:

    $a = $b or $c;
Where $a will never be assigned the value of $c.


> Lots of other languages have postfix conditionals.

I didn't make a case as Perl being the only language, just that it's an interesting aspect of Perl. That said, I would be interested in what languages you are referring to. I haven't seen many.

> On the readable boolean ops, all the Perl people recommend shying away from them except for a few specific constructs (do or die, eval or do, etc), since the weaker precedence rules make it really easy to shoot yourself on the foot:

They are perfectly acceptable in a boolean statement. You only need to shy away from them when mixing them with assignments or higher precedence boolean constructs. The only case where you would have to worry is in non-simple boolean statements with assignment in the statement, or functions that omit parens for arguments in some cases, or mathematical operations without grouping parens, all of which I would argue should include their own grouping parenthesis for clarity anyway.

That said, I devoted space in both of my comments in this thread to noting that there are definitely places where you might shoot yourself in the foot with some of these features, and you'll note the examples I used them in are exactly as you've described, where they are either after a postconditional (in which case it's kept to a simple boolean statement which has no ambiguity), or to affect control flow (e.g. return or die), in which that assignment doesn't matter anyway.

> Where $a will never be assigned the value of $c.

Which I never used as an example for that reason, but that's the point of those operators. Being lower precedence allows for some alternate constructs than is possible in many other languages without them.

Someone asked for examples of constructs that help Perl match mental models of how might think of an algorithm, so I decided to explain a few. The purpose isn't to point out how Perl is better than Python or some other language, but how it's different in an interesting way. A lot of that was planned, but sometimes that came out to its benefit, and sometimes to its detriment. Like most interesting new things (because at the time it was), it's not entirely one thing or the other.


>I didn't make a case as Perl being the only language, just that it's an interesting aspect of Perl. That said, I would be interested in what languages you are referring to. I haven't seen many.

I'm not the one you replied to, but Python has got, not postfix conditionals, but what I might call infix ones, for lack of a better name. Here is a nested example:

Using nested conditional expressions to classify characters:

https://jugad2.blogspot.com/2017/04/using-nested-conditional...


That's a really nice explanation, thanks.


In Perl 6 this could almost look the same:

    for @numbers -> $number {
        next unless $number > 10;
        next unless $number % 2;
        work($number);
    }
Although personally, I wouldn't write it like that: I would probably write it as:

    for @numbers.grep( { $_ > 10 && $_ % 2 } ) -> $number {
        work($number)
    }
or use the postfix notation:

    work($_) for @numbers.grep( { $_ > 10 && $_ % 2 } );
If you want to spread this out over multiple CPUs and you don't care about the order in which the work is done, you only need to add the `.race` method:

    for @numbers.grep( { $_ > 10 && $_ % 2 } ).race -> $number {
        work($number)
    }
More info: https://docs.perl6.org/routine/race


That ought to be a oneliner in any sane language today:

    numbers.into_iter().filter(|n| n>10 && n%2!=0).for_each(work);

    map work . filter ((/=0) . (`mod` 2)) . filter (>10) $ numbers
Insert tirade about how for-loops are free to do so much that they are slower-to-comprehend than specific-purpose iterator/list functions, here.


The language is happy to accommodate any style you like best, including oneliners.

    sub work($n) { say $n }
    my @numbers = 1..100;

    # rubyish
    @numbers.grep(* > 10 && * %% 2).map(&work);

    # lol turbo haskal
    map &work <== grep * %% 2 <== grep * > 10 <== @numbers;

    # same, but in proper reading direction
    @numbers ==> grep * > 10 ==> grep * %% 2 ==> map &work;
The traditional function composition operator exists, see https://docs.perl6.org/routine/%E2%88%98


The following doesn't do what you think it does

    * > 10 && * %% 2
That is two WhateverCode objects which each take one argument. Since both are definite it gives you the second one.

    my &a = * > 10;
    my &b = * %% 2;

    my &c = &a && &b;

    &c === &b; # True
If it wasn't split up by the `&&`, it would be a code object that took two arguments.

    # using multiplication (×) as a boolean and
    # (it always cooperates in the WhateverCode lambda syntax)
    my &c = (* > 10) × (* %% 2);

    say so c(10,2); # True

    say (1..20).grep(&c);
    # ((11 12) (13 14) (15 16) (17 18) (19 20))
Note that `grep` is written in terms of `map`

    (1..20).map({ ($^a,$^b) if  ($^a > 10) × ($^b %% 2) })
    # ((11 12) (13 14) (15 16) (17 18) (19 20))
If you need to refer to an argument more than once, you (generally) can't do it with the WhateverCode lambda syntax.

    ->   $n {  $n > 10 &&  $n %% 2 }
            { $^n > 10 && $^n %% 2 }
    sub ($n){  $n > 10 &&  $n %% 2 }
I say generally because array indexing will give you the number of elements for all the arguments you ask for.

    @a[ (* × ⅓) .. (* × ⅔) ]
    @a[ (@a.elems × ⅓) .. (@a.elems × ⅔) ]


I noticed that error too but decided I didn't have the energy to provide a response worthy of the situation.

I'm so glad I didn't try. As always you've provided a helpful answer and I learned something new. I hadn't twigged that `[...]` context would treat each Whatever as the same value -- though in retrospect I can see of course it would given the Perlish principle of doing something very useful rather than doing something useless (generating an error).

I noticed what looked like a mistake in your post:

    my &c = (* > 10) × (* %% 2);

    say so c(10,2); # True
I thought "surely that returns False" and when I tried, it did.


Right it was late, and I was writing the code in different ways when writing here and writing in the REPL.


Here is a slight modification that takes advantage of the hyper operator >> (»):

  @numbers.grep(* > 10 && * % 2)>>.&work;
https://docs.perl6.org/language/operators#index-entry-hyper_...


This would be one way to write in Perl 6:

    for @numbers -> $number {
        next unless $number > 10;
        next if $number %% 2;
        work($number);
    }


A lot of that "cryptic charade" comes straight out of the UNIX environment. To those familiar with this, it was/is hardly "cryptic".


Just like the Old Testament is “hardly cryptic” for someone studying it since the 70s. Doesn’t tell you anything about it’s validity or relevance today.


Why would Perl repeat the same mistake as others, of trying to treat a programming language too much like a natural language? It's optimized to be read as a programming language, not anything else.

Also, "cryptic charade" could be a good name for what all non-Perl 6 languages call "regular expressions". It would make an even better name for a prog rock band.


Perl (5 or 6) doesn't try to treat a programming language as a natural language. Instead it tries to allow the structure in which the author's brain defines the problem to be able to match the structure in which the code of the program defines the solution. It is linguistic in the sense that it tries to follow the normal flow of human language as a form of communication, allowing skills learned for human communication to be re-used for communicating via source code--not in a natural, human language (still in a computer language) but without necessarily having to pivot the problem in to something more natural for computers first.

Source code is instructions for two audiences: A human, and a computer. The computer doesn't care what the syntax is, but the human does. It is an ongoing challenge to write code in a manner which effectively and concisely communicates to other humans, including your future self. This is a thing at which Perl5 and Perl6 both excel, Perl6 more so IMO (although there is not yet enough history to prove it).

It is true that one can easily write unmaintainable spaghetti in Perl5. One can write unmaintainable spaghetti in any language, but Perl5 makes it somewhat easier to do it by mistake--this is an aspect of the same versatility which gives it its expressive power, which in turn is what makes it possible to communicate things using Perl more effectively (in the same space) than with many other computer languages. You have to employ some discipline not to sound like a gibbering lunatic. This is not much different from human languages: if you have ever read English 101 papers you will find some of them sadly similar to Perl5 scripts written by similarly undisciplined authors.

In contrast to Perl5, Perl6 makes it far easier to avoid accidental spaghetti and does so without sacrificing any of the linguistic expressiveness that makes Perl generally so useful.


> It is true that one can easily write unmaintainable spaghetti in Perl5.

This was something that surprised me when I first learned about Perl 5 in college. Most people in the internet would parrot it as a "write-only" language and yet I've always being capable of getting the whole picture of a code snippet posted on Perl Monks, Reddit, Stack Overflow, etc. Granted I've always steered away from golf code which obviously has its place but shouldn't be mistaken as being the "de facto way" of writing Perl 5 or Perl 6 for that matter.


>In contrast to Perl5, Perl6 makes it far easier to avoid accidental spaghetti and does so without sacrificing any of the linguistic expressiveness that makes Perl generally so useful.

Can you give some examples of that point, w.r.t. Perl6?


I'm not sure if I've nailed what the GP was speaking of or what you're looking for but anyway I do think the following is illustrative of the linguistic evolution P6 represents.

Earlier this year at perlmonks (perhaps the top resource along with stackoverflow for experienced perl folk answering questions) a poster wanted solutions to a fairly basic operation:[1]

> I need a function which will filter a nested hash, removing any fields I'm not interested in.

Their test data had a source that began:

    my $source = {
        f1 => 'garbage',
        f2 => 'more garbage',
        f3 => 'important data',
        f4 => {
            this => 'sub hash',
            is   => 'garbage'
        },
        f5 => {
            f6 => 'more important data',
and a filter that began:

    my $filter = {
        f3 => 1,
        f5 => {
            f6 => 1,
After a few days the person who asked the question summarized the community's P5 answers.[2]

The first one listed (slightly trimmed):

    #! /usr/bin/env perl

    use strict;
    use warnings;

    use Carp;

    use Deep::Hash::Utils qw(reach nest deepvalue);

    sub hash_filter_recursive {
      my $source = shift;
      my $filter = shift;

      my %output;

      foreach ( keys %$filter ) {
        if ( exists $source->{$_} ) {

          if ( ref $filter->{$_} eq 'HASH' ) {
            croak "bad filter: on '$_', expected HASH\n"
              unless ( ref $source->{$_} eq 'HASH' );

            $output{$_} = hash_filter_recursive( $source->{$_}, $filter->{$_} );
          }
          else {
            $output{$_} = $source->{$_};
          }

        }
      }

      return \%output;
    }
(This appears to include a modicum of input validation.)

Here was my P6 answer, including the call to invoke the routine (which I omitted from the P5):[3]

    sub infix:<landr> ($l, $r) { $l and $r };
    say $filter «landr» $source
Even though this uses a parallel operation which will one day optionally be automatically mapped to multiple cores to run faster, I'm pretty sure this is currently slower than the P5 solutions.

And I didn't bother with any validation that it was indeed being passed a nested hash.

But it makes a point. While P6 can typically do similar things to P5, it often turns out easier to do many things at a much higher level, which leads to less spaghetti.

----

[1] https://www.perlmonks.org/?node_id=1215517

[2] https://www.perlmonks.org/?node_id=1215736

[3] https://www.perlmonks.org/?node_id=1216274


Note that there was no need to actually create an infix operator, as you can use any code as an infix operator if you surround it with `[&( )]`.

    say $filter «[&(  -> $l, $r { $l and $r }  )]» $source
Golfing it down a bit, the shortest I was able to get was

    say $filter «[&(   &[and]   )]» $source;
The `&[and]` references the infix `and` operator.

I think the reason the following doesn't work that way is that `and` is too thunky.

    say $filter «and» $source;
    say $filter «[and]» $source; # identical to previous line
(Note that `and` is supposed to be thunky, so that isn't a bug.)

---

I personally would write this:

    sub infix:<l-when-r> -> $_, $r {
      # note that the value to be matched with must be in $_
      # prior to using the `when` keyword.
      # it was done in the signature for conciseness

      $_ when $r
    }
Then the conditions can be code objects, regexes (which are a form of code object in Perl6), or literals. (I tried to get it to work with bare Junctions, but I was unable to get the `«»` part to pass it into the operator.)

It does mean that you have to use `True` rather than `1`.

    my $filter = {
        f2 => True,
        f3 => *.contains('data'),
        f5 => {
            f6 => /data/,
        },
        f10 => * == (0 | 1 | 42), # only match these values
        f11 => 42, # only match something equal to 42
    }

    say $source «l-when-r» $filter;


Thanks for the reply. Definitely looks like P6 can work at a higher level ...


You're welcome.

Here's another quick example. It may or may not touch on your or the GGGP's point. So, no need to reply. I just thought I'd post something more while we wait for their reply.

    say now - INIT now
This displays the time difference between the normal run-time moment that the `now` call before the minus is called and the `now` call after the minus sign which is run during the earlier INIT phase of execution: https://docs.perl6.org/language/phasers#phasers__INIT

In P5, phased code didn't return values so one needed to create a variable and initialize it elsewhere in the code.

P6 has many more phasers than P5 and allows many of them to return values to code that's run at a different phase. (This is sometimes called "time traveling" code.) This saves a lot of jumping back and forth needed to understand a fragment of code.


>You're welcome. Here's another quick example. It may or may not touch on your or the GGGP's point. So, no need to reply.

I'll reply anyway, to say thanks again :)

I'll admit that I'm a bit phased by P6 phasers :) Had come across them just recently in the docs, initially thought, on a brief look, that at least the ENTER and LEAVE phasers were something like Python's __enter__ and __exit__ special methods used with context managers / "with" statements, or a way of wrapping a function call (or statement) in pre- and post-function invocations. which can be done with decorators in Python. But it seems like phasers may be something more, if not different. Also, there are many other kinds. Need to look into it some, including the "time traveling" code part.


> I'll admit that I'm a bit phased by P6 phasers :)

.oO ( a pun set to stun? )

> ENTER and LEAVE ... like Python's __enter__ and __exit__

Aiui their primary usage involves similar use-cases and sugar.

The common aspect is that some code is declared and then the language/compiler calls that code when the time is right.

> But it seems like phasers may be something more, if not different.

Aiui P6:

* Has more of these hooks for block processing (eg PRE and POST for convenient pre and post condition assertions);

* Has hooks that aren't for blocks but instead much larger scale phases of program execution (eg there's CHECK which runs at the end of compilation, before running the program).

Also...

> Need to look into it some, including the "time traveling" code part.

What I meant by "time traveling" is as follows.

The compiler calls phased code when the times is right. Some of the time this is implicit. For example, in this Python code the __exit__ code gets called automatically by the Python interpreter as the block is exited:

    with foo as bar:
      qux
P6 phases can return values as follows:

    say now - CHECK now
the first `now` happens during regular run time. But the second happens during CHECK time -- which is at the end of compilation, before the program starts to run. The compiler knows to run the CHECK code earlier, then store the result, then subtract that from the `now` run at normal run-time.

I don't recall who first called that time traveling and I'm not even sure on reflection whether it makes sense to call it that but that's what I meant.


>.oO ( a pun set to stun? )

Well done. Good one. :)

Thanks once again, I understand phasers better now.


I'm not sure your definition of 'it' (that is, a default) matches how 'it' is actually used. 'It' is a locally scoped name binding to a previously mentioned symbol. In English, the referent of 'it' is sometimes ambiguous, requiring contextual intelligence that computers lack, so programming languages with 'it' need to be more precise.

Here's 'it' in lisp: https://en.wikipedia.org/wiki/Anaphoric_macro


The official name for "it" in Perl 6 is "the topic variable":

https://docs.perl6.org/language/variables#index-entry-topic_...


This makes so much sense, in its own way. Is there anywhere I can read more about this perspective?



Try the "state of the onion" series of speeches.


I do agree that Perl (6) is not a cleanly designed language.


Would you care to elaborate on the non-clean parts in your opinion?


Things like this seem like odd design choices:

  my @menu = <hamburger fries milkshake>;
  say @menu.contains('hamburger');            # True 
  say @menu.contains('hot dog');              # False 
  say @menu.contains('milk');                 # True! 
  say @menu.contains('er fr');                # True! 
  say @menu.contains(<es mi>);                # True!


From https://docs.perl6.org/routine/contains, `contains` coerces its invocant to a string and searches for a substring starting from a certain position (index 0 by default):

    # Let's drop `<>` (quote-words constructor) and 
    # use a more familiar array of strings:
      
    my @menu = 'hamburger', 'fries', 'milkshake';
      
    # Let's look at the definition of the `Str` method in 
    # the `List` class from which the `Array` class inherits:
    
    #`{
      method Str(List:D: --> Str:D)
      Stringifies the elements of the list and joins
      them with spaces (same as .join(' ')).
    }

    # Thus, after being stringfied, @menu is treated as 
    # the string 'hamburger fries milkshake'
    
    # With this is in hand, we can gauge the possible
    # result of the following statements:
    
    say @menu.contains('hamburger');            # True 
    say @menu.contains('hot dog');              # False 
    say @menu.contains('milk');                 # True
    say @menu.contains('er fr');                # True 
    say @menu.contains(<es mi>);                # True


If you'd like instead to search the array for words as elements, we could use Perl 6's set functions. However, I don't know if they're as performant as regular string searches:

    say 'hamburger' (<=) @menu;  # True 
    say 'fries' (<=) @menu;      # True 
    say 'hot dog' ∈ @menu;       # False 
    say 'milk' ∈ @menu;          # False 
    say 'er fr' ∈ @menu;         # False 
`∈` is the unicode equivalent of `(<=)`.

---

I'm not sure if I'm missing something in the "odd design choices" in this specific case so it'd be great if you could elaborate a little bit further here.


The ASCII equivalent of `∈` is `(elem)`.


You're totally right! I always get them confused. So `∈` is `(elem)` and `⊆` is `(<=)`.

Thanks for pointing it out!


English contains ambiguous words. What does "contains" mean in the previous sentence? In P6 it means searching a string for a substring. Your code asks P6 to treat @menu as a string. If you want to treat it as a list and grep that list then use grep:

    my @menu = <hamburger fries milkshake>;
    say so @menu.grep('hamburger');            # True 
    say so @menu.grep('hot dog');              # False 
    say so @menu.grep('milk');                 # False 
    say so @menu.grep('er fr');                # False 
    say so @menu.grep(<es mi>);                # False


You are sort-of right.

It should have used a different word.

A similar example would be the word `length`.

There is no `length` in Perl 6 because it is ambiguous. Instead there is `.elems` and `.chars`.

It is perhaps even a worse because there are other languages which use `contains` to see if the container has a given element.


Not to be trollish, but is anyone actually using Perl 6 for more than just for kicks? It is a super interesting language, but has it been battle tested over the years similar to Perl 5?


We are using in in production. One of our bigger uses is a DB metrics aggregator. We use it to to pull stats from DB servers for remote clients and dump them into graphite. Sort of an agent-less monitoring platform. We've had this Perl 6 tool running 24/7 since last summer. It's now pulling from ~80 DB servers.

Another internal use is an AWS infrastructure management tool that we built. A cli util that handles the initial bootstrapping for new AWS projects and a few helper features to simplify some of our common management tasks.

Perl 6 has been pretty easy to work with. Even in situations where a module isn't available or the requirements are too complex to build it with Perl 6 within our project time constraints, its facilities as a glue language really make it simple to work with external tools, modules, libs.

If you like the Perl 6 syntax then I'd recommend just spending some time with it. It's stable and fast enough for regular use now.


Perl 6 is still 9 times slower than Perl 5 when parsing log files with a regex. I don't quite get why the feature which made Perl famous has now taken a back seat. Why should I take a 9x performance hit?


The Perl 5 core is hack upon hack, to the point that it's been mostly abandoned due to how hard is to change things without breaking anything. Perl 6 was born as a specification, which allows for a "first make it right, then make it fast" approach.


That's assuming it can be made fast. It's been stagnant around this level of performance for quite some time now.


Unfortunately, the performance of regexes has not been improved much in the past years, that is true and on the radar. Yes, it can be improved (very much indeed).

Most other subsystems of Rakudo Perl 6 have been improved significantly, some by orders of magnitude. And then there's work on the basic runtime of MoarVM and its JIT that will benefit all programs running on MoarVM.

The Perl Foundation recently approved another grant for the JIT: http://news.perlfoundation.org/2018/11/september-2018-grant-... about http://news.perlfoundation.org/2018/10/grant-proposal-moarvm...


Perl with poorly-performing regexes is beta software, as far as I'm concerned. Why OOP, junctions and all the less relevant stuff has taken priority over regexes baffles me.


Well volunteered!


It may be that it's of interest, as an early Perl 6 implementation was written in Haskell (Pugs)


I think this Haskell version (pugs) came at a time when perl6-development was somewhat stuck, and it enabled the Perl 6 developers to test new language constructs on an improved runtime (I believe); so Haskell was actually key to Perl 6 development. (https://gist.github.com/masak/479846/4908b28645b8815d1afe2b4...)



It seems to me that Haskell programmers are the least likely to need something like this.


To be interested in programming languages generally, I think, is an inherent feature of a passionate programmer.


Being neither a Haskellian nor a Perlist, I found the article interesting and I think you nailed the reason why.


A great Haskeller led to this document being made available. [1]

She didn't question whether Haskellers needed something like P6, she just implemented it and pushed Haskell to greater heights. I think that is a worthwhile point.

But I don't understand why you've introduced your point about what you perceive as the level of need for this document.

Given a non-zero number of lang X to lang Y documents, one or more of them will be the most likely needed, one or more the least likely. And given such a scenario, it'll likely seem one way to some folk and another to others. So?

----

[1] The first P6 compiler prototype was written by Audrey Tang. https://en.wikipedia.org/wiki/Audrey_Tang The P6 project follows several principles she established such as being optimized for fun, and a "forgiveness > permission" policy for most contributions. So someone wrote a nice doc and it's been made available.


Right. This is like saying "Hello most elite gamers, here is an entry level tutorial to Duke Nukem Forever..."


Duke Nukem Forever jokes, really? Look, Perl 6 can either be a "crazy complex" language that is "over-designed" and "hard to read", or it can some sort of toy with laughable complexity (your supposition is that Perl 6 is to elite programmers as Duke Nukem Forever is to elite gamers).

So which is it? Complex enough for only elites to grasp? Or just some toy language with no real capabilities, let alone unique features of interest to elite programmers?


I think you misunderstood or are trolling. This is a Haskell to Perl 6 guide. Haskell is for the elite programmers. Perl 6 is the Duke Nukem Forever of programming languages. This of course was all tongue in cheek.


Sorry dude, but the crux of your joke is that elite programmers shouldn't look at Perl 6.. because it took a while to develop?

And it is hardly "tongue in cheek" when you talk trash about the language (which you have never used) throughout this news item.


Actually Perl 6 comes off badly in this comparison. The Haskell expressions are almost always easier to read, understand, reproduce, and overall even shorter.

Nevertheless it shows that Perl 6 can do real functional programming. Even if the syntax looks exceptional sometimes, even for people familiar with Perl 5.


It's not a comparison. It's not an appetizer for P6 or ways in which P6 comes off better than Haskell. It's not an overview or tutorial for learning P6 if you come from a Haskell background.

It's for someone who has already decided they like P6, has learned the basics, and wants to tighten up their understanding of P6 as it relates to Haskell things they know. It deliberately picks things that are basic in Haskell even if they're not so basic in P6.

That's why it says:

> Note that this should not be mistaken for a beginner tutorial or overview of Perl 6; it is intended as a technical reference for Perl 6 learners with a strong Haskell background.


You're certainly right, but that doesn't change my point that, by just looking at the code, Haskell seems to have the better solutions for the problems.

This conclusion is clearly unfair because the author tried to port simple Haskell solutions to Perl.


> You're certainly right, but that doesn't change my point that, by just looking at the code, Haskell seems to have the better solutions for the problems.

Sure. But that's an inevitable consequence of what the document aims to achieve.

The problems chosen were the ones for which Haskell had simpler solutions.

The point of the document was to help someone who is already motivated to learn P6 and knows Haskell to get to grips with P6.

If the point were to motivate someone who knows Haskell to want to learn P6 then the examples chosen would be ones for which the P6 solution is better than the Haskell one.


What’s the objective or rationale here? I don’t understand why this is interesting.


Language compare and contrast is whats interesting to me.

I don't use either day to day but have had some exposure to both. I think both languages will have influence on future of language design at a minimum. Doubtful Perl does a phoenix routine but weirder things have happened.


I'm not sure, but I've got to say, as someone with 10 years Perl 6 experience, I nevertheless learned useful new-to-me things in the second section of it.


There's also a Python version of this[1], which starts with a discussion about Perl 6's equivalent of print, which is put. This makes no sense to me whatsoever, as print is both a much easier way to say it and _what was used in Perl 5_, but not my circus, not my monkeys. But then it goes on to say:

> There is also say, which behaves similarly, but will call the gist method of its argument.

And after having read the linked-to docs for say[2] and gist[3], I not only cannot understand what is being said, I have no idea how anyone else could, either.

1) https://docs.perl6.org/language/py-nutshell 2) https://docs.perl6.org/routine/say 3) https://docs.perl6.org/routine/gist


I've never used Perl6, but it took me about 30 seconds to figure out what 'say' and 'gist' do from the linked docs? 'gist' prints a string representation of an object aimed at being human-readable at the expense of not necessarily being a complete representation (e.g. the doc page gives an example that an array has only its first 100 elements printed followed by a '...'). 'say' is a version of 'put' that does this for every object being printed.


So, I sort of took that away from it, but there's stuff in the gist page like:

> The default gist method in Mu re-dispatches to the perl method for defined invocants, and returns the type name in parenthesis for type object invocants. Many built-in classes override the case of instances to something more specific that may truncate output.

And I have no idea how anyone that isn't already fluent in Perl 6 is expected to read that.

EDIT: My point is mostly that it just seems... weird. Like, I get the animating idea of Haskell, even if I don't understand all of the concepts. Perl 6 just seems... alien. It's incredibly funky.


If I went on to learn about "Functors, Applicative Functors and Monoids" (which I'm completely ignorant about) in Haskell without having first learned Haskell's basic building blocks, then I would be disingenuous myself if I blamed the language for my ignorance and unfamiliarity with the language. On top of that, if you're not a Haskell user I don't think you're the target audience as pointed out by bmn__. For this reason, there are several migration guides (Python, Ruby, etc.) which ,although incomplete, they give the languages' respective users a contrast against Perl 6 which hopefully translates into some familiarity with it.

If you want to start from the bottom out, there's the ever improving language docs: https://docs.perl6.org/language.html


My takeaway from that is it’s basically Go’s Stringer() but with a default method so even objects without String method can still return a string.

Quite a few languages have that kind of feature though I believe. PHP has print_r and var_dump, Perl 5 had Data::Dumper, Python has tools too which I forget the name of.

I like how Perl 6 has baked it into the language though rather than making it a part of the standard library.


Reading the docs a bit more and/or googling for terms like "perl6 mu" might have helped. I too might have not what Mu meant (in the context of Perl6, although I did know the original meaning), unless I had come across it in the docs or elsewhere.

But IMO, like others have said, it is not really that difficult to figure out what it means (if you know some OOP) (although some of the rarely-used words (e.g. "invocants") get in the way a bit.

Basically when I read your comment, I figured out that the default gist method (even the word "gist" is a clue) was something like a default-valued method (to print the representation of any object) that can be overridden on a case-by-case basis by any other object - something like Python's __str__() and __repr__ special methods, like others have said.

However, having read some of it, I'll have to agree with you that the Perl6 docs can do with some improvement (check out Phasers in the Perl 6 manual for an example of what I mean) - whereas, in contrast, the Perl 5 docs are considered by some (me too) to be good-to-excellent. But then Perl6 has been evolving for less time (yes, I know about the long time for the 1st stable release).


I have no problem reading that. Sure, I dont understand it in fine technical detail (what's Mu? An implementation of Perl? A codename for Perl 6?) But I believe I understand enough of it to start using it.

This specific example seems similar to the __repr__ vs __str__ thing in Python, and not very alien at all.


As pointed out by others, Mu is the most undefined value there is in Perl 6 and the base root for the immediate child classes (https://docs.perl6.org/images/type-graph-Mu.svg). However, most classes (both built-in and user-defined ones) don't inherit directly from it. Instead, they inherit from Any, which in turns inherits from Mu.

More info about it:

- https://docs.perl6.org/type/Mu

- https://en.wikipedia.org/wiki/Mu_%28negative%29


Right. Here's a blog post, which, while not directly about Mu (it's about m, a shell script I wrote), has many excerpts about (the original) Mu (from which Perl6's Mu descends, pun intended, ha ha) near the end - some may find them interesting:

m, a Unix shell utility to save cleaned-up man pages as text:

https://jugad2.blogspot.com/2017/03/m-unix-shell-utility-to-...


`Mu` is perl6's `Object` ("mu" ≈ "nothing" in chinese/japanese). cute, but alien


Also, "most undefined".


Thanks for pointing out this Python similarity!


You cannot blame the language reference manual for exposing all the complexity and using precise wording. You are not expected to read that.

Other resources exist which are targeted at newcomers and explain things differently.


The reference manual is what was linked to to explain terms that a resource aimed at people who know Python but not Perl 6 used.


print in Perl 6 works the same as print in Perl 5.

put/say are output functions which automatically add a newline at the end.

If you want fancier formatting, printf is available as well.

And notice the relative lengths of these names. As much as possible, p6 is organized so that the more commonly used thing will have the shorter name.

PS I don't think I have ever used put in p6. My code uses say, or print if I don't want a newline added to the output.


As for the say function, it's also supposed to output text in a more human readable format. It calls the `.gist` of its argument, which you can override in user-defined classes. Take for example the following code snippet from Perl 6 Deep Dive:

    class Chemical { 
        has $.formula; 
        method gist { 
            my $output = $!formula; 
            $output ~~ s:g/(<[0..9]>)/{(0x2080+$0).chr}/; 
            $output; 
        }
     }


     my $chem = Chemical.new(formula => 'Al6O13Si2'); 
     say $chem; # Al₆O₁₃Si₂

     #`[
     Without overriding the `gist` method:

     say $chem; # Chemical.new(formula => 'Al6O13Si2')
     ]


I still can't take Perl 6 seriously with that butterfly logo. Website looks like it's from 2003 as well.


Use this one https://rakudo.org


See that looks nice and the website looks like it was made this decade.


If the logo is an issue, how do you feel about the Go gopher? Or Glenda the plan9 bunny?


At least the Go Gopher/Glenda are kinda minimal


I'd like to hear opinions on how the use of sigils and the other syntax oddities like Int:D, Int:U, given, when, etc improves the codabliity/readability of Perl 6 vs other languages. The examples vs Haskell are not helping me understand. Personally I don't think the added verbosity is helping in any way.


Can you give an example of a language that is similarly precise with less verbosity, while still being comprehensible?

Perl 6 is alarmingly concise in a lot of cases (hyper-operators come to mind), so it's super weird to see it called verbose. I'd wager that the ideal, or at least shortest, Perl 6 solution to most problems is shorter than most other languages...I don't know if it's necessarily more readable (you have to know a lot of the language to read really concise Perl 6 code, and there are many new concepts for most developers), but it's definitely not verbose.

Int:D, Int:U, etc. provide information about types. They aren't arbitrary extra boilerplate. Every language with types specifies them in somewhat comparable ways. Perl 6 has gradual typing, you can use as much or as little of it as you want, and as suits your problem ___domain. You don't need those types, but if you use them well, you can do things more concisely...e.g. for multi-method dispatch based on type of arguments.

given/when are keywords. Every language has keywords, and sometimes they'll be new ones that you haven't seen in other languages.

Sigils, again, provide additional information, both to the reader and the compiler. Perl 6 is probably an improvement, or at least simplification, over Perl 5 in that the sigil is constant and doesn't reflect the usage. e.g. in Perl 5, when you want a single element of an array, you use $name[1], but when you want the whole array you use @name. The idea (sort of) being that $ is singular (a "scalar" value), while @ is plural. Some people don't like sigils, but I don't see any point in re-litigating it 30 years on. Perl has sigils. That's just how it do. Some like it, some don't. Enough Perl developers like it that it's never gone away.


> Can you give an example of a language that is similarly precise with less verbosity, while still being comprehensible?

This assumes I think Perl (6) is precise and comprehensible.


You've already made it clear you have no experience with the language...so, what are you trying to accomplish here?


Sigils have been standard in shells for decades. And sigils allow string interpolation to work; again, just like in normal unix shells. The python people decided that sigils are a bad idea, so instead of being able to say "I have $n apples" (like you could in shells we've all been using forever!) I now need to say "I have {} apples".format(n). I know which one I prefer!


Javascript has `I have ${n} apples`, or even `This is chapter ${i+1}.`

In terms of interpolation, that's the variant that I like best.


Perl 6 does it without the sigil outside the bracket :)

"I have {some-complex-calc($i)} frobitzes"


Unlike Python's `"I have {} apples".format(n)` and various shells' `"I have $n apples"`, Javascript's and Apache Groovy's `"This is chapter ${i+1}"` mean the lexer must make a call to the parser when lexing the string contents -- this allows `"This is ${"chapter"} ${i+1}"` to parse. Don't know about Javascript, but this makes Groovy's parser unreadable, and stuck on a very old version of Antlr, i.e. 2 instead of 4 (the latest).


In P6:

grammar one-grammar { rule { <some-pattern> <another-grammar> .... } }

Can't get simpler. Can't be more readable.


AFAIK, Groovy 3 is targeting Antlr 4.



Also in groovy. I too am a fan.


I don't get the given/when part of this comment at all? given/when is exactly like C's switch/case, except the names are better and it's at least an order of magnitude more powerful.

It's 100% not added verbosity in any way. Added complexity, sure, but it's a pretty straightforward application of some of the main ideas of the language, usable in the standard C-language-family way out of the box, and powerful and flexible when you understand it.


> I don't get the given/when part of this comment at all?

Given and when were listed as separate items, not “given/when”; I agree with you about given (encompassing the given/when construct), but I can understand seeing “when” as an oddity (though I think it's a plus for comprehensibility, because it's general behavior is a consistent generalization of it's behavior in given/when.)


If Perl is too verbose for you, you can always go to APL.


I think APL wins hands down in being the most concise when it comes to mathematical tasks, but P6 wins at more common scripting tasks such as parsing data. Only Rebol & Red in my opinion have similar constructs to P6's native grammars. Rebol wins at being the quickest way to write short GUI applications that do useful things as it uses its GUI dialect (basically a dsl) to make it really easy....almost unbelievably so (http://www.re-bol.com/rebol.html). I'd say powershell is the most concise way to deal with Windows automation.

So really...all depending on what you mean.


> I'd like to hear opinions on how the use of sigils and the other syntax oddities like Int:D, Int:U, given, when, etc improves the codabliity/readability of Perl 6 vs other languages.

Given/when is not really a syntax oddity, it's (in the simplest case), a structurally and semantically common construct in other languages that goes by various names (case/when, switch/case, etc.), the name is unique to Perl but the naming fis all over the map between other languages, and Perl matches English much better than most others (though it would do so more precisely if “when” was “when it is”), so that's a plus for readability except for people who come to Perl more fluent in some other programming language than in English.

Other uses of when might be unique to Perl, but they generalize the use from given/when (and have the much the relation to English), so there is a deep consistency there; learning a concept that is more limited in other languages buys you more in Perl.


FWIW, with a little syntactic trick, you can actually have sigillless variables in Perl 6:

    my \foo = $ = 42;  # bind sigilless name to a container with 42
    say foo;    # 42
    foo = 666;
    say foo;    # 666
See https://opensource.com/article/18/9/using-sigils-perl-6 for more information. </plug>


Perl6's use of sigils seems excessive to me but I do like sigils for variables. It acts like a namespace between similarly named constructs. I know for instance WebClient is a class and $WebClient contains an instance of it. I also like how it makes it easy for syntax highlighters to identify variables from classes and keywords.


> The examples vs Haskell are not helping me understand. Personally I don't think the added verbosity is helping in any way.

It doesn't sound to me like you are the right audience for the document you're reading.

Quoting from that page:

> this should not be mistaken for a beginner tutorial or overview of Perl 6; it is intended as a technical reference for Perl 6 learners with a strong Haskell background.

It is not wise to start with a technical reference unless you are already fairly well versed in the basics of the technology you're learning and are motivated to deepen your knowledge of it.

If you are interested in P6 you should start with overview or beginner material. Then, if you have a strong Haskell background, you can refer to the technical reference if and when the overview or beginner material isn't working for you.

(If you are not genuinely motivated to have fun learning P6 then nothing related to P6 will work for you. Are you genuinely motivated to have fun learning P6?)

----

> I'd like to hear opinions on how the use of sigils and the other syntax oddities

If you view childishly simple and natural syntax as "oddities" then your mind is already made up that they are oddities.

So the rest of this comment is intended primarily for other readers and secondarily for you on the off chance that you are able to transcend your mind's confirmation bias against the following constructs actually being simple and natural.

> use of sigils

Many programmers think in terms of three fundamental primitive data types from which all other datatypes are composed:

* single items

* collections of numbered things

* collections of named things

P6 adopts this view and assigns three sigils to these three abstract notions.

This makes it both easier and quicker to both read and write code -- once you've learned how they work. In P5 sigils were onerously complex. In P6 they are childishly simple. So now it's also easy and quick to learn them as well as to use them.[1]

> Int:D, Int:U

In P6, every type that's created using any of its type constructors is a sum type with two sub-types. This includes types defined in the standard language such as Int. The sub-types are named D and U. For example, to refer to Int's D sub-type, use `Int:D`.

This makes it easy and quick to read and write code once you've learned what they are. Fortunately, it's childishly simple to learn what they are.[2]

> given

The `given` keyword means essentially the same as the English word `given`.

This makes it easy and quick to read and write code once you've learned the English meaning of `given`.[3]

> when

The `when` keyword hides a good deal of complexity. But one can hop on Wittgenstein's Ladder easily. Because for the first rung, it just means the same as the meaning of the English word `when` used in the context of something that's `given`.

The keyword `when` makes it easy and quick to read and write code once you've learned the English meaning of `when` in the context of `given` -- and it can then be used in other contexts.[4]

----

[1] 27 second vide clip covers it all: https://www.youtube.com/watch?v=Nq2HkAYbG5o&t=10m&list=PLRuE...

[2] They're called "type smilies" for a reason. :D is the definite, happy, valuable type. What's `42`? Simple. Definite. Happy. Valuable. Unlike :D, the other subtype, :U, is undefined, unhappy, not a value. What's `Int`? Is it `42`? No, because that would be defined. Every value/object is either definite/happy or it isn't.

[3] From dictionary.com: given: noun: "an established fact"

[4] From dictionary.com: when: conjunction: "in the event that"


> In P6, every type that's created using any of its type constructors is a sum type with two sub-types. > This includes types defined in the standard language such as Int. The sub-types are named D and U. > For example, to refer to Int's D sub-type, use `Int:D`.

Probably your comment hints to this already in which case the following will be redundant but I wanted to mention them more explicitly. This is mainly for people unfamiliar with Perl 6.

Using the type smileys(:U, :D) are also ways to specifically match against a type object (`Int`, `Str`, `Rat`, etc.) and an instance object of a type object (-5, 'Hello', 1/5, etc.):

    Int ~~ Int:U;   # True
    -5  ~~ Int:U;   # False
    -5  ~~ Int:D;   # True
    Int ~~ Int:D;   # False
There is also the :_ smiley which is used by default whenever the other two aren't specified:

    Int ~~ Int;     # True, same as: Int ~~ Int:_;
    -5  ~~ Int;     # True, same as: -5  ~~ Int:_;


> Probably your comment hints to this already

Regardless, I'm glad you've written your comment to clarify. :)

I'd be delighted to hear about any of the several big or small mistakes I am about to make in the following.

Also an honest opinion about whether the following approach I take boils down to one that is complete gibberish, vaguely interesting but terribly complex, OK but meh, good but a bit abstract, enlightening, or something else. If you do let me know, please clarify whether you mean what you say for just you, or for what you think might be true for others that don't know P6 at all. TIA.

----

Like a lot of P6 stuff this basic aspect of its type system is both childishly simple but also so general, abstract, and high level, and comes at things from such a different angle than pretty much all other languages, that it can be difficult to explain.

Another attempt at what I was trying to get at in my second footnote in my GP comment...

----

A P6 type and its two standard sub-types are a simple and fun unification of the universal/existential "quantification" that our inner logician loves and the "article definiteness" distinction recognized by our linguistic side.

From https://en.wikipedia.org/wiki/Article_(grammar):

> The articles in English grammar are "the" and "a/an" ... In languages that employ articles, every common noun, with some exceptions, is expressed with a certain definiteness, definite or indefinite

From https://en.wikipedia.org/wiki/Quantifier_(logic):

> The two most common quantifiers mean "for all" [Universal] and "there exists" [Existential].

----

:D denotes a definite thing.

It is directly analogous to "the".

The value `42` is considered definite.

Definiteness implies that a thing actually exists. Its the linguistic analog of existential quantification.

Many coders talk about happy/sad path processing. :D is associated with the happy path, perhaps because it has no existential crisis. :D

----

:U is related to Universal quantification.

As a type, it is also related to "a". Quoting wikipedia:

> An indefinite article indicates that its noun is not a particular one identifiable to the listener.

:U corresponds to an indefinite thing, something that's only identifiable as a Universal, not a Definite thing.

:U is also associated with Undefined things, even if they are supposed to be undefined.

In the context of talk about happy/sad path processing, :U is associated with the Unhappy path, because it can denote a thing that should be definite but isn't.

----

As a value, a type name without a `:D` or `:U` smiley is the same as the type name with a `:U`.

As a type, a type name without a smiley is the same as the type name with a `:_`, where the `_` denotes either `D` or `U`.

Thus:

* `Int`, as a thing in of itself, is the same as an `Int:U`.

* `Int`, as a type of thing, denotes either an `Int:U` or an `Int:D`.


> ...the several big or small mistakes I am about to make in the following.

Everything you wrote seems fine to me and you even expounded on what I wrote! However, even if it wasn't, I'd be hardly pressed to come up with a response as clever and resourceful as your responses. For this reason, I quite enjoy reading your comments whenever I come across them on /r/perl6 and /r/programminglanguages.

> Like a lot of P6 stuff this... is both childishly simple but also so general, abstract, and high level... that it can be difficult to explain.

You're totally spot on. The most recent example of my struggle (mainly due to my ignorance of Perl 6 and probably CS concepts too) was the concept of containers and how they interface most assignments in Perl 6. I think the fact that many Perl 6 constructs/concepts, which complex in nature, seem so natural can deceive people who haven't tried it yet. This is because it's easy to overlook (or plainly ignore) how much thought went into both integrating them into the language and make them play nicely together.

---

Thanks for your comments!


> Everything you wrote seems fine to me and you even expounded on what I wrote!

Given that your reply was just the right sort of clear answer that would make up for my original footnote I was especially happy to riff off your answer and get super detailed again. :)

> I'd be hardly pressed to come up with a response as clever and resourceful as your responses.

.oO ( Ever too clever by half )

> The most recent example of my struggle (mainly due to my ignorance of Perl 6 and probably CS concepts too) was the concept of containers and how they interface most assignments in Perl 6.

Yeah. Simple on the outside so noobs can just do their thing. Rich on the inside so gurus can develop new candy and gourmet meals.

Anyhoo, thanks for your reassuring feedback. :)


[flagged]


It breaks HN's civility rule to insinuate dishonesty in other users. Please review the site rules at https://news.ycombinator.com/newsguidelines.html.


The lack of maybe or nullable types in perl6 with the need to check for definedness at run-time (Int:D) is one of its major design blunders. Also this syntax!

In cperl I rather use proper maybe types as in every other language. ?Int is (Int | Undef) you cannot use Int? as this would confuse the parser to look for the matching :


> The lack of maybe or nullable types in perl6

P6 supports something more powerful and uses that instead:

https://en.wikipedia.org/wiki/Tagged_union

In P6 the symbol Int, when treated as a type by the compiler, denotes Int:_, which is a sum type, with two subtypes, namely a generically existentially quantified Int (Int:D) and a generically universally quantified Int (Int:U).

Thus Int can be used in the role of a nullable type, but is an improvement in the sense that the equivalent to None (Int:U) encodes its type.

In P6 all constructable types are automatically sum types with :U and :D subtypes.

> need to check for definedness

There is relatively little need for users to check definedness. The language and compiler ensure basic type/memory safety and the user can just write code and it'll automatically be type safe at this basic level.

When the need arises, the user only need type one or two characters in almost all cases (either `:D` if writing a type constraint or `if foo` or `?foo` if writing an explicit check).

> at run-time

In P6 definedness refers to the notion that something actually exists and this is deliberately aligned with the notion that something exists at run-time.

Users seldom need to concern themselves with this but when they do the P6 approach is simple and convenient.

> one of its major design blunders. Also this syntax!

I see the Int, Int:D, Int:U semantics and syntax as a design triumph. See another comment in this thread for an introduction to my view: https://news.ycombinator.com/item?id=18647590

> I rather use proper maybe types as in every other language.

When I read things like "proper" and "as in every other language" in this manner I experience them as appeals to authority.

Perl 6 is not a typical language. Just as Perl 5 isn't either.

For example, a P6 compiler is allowed to statically check that types match at compile time:

    sub foo (Str $bar) {}
    foo 42
yields the compile time error:

    Error while compiling .code.tio
    Calling foo(Int) will never work...
but it doesn't view static type checking as a panacea any more than it considers dynamic type checking as a panacea.

P6, like Perl, is designed around the notion of a this and that view of things rather than an either/or view.




Consider applying for YC's Summer 2025 batch! Applications are open till May 13

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: