2018-09-18 Thoughts on using Perl 6

So, I’ve used Perl 6 for a few days. I’m trying to write a wiki, because that’s what I like to do, and that also what I use every day. I’ve been maintaining and running Oddmuse since 2003. I know what I want. I’ve been down every dead end, I sometimes feel. Now I want to learn the language using a real project and that’s what it is.

The current state, from a programming perspective:

Cro

Markdown

Wiki Creole

Mustache templates

The software, from a user perspective:

Missing features:

Missing big ideas:

More to come! I’m running out of time and I have to go. Here’s an idea: draft pages. They are like real pages but they don’t show up in search or feeds. Hah!

Anyway, I was talking to @tyil and thought that I should write this stuff down. Not sure who the intended audience is for these things. I feel like I’m too confused right now to understand where the problem is to be found, how can I create an issue, and where, and with what suggestion? Perhaps my future self is the audience for this blog post. One day I’ll wonder how newbies get into Perl 6 and what their issues are and I’ll be able to come back to this blog post and see myself struggling.

@tyil

So, for a start, these are the things that immediately jumped out at me:

I bought *Perl 6 Deep Dive* by Andrew Shitov and I’m surprised at how quickly I’m running out of information in the book. It was a good read to get started and to motivate myself. Good enough to actually pull me into starting this project. That’s cool. But the next point is the sort of documentation I’ve had trouble finding.

For example:

I’m trying to have a class called `Storage` which delegates all the important method calls to another class which I want to load at run time. In this case, it’s going to be `Storage::File`. How to do it? I searched for “delegation” and the like and ended up on documents that were deprecated. I figured it would have to involve `require` somewhere, and then something like that “synopsis” or whatever it was. I don’t really care about the “synopsis” and “exegesis” and all the other funny ways the language was developed now that I’m actually trying to get stuff done. I’m a different kind of user, I know – but this is the kind of user that we will have to pull in. In the end I asked on the `#perl6` channel on IRC and found something that works:

class Storage {
    my $class = %*ENV<storage> || 'Storage::File';
    require ::($class);
    has $!delegate handles <get-page put-page get-template put-change get-changes> = ::($class).new;
}

This illustrates two points: I might have found out about “handles” but I didn’t find it in the book. The index doesn’t mention “delegation”. Apparently this is called a “trait”. The index doesn’t mention “traits”. But even knowing all these keywords, I can’t find out about these things by starting with `p6doc objects`.

And that brings me to another topic: `p6doc`.

IO

IO::Path

And then there are all those little things that bite.

And many other things besides. As I’m too new to the language I don’t understand why things have to be “same same but different”. I hope there’s is a grandiose pay-off, I guess?

Here’s an example of how access to the hash elements no longer uses braces but angled brackets, the regular expression is different, the braces aren’t used when creating the hash, and map takes a comma after the block:

    my $menu = %*ENV<menu> || "Home, Changes";
    my @pages = $menu.split(/ ',' \s* /);
    my %params =
	id => $id,
	pages => [ map { id => $_ }, @pages ];

The Pod is also subtly different and the documentation confused me a bit. There are many options. What the suggested way of doing it? Is this good? Should I be using `#|` instead?

    =head3 put-page
    =begin pod
    Pages are saved in the C<page> subdirectory with the <md> extension.
    =end pod

    method put-page (Page $page!) is export {
	my $dir = %*ENV<dir> || '.';
	my $path = "$dir/page/$($page.name).md";
	spurt $path, $page.text, :enc('UTF-8');
    }

Anyway, that’s the kind of stuff I’m thinking about when I write Perl 6 code.

Oh, and recently my application has this super aggravating tendency: Often, when making changes (and this only started showing up recently!), I get an error.

♻ Restarting edit (edit)
⚠ edit ===SORRY!===
⚠ edit This type (NQPMu) does not support associative operations

The strange thing is that no matter what change I make, that fixes it. So now I have a second shell open where I just do the following:

echo >> lib/Storage/File.pm6

And then it works!

♻ Restarting edit (edit)
📓 edit Listening at http://localhost:20000

Apparently, all I have to do is trigger a recompilation.

When I’m testing, same thing.

dir=. storage=Storage::File prove6 -l -v t/edit.t

This causes an error:

===SORRY!===
This type (NQPMu) does not support associative operations
t/edit.t .. Dubious, test returned 1
No subtests run
All tests successful.

Test Summary Report
-------------------
t/edit.t (Wstat: 256 Tests: 0 Failed: 0)
Non-zero exit status: 1
  Parse errors: No plan found in TAP output
Files=1, Tests=0,  4 wallclock secs
Result: FAILED

The fix is simple:

echo >> lib/Storage/File.pm6

The result:

    ok 1 - Status is acceptable
    ok 2 - Content type is acceptable
    ok 3 - Body is acceptable
    1..3
ok 1 - GET /edit/About
    ok 1 - Status is acceptable
    ok 2 - Content type is acceptable
    ok 3 - Body is acceptable
    1..3
ok 2 - POST /save
ok 3 - page name correct
ok 4 - page content saved
ok 5 - changes correct
ok 6 - year
ok 7 - time
ok 8 - major change
ok 9 - page name
ok 10 - code
ok 11 - summary
    ok 1 - Status is acceptable
    ok 2 - Content type is acceptable
    ok 3 - Body is acceptable
    1..3
ok 12 - POST /save
ok 13 - year
ok 14 - time
ok 15 - minor change
ok 16 - page name
ok 17 - author
ok 18 - summary
1..18
t/edit.t .. ok
All tests successful.
Files=1, Tests=18,  6 wallclock secs
Result: PASS

How weird is that? I asked on the `#perl6` channel and one of the people there was curious and was interested in fixing this. Sadly, I was unable to produce a small working example. I tried for quite a while. I have no idea what causes this.

​#Oddmuse 6 ​#Perl 6

Comments

(Please contact me if you want to remove your comment.)

Sadly, I was unable to produce a small working example. I tried for quite a while. I have no idea what causes this.

I can try something without a small example, as long as you can provide any example that reproduces the issue in at least a semi-reliable fashion. Basically we have a bunch of tools that can run stuff on any given rakudo commit, and bisect if necessary. Just ping me on ​#perl6 if you have that (a zip file or something like that will do) and I’ll try to find out if it’s a new issue or if it existed before, and we’ll see what caused it if it’s new.

– AlexDaniel 2018-09-18 22:28 UTC

---

I’ll keep it in mind. It’s been working for today, with no issues except for once. Who knows.

– Alex Schroeder 2018-09-19 14:41 UTC

---

Here’s another strange thing: locks don’t seem to work as I’d expect them to.

use File::Temp;
my $fh = open('test.p6', :w);
say "File locked: " ~ $fh.lock;
say "Deadlock: " ~ $fh.lock;

Output:

File locked: True
Deadlock: True

I sort of expected there to be a deadlock as the second call to `lock` never returns. But apparently not...

So I wrote my code using empty lock directories, like I did for Perl 5.

– Alex Schroeder 2018-09-19 14:44 UTC

---

One of the goals of the design of Perl 6 is to be more consistent.

This is why `map` has a comma after the block, it is just a subroutine and the block is just a lambda.

This consistency is even more evident when you look at the pointy block.

for @a -> $i { say $i }

if $a.method() -> $result { say $result }

my &lambda = -> $a { say $a }

Note that pointy blocks works with all operators of the same form as `for` and `if`.

The reason for `??` `!!` is that

1. The `:` is used everywhere for many things, so it is very confusable.

2. The `?` is used for a variety of features itself.

3. There is no need for `!!$a` because you can just use `?$a`

Frankly, it is a very odd operator because it is in a category all of its own. If it wasn’t already so widespread amongst other languages it probably wouldn’t have been included at all. (similar reason for the inclusion of `loop (;;){}`)

The Regex sub-language got a complete overhaul as it was getting very kludgy. It was also better integrated such that regular Perl 6 language features can be used rather than create regex exclusive features. (A regex in Perl 6 is just a type of method with a different base syntax)

`p6doc` copies `perldoc` in that you use the `-f` flag to read up on functions.

– Brad Gilbert (b2gills) 2018-09-20 23:28 UTC

---

Thanks!

– Alex Schroeder 2018-09-21 21:31 UTC

---

Just to note, whenever you would normally reach for a parent class, it’s probably more idiomatic for Perl 6 to use a Role instead.

Then you can have your absolute base class as a role with the barest essentials, including stubbed methods that “role-ing” classes are required to implement.

The advantage is that you don’t end up with the kind of hierarchical entanglement associated with multiple inheritance *and* you get to keep all the goodness of distinct type-ness, Smartmatching against a role vs a class is the same for the end user, for example.

– ab5tract 2018-09-24 20:01 UTC

---

Well, right now I’m basically using classes as structs: just data, no methods. Roles seem like a very cool addition to objects, but my love for Lisp leads my code to much less object oriented than what people might be used to.

– Alex Schroeder 2018-09-24 21:48 UTC