Stories
Slash Boxes
Comments
NOTE: use Perl; is on undef hiatus. You can read content, but you can't post it. More info will be forthcoming forthcomingly.

All the Perl that's Practical to Extract and Report

use Perl Log In

Log In

[ Create a new account ]

masak (6289)

masak
  (email not shown publicly)
http://masak.org/carl

Been programming Perl since 2001. Found Perl 6 somewhere around 2004, and fell in love. Now developing November (a Perl 6 wiki), Druid (a Perl 6 board game), pls (a Perl 6 project installer), GGE (a regex engine), and Yapsi (a Perl 6 implementation). Heavy user of and irregular committer to Rakudo.

Journal of masak (6289)

Monday February 15, 2010
08:40 AM

Ok, so the ante is upped: E03

So, apparently my challenge on IRC and on SF's blog got at least SF interested. Which means now there's even a challenge. I'm hoping others will jump on as well. It's simple: just blog your modern Perl 6 version of E03 on Friday.

Will E03 be hard? I don't know, maybe. But we're just trying things out. We're exploring a piece of Perl 6 archaeology, and how old documented intents interact with new actual practices. There's no way to lose the contest, but plenty of ways to win it. And remember, while the official price is One Internet (method of delivery unspecified), your contribution might very well end up in a revised modern-day E03. Or something.

Since there's a Rakudo release on Thursday, and since there's no shortage of rakudobugs to report and features to implement till then — you should see the activity only this morning! — I suspect I won't have time to actually start porting E03 until Friday morning. But that should be plenty of time.

Monday February 08, 2010
07:54 AM

The typo trap: a farcical FAQ

[Update 2010-04-03: The below post is about a bug which jnthn++ just fixed in Rakudo master. That means that the cause for the main complaint of the post — not getting any sensible error diagnostics whatsoever — has been removed. Yay!]

Help! I'm getting the error "invoke() not implemented in class 'Undef'" in my large application. What did I do wrong?

You've mistyped a class name which sits inside a namespace.

How am I supposed to figure that out?

I didn't say it was a particularly good error message.

It's like this: if you mistype a class name which is not in a namespace, you'll get an informative error message:

$ perl6 -e 'A.foo'
Could not find non-existent sub A
in Main (file src/gen_setting.pm, line 324)

However, if you mistype a class name which is in a namespace, you will get an uninformative error message:

$ perl6 -e 'A::B.foo'
invoke() not implemented in class 'Undef'
in Main (file <unknown>, line <unknown>)

So there's your error message. Linking it to the actual cause is something which you'll learn by experience.

So in that case, I don't get the name of the class which was mistyped in my program?

Correct.

And I don't get the line number of my typo?

Indeed not.

Or the file?

Right. You'll get no information about the location of the typo.

Is that intentional?

Well, no. As you see from the error message above, the information is meant to be printed, but it comes out as (file <unknown>, line <unknown>) instead.

Why?

Rakudo is built on top of Parrot. Usually, Rakudo generates its own error messages, but in some cases, Parrot will also generate an error. The error invoke() not implemented in class 'Undef' is such a case. When a Parrot-internal error like this one occurs, Rakudo will not be able to extract the annotation information required to provide a sensible line number and file.

I... I see.

Yeah. Sorry about that.

Are you able to pick up the irony in the fact that when I use namespaces to help mitigate the complexity of my project, I end up with an error message that in fact makes it harder for me to manage the complexity of my project?

Hold on.

Yes. We are able to pick up the irony in that. Quite easily, in fact.

Consider not using namespaces at the present juncture. They are very useful, but they are also known as a frequent source of annoyances like this.

By the way, I couldn't help but note that the line number and file information in your first example doesn't make any sense either. What the heck is src/gen_setting.pm and line 324?

Well, uh, that's the last line of internal Rakudo code that actually has a working line-and-file annotation. It's nothing that should reach the user, really.

So that's kinda broken, too?

Annotations are currently broken, yes. Apologies.

Back to my mistyped type name. My program is distributed over fifteen modules and ten thousand lines of code. How do you propose I find my typo?

First off, we recommend that you compile often. That way, the diff from the last working code will not be too large, and you will not have to visually scan so much text hunting for your typo.

Secondly, it's often useful to have your project in a version tracker such as Git, so that you can do git diff to see the changes against the index, or against the latest commit.

Thirdly, when all else fails, you can always insert print statements into your code, to try to bisect the origin of the error.

So in other words, Rakudo is no help whatsoever when this occurs?

Now, that's not quite fair. Rakudo tells you that the error occurs. That's actually useful information.

And you consider that adequate?

No, I didn't say that! No-one is happy about this situation. It's just the way things are.

So it can't be fixed?

Theoretically, yes. But not easily. Remember that the error occurs in Parrot.

Don't Rakudo and Parrot developers confer with each other?

Oh, sure we do. Do not assume that we're deliberately causing this situation. It's just that the current way Rakudo and Parrot are welded together makes the situation non-trivial to rectify.

So this problem is going to go away with the advent of the new ng branch?

There's nothing to indicate that this would be the case. In ng, you currently get a Null PMC access:

$ ./perl6 -e 'A::B.foo' # ng branch
Null PMC access in invoke()
current instr.: '_block14' pc 29 (EVAL_1:0)
called from Sub '!UNIT_START' pc 984 (src/glue/run.pir:17)
called from Sub 'perl6;PCT;HLLCompiler;eval' pc -1 ((unknown file):-1)
called from Sub 'perl6;PCT;HLLCompiler;command_line' pc 1489 (src/PCT/HLLCompiler.pir:794)
called from Sub 'perl6;Perl6;Compiler;main' pc -1 ((unknown file):-1)

To its credit, Rakudo ng does provide more information in this case, but unfortunately the information is of a kind which was concealed from the user in Rakudo master about a year ago (because it tended to be very uninformative).

Just to summarize: this all sucks, right?

That would be a succinct description of the state of this particular error message, yes.

I heard that the Perl 6 community has adopted very high standards with respect to error messages. There's talk about "awesome error messages", and last summer I was in the audience when Larry Wall demonstrated how good Perl 6 was at reporting error messages to the user. How does this error message square with all of that?

The awesome error messages are like a platonic ideal towards which all implementations aspire. Rakudo, being rooted in our imperfect physical world, doesn't always get all the way. Yet.

I'm about to go visually scan ten thousand lines of code, looking for where my error message might have originated. Any last words?

We value your efforts as an early adopter of Rakudo. Your feedback is important to us. Have a nice day.

Thursday February 04, 2010
09:47 AM

Blast from the past: E02

SF took my challenge to heart and started producing a "modern Perl 6" version of the example code in E02. His thought process can be seen here, and here.

After being a bystander for a few hours, I coulndn't restrain myself anymore: I produced my own version. I should say at once that it's quite different from SF's: while he keeps close to the original E02 (which, in turn, sets out to prove that Perl 6 is/was not very different from Perl 5), my version is a bit more liberal in its interpretation. I do mix in some of my personal preferences into it. Some examples:

  • We don't do $ARGS prompts("Search? ") anymore, but there's a nice &prompt function which I used instead, together with a while loop.
  • The &show function now uses gather/take, rather than printing directly.
  • Also, I avoided the statement-modifying mess from the original E02 &show code.
  • Also, E02's &show makes a point of using a slurpy @_ rather than naming the paramters. I don't. (Neither does SF.)
  • It just makes sense to use a given/when construct in the &insert function. To its credit, E02 tantalizingly hints of it, but then does a MIB mind-wipe. (You don't recall that bit? Oh well...)
  • In the same function, E02 puts undef to initiate the child nodes to some empty value. Both SF and I independently realized that just any undefined value won't work if &insert is to have %tree in the signature, because %tree only binds to an Associative value. SF solved it by putting Hash (an undefined Hash type object) in the child nodes, and changed it to Hash.new in the later version. I used {}, which should be equivalent to Hash.new, but IMHO more idiomatic.
  • The whole traits business hadn't solidified in 2002, but I believe that the end result is both more realiable, more useful, and prettier. You'll have to judge for yourself.

I believe rewriting the exigeses in modern form is a very worthy activity. I hope we'll see more of that. Perl 6 suffers a bit from stale, outdated documentation, and having these in new versions would be valuable.

It's also a very interesting historical activity to read the old apocalypses and exigeses, as I increasingly find. Perl 6 has come a long, long way since 2001.

Friday January 29, 2010
08:54 AM

Mildew, Sprixel, Vill: In praise of the alternatives

Not all of Perl 6 is Rakudo. Well, when I use Perl 6, it is. But I'm hoping 2010 will change that. We have a few other implementations out there, which fall in the "small but promising" category.

Mildew

From the README:

Mildew is an experimental implemention of Perl 6, written mainly in Perl 5. It is named in the tradition of 'yeast', 'slime' and 'mold', which were/are related projects.

I can't say I've ever understood the idea behind naming projects after icky things, but I like the projects as such. They seem to generate a kind of "basic research" which strengthens the foundations of Perl 6. The decade-old project has always been about attacking the enormously big task of implementing Perl 6 from different angles — and I like the angle pmurias++ and ruoso++ are taking.

Mildew uses the 'viv' parser and the STD.pm grammar to convert Perl 6 source code into an Abstract Syntax Tree. An AST is a data structure that describes what the Perl 6 program is meant to do. Mildew contains various experimental backends selected by the -B and -C switches to export or to execute the code in the AST.

Mildew targets both SMOP (written mostly in C) and the Google V8 JavaScript compiler.

Sprixel

From the README:

sprixel (anagram of perlsix): viv and STD.pm parse Perl 6 source, emitting an Abstract Syntax Tree in YAML, then sprixel walks the AST using its trampolined, stackless, continuation passing style interpreter written in JavaScript and executed by Google's V8 JavaScript compiler and runtime engine.

I know diakopter++ is playing around with both JavaScript and C♯ implementations of Perl 6 rule engines. That is also an area which excites me, and where I'm glad people are making headway.

Vill

From the README:

'vill' is the ugly temporary name of this project that connects 'viv' as Perl 6 front end to LLVM as code generating back end. It sounds too much like 'vile', or mock German 'will', but it fits.

Heh.

Unlike other Perl implementations such as Pugs, Rakudo, Sprixel and Mildew-js, 'vill' produces native executable files. [...]

Whoa! That's potentially very attractive.

The slowest part of 'vill' is 'viv', because that runs as a separate Perl 5 child process. The medium term plan will be to use the STD.pm grammar, but replace the 'viv' parser with a new one to be written in C. [...] If the dependency on 'viv' can be removed, the ugly 'vill' name will no longer be appropriate, and it will be time to think of a better one [...]

I'm actually hoping I might be able to help with the C-based parser.

Conclusion

Rakudo is the implementation that shows up on the radar of most outsiders right now. (And with good reason.) But much exciting work is going on in the background, with implementations like mildew, sprixel and vill.

I'm sure this will come off as almost self-evident, but I'll say it anyway: the moment an alternative implementation will cross a threshold into the area of the really interesting, is when it provides a significant chunk of Rakudo's functionality (which is saying quite a lot), together with some feature that Rakudo doesn't have. Given Rakudo/Parrot's current performance, the most obvious feature would be speed. But it might also be something else, such as a bridge to Perl 5, or a very solid metamodel. The more ground-shaking the new feature, the less important will be the delta between the alternative implementation and Rakudo.

At the very least, I think one of the above implementations will pass through the Mach 1 barrier in 2010, and attract a serious user base, and more developers. I'd love for Rakudo (and Pugs) to have some company up there among the "big" implementations.

Exciting times!

Friday January 22, 2010
11:41 AM

Code generation and stone soup

I don't know what kept me away from generating code for so long. Fear and prejudice, perhaps.

I've been trying it the last few days, and I have two things to say. First, it's like learning to program all over again. Remember that sense of power from the early days, when just picking up coding? "Hey, I can program this piece of code to do whatever I want." Well, guess what? That feeling comes back when one starts down on the path to madn... erm, to code generation. Only it's stronger. "Hey, I can program this piece of code to program that piece of code to do whatever it wants!" I think I've just discovered meta-hubris. Most likely, I'm not the first to do so.

Second, there's a flip-side to the feeling of power. That other feeling is how you feel when you knit your brows and wish that your neurons would line up a bit better so you could think more clearly about the problem at hand. Who would have thought, that feeling is also stronger when you're suddenly writing two different, entwined and related programs at the same time, in the same file. In my case, the knitted brows turn into an empty stare and a jaw left slackly agape, as I sit there wishing that I was better at context-switching between runloops.

Honestly, I think I expected eval to be the source of much programmer confusion, but I have to confess that it seems I underestimated the vistas it opens up when you buy into the idea of generating exactly the piece of code you need for the task (from an AST, say), and then eval it into a closure. That's what the back end of a compiler ends up doing, so maybe I shouldn't be so surprised that it's a versatile technique.

Lately, I've been in the business of squeezing every drop of juice out of the already implemented control flow constructs already implemented in Rakudo. I'm writing a p6regex→p6 compiler, you see. (Yes, that's a rather crazy notion; thanks for asking.) Along the way, I've often felt the need for not-yet-implemented control flow. This has led me to this hope-inducing maxim:

Every type of control flow in programming languages is just convenient sugar for if statements and while loops.

ifs and whiles are the stone soup to which all the rest of our control flow can be added as seasoning. ifs let you conditionally skip ahead in code, and whiles allow you to conditionally skip back. That's all you need.

Here are some examples.

  • Switch statements are just sugar for chained if/elsif/else statements. Even Perl 6's given/when constructs.
  • The variants next, last and redo, either with or without a label to affect a less-than-innermost loop, can be desugared to sad boolean-ish variables, plus some if statements to appropriately regulate the expression of the code inside the loop. (Yes, go ahead and twitch just thinking of it. That sugar is there for a reason.)
  • Subroutines and subroutine calls can be simulated with the appropriate use of a switch statement and an explicit call stack stored in an array variable.
  • Even exceptions, or more generally continuations, can be desugared in this way. As soon as you have total control of the call stack, you're free to save and rewind to some previous state to your heart's content.

Aside from the switch statements and unlabeled next etc, which already work very well in Rakudo, I've been doing the whole list of desugarings in GGE (the regex compiler). The part with the continuations was especially fun. I needed them for backtracking, at least as long as the compiler was only an interpreter.

But then, during a fruitful discussion with diakopter++, I was told how to emulate (delimited) gotos with a switch and a loop. The idea is quite obvious in retrospect: just keep the current 'label' in a variable, and switch on it in each iteration. Presto! I should have thought of that. I don't even need to flee to PIR any more.

I took the idea and generalized it to delimited gosubs: instead of keeping the current label in a scalar, keep it at the top of a stack. Define macro-like constructs to push to (local-branch) and pop from (local-return) the stack. Suddenly I don't need continuations as much.

Result: this. We send in the regex /<[a..b]> | <[b..e]>/ on the top line, along with the target string c to match on. The program generates an AST, an anonymous subroutine which executes the regex in atomic Perl 6 operations, and finally a match object which indeed finds c to be a match.

Here's a similar but slightly more involved example. And here's one doing captures and backreferences inside a quantified non-capturing group. Isn't that exquisite? (Ok, bad choice of word. Sorry.)

As I said, I wrote most of with a feeling of being not just in over my head, but of being in over my head twice. I'm still a bit surprised it works. The runtime compilation seems to introduce a bit of a speed penalty, but (1) it's a one-time cost, since you can re-use the regex object, and (2) I told you it would be slow.

The code-generating work still resides only in a local branch on my computer. I'll push it to master as soon as I'm done bringing GGE back to its former capabilities. (Update 2010-01-24: Done, and done.)

Code writing code. What a concept!

Tuesday January 19, 2010
04:26 AM

The taming of the newbie - a comedy on IRC

The other day, I remembered this old piece of #perl6 backlog from 2005:

<masak> question: what are good ways in p5 and p6 respectively, to reverse a string?
<masak> the easiest way i found in p5 was join '', reverse split // $string
<masak> doesn't look very nice, now does it?
<integral> *blink*
<integral> $string = reverse $string

It feels odd to realize this five years later, but it seems that in 2005 I didn't have a firm grip on how reverse worked in Perl 5. Chances are, dearest reader, that you do. But if not, the rest of the refreshingly frank discussion will explain it.

Meanwhile, five years earlier, I persist in my innocent ignorance:

<masak> nope
<masak> doesn't work :(
<masak> reverse only reverses lists... i think

Reading this from the perspective of five years' work with Perl 5 and 6 is... enlightening, in a slightly cathartic way. Sure, it could have been that I'm the first to discover that reverse in Perl 5 doesn't in fact reverse strings, despite thousands of people using it daily for that purpose. But the chances of that are astronomically small. My peers on the channel tell me this.

<PerlJam> masak: clearly you are insane.
<integral> perl -le '$string = "abc"; $string = reverse $string; print $string'
<integral> masak: the manual *clearly* explains all the stuff about context
<integral> and the faq

They do, you know.

<PerlJam> masak: in perl6 it would be $string.=reverse probably.

This was true in 2005, but nowadays we have flip for strings, reverse for lists, and invert for hashes. The need for different functions falls out naturally from the fact that Perl 6 doesn't depend as heavily on context as Perl 5 does.

Back in the log, I'm still trying to reintegrate into reality.

<masak> integral: your example worked, thx
<masak> but nothing worked for me
<masak> apparently i am insane :P

PerlJam and integral are one step ahead of me.

<integral> no, you don't understand scalar context. perl -le 'print scalar reverse shift' foobar
<PerlJam> masak: you were probably saying "print reverse $string"
<masak> no, but maybe something of the sort
<masak> and that doesn't work, because...?
<integral> masak: print's prototype is (@), ie list context. It's a rightwards named list operator
<PerlJam> masak: context.
* masak thinks he sees it now

These explanations are actually very good, but just in case, let me restate them in my own words: reverse has two main behaviours. Either it reverses a list of things, or it reverses a string of characters. It switches between these two behaviours based on something. You might think that this something is what type of thing you send in (a scalar or a list), but that isn't so. Instead, reverse responds to its surroundings and figure out what they expect. $string = reverse $string is a scalar assignment, and expects a scalar. print reverse $string, as integral explains, puts reverse in list context, so it reverses the list of one thing ($string), i.e. doing nothing.

Steve Yegge has this to say, in a vitriolic critique of Perl:

Perl also has "contexts", which means that you can't trust a single line of Perl code that you ever read.

I would say that it's actually not that bad, and the idea of context can be unintuitive at times, in many cases it's actually very natural and useful. reverse, in my humble opinion, is not one of those cases. I'm glad it's split up into different methods in Perl 6.

At the end, we learn that I had actually Read The Faithful Manual already, I just hadn't read it carefully:

<PerlJam> masak: perldoc -f reverse
<masak> thx, integral and PerlJam
<masak> PerlJam: I read the perldoc entry but apparently not carefully enough
* masak reads it again
<masak> ah
<masak> "In scalar context, concatenates the elements of LIST and returns a string value with all characters in the opposite order."
<masak> this somehow went past me as something i didn't want :/

In summary, I mostly wrote this blog post because I like to make myself squirm. 哈哈

But I guess there's also a moral to it all. We all start somewhere, and in a way it's reassuring to find five-year old proof of this fact. A newbie is just on a part of the learning curve you've already visited; they haven't had a chance to tweak their keyboard and developing environment to maximum efficiency yet, and they sometimes forget that the manual is there, or misread it in some way. So, don't hesitate to be be kind to them, and help them connect to the goodness that is perldoc, PerlMonks and Planet Iron Man so that they can grow and bloom into experienced wielders of Perl.

But don't hesitate to call them insane, either, when the situation calls for it.

Saturday January 16, 2010
12:38 PM

Ovid is right: roles are awesome

A class hierarchy of expression nodes: it's so much the prototypical use case for run-time method polymorphism that it's almost a cliché. One can close one's eyes and picture the way parts of the expression tree interact in rich, complex ways, shaped by the very types of the nodes themselves, in a dynamic dance of late bindings and virtual methods. Switch statmement, get thee behind me. Et cetera.

I'm building one. And I'm having almost too much fun doing it. In between trying to use the strengths of Perl 6 and keeping true to the original program I'm porting, I've discovered an important thing: Ovid is right about roles.

Specifically, I'm having trouble picturing how I would cram all the type information into my expression node class hierarchy, were I not using roles. The roles definitely help manage complexity in my case.

Here's a pretty diagram of my class hierarchy.

It's a flat beast. Apart from everything deriving from Exp, I have only one case of old-skool inheritance in the diagram. And even that one is more making a point than actually shortening the code.

Then there's all the colorful dots, representing the roles I'm mixing into my types. Some are for convenience (like the blue ones), others are vital for my program (like the green ones), and the rest are somewhere in between on the convenient/vital scale.

I even have a case of inheritance between two of the roles! Which means, in practice, that those classes with an orange dot also act as if they had a red dot. Very handy.

During the infancy of Rakudo, I've gotten used to learning to live without various features. Were I to do what I'm doing here without using roles, I could use two other mechanisms. The first is regular inheritance. The very thought gives me a bit of vertigo; I don't think I'd be able to turn the colored dots into base classes. Definitely not all of them at once; I'd have to choose. And that choice would affect the entire design of the program, probably resulting in loss of clarity.

The second way I could compensate for not having roles would be by using .can a lot. The presence of a given role in a class is isomorphic to the presence of a given method in a class. So that would definitely work, but I don't think I would like it as much. There's something to be said for declaring is and does relationships at the very top of the class declaration.

All in all, I'm very happy about the way things work. I'm wondering whether, had I not read all of Ovid's posts on managing the complexity of class hierarchies with roles, I would have come up with this design myself. Maybe, maybe not. But anyway: thanks, Ovid! This rocks!

A still-open question for me is whether the topmost type, Exp, should be a class or a role. Synopsis 12 has this to say about when to use roles:

Classes are primarily for instance management, not code reuse. Consider using roles when you simply want to factor out common code.

I am using Exp for code reuse, and for giving all of the other classes in the hierarchy a common base type. So I guess I could indeed turn it into a role. But it's just that... I don't see a reason to do so, and I still feel instinctively reluctant about it. Maybe I'm a bit hung up about it being a class hierarchy.

This point has come up before on IRC, and I've yet to hear a satisfactory way to resolve it: when faced with making a base type a class or a role, which way should one go?

Friday January 08, 2010
11:22 AM

Adding 'goto' to your Perl 6 program

Today I tested something that jnthn++ and I had discussed during a walk in the non-tourist parts of Riga after Baltic Perl Workshop.

$ cat test-goto
Q:PIR {
  line_10:
};

say "OH HAI!";

Q:PIR {
  goto line_10
}

$ perl6 test-goto
OH HAI!
OH HAI!
OH HAI!
OH HAI!
[...]

Oh. My. Wow.

The 1980's called; they want their infinitely looping toy BASIC idiom back.

I half-expected that not to work, but I'm glad it does. I can even imagine it being of actual, code-simplifying use in some applications. The reports of the harmfulness of GOTO have been greatly exaggerated, if you ask me. Like everything else, the goto keyword shouldn't be overused, but a well-placed goto LABEL can actually improve readability. Often these masquerade as next LABEL or last LABEL or redo LABEL in Perl loops. But those are gotos with a nicer accent, a briefcase, and a better salary.

Unfortunately, the trick doesn't take us very far. Since we're using PIR gotos, we can only jump around within the same sub. Not just the same Perl 6 sub, that is, but the same PIR sub. Since every block in Perl 6 corresponds to a sub in PIR, we can't jump outside of the block.

$ cat test-goto-loop
loop {
    say "OH HAI!";
    Q:PIR {
      goto line_10
    }
}

Q:PIR {
  line_10:
};

$ perl6 test-goto-loop
e_pbc_emit: no label offset defined for 'line_10'
in Main (file <unknown>, line <unknown>)

Well, that certainly makes it less useful. Shame.

Now, how about them PIR-based continuations...? ☺

Friday January 01, 2010
04:31 PM

Highlights of Perl 6 spec changes of 2009

652 individual changes were made to the Perl 6 spec during 2009. I had a mind to read through them and make some sort of list of honorable mentions; unfortunately, that's not likely to happen in the next few days.

But I might as well mention why I got a sudden urge to list noteworthy changes: it's because in 99% of the cases, I like when the spec changes. A lively discussion in the last few days contained mentions of a proposed 'freezing' of the spec, in order to 'get there sooner' with Perl 6. I don't think freezing down the spec at this point would help us get there sooner. It would be if, say, most of the spec changes were ambitious semantic additions and new features. But most spec changes nowadays are responses to questions, complaints, comments and points of particular confusion from implementors, users, newbies or random people of Twitter.

Maybe I'll get around to summarizing the spec changes of 2009 later in January. Right now I'm having too much fun coding on a Perl 5/Perl 6 hybrid application.

Sunday December 27, 2009
01:39 PM

Notation, and the 'business case' for Perl 6

A few days before Christmas, I was sitting in the car with my father. I decided to try to explain why I'm spending time doing Perl 6.

I compared the evolution of programming languages with the evolution of mathematical notation. In maths, it was tricky to imagine the concept of zero before it was formalized down to a number; the idea of derivatives was tossed around in vague forms before Newton and Leibniz made notations for it; we slowly but surely got a standard way of saying "is equal to". And so on.

I was just about to connect this back to how each new programming language can be seen as a contribution to an ongoing, open debate about notation within the programming world, one that has only been going on in earnest for half a century or so. But I never got that far, because my father interrupted me and asked what the business case is for Perl 6.

I was half stumped, half amused by this interjection. I didn't have a good answer for him, besides trying to explain FOSS and the fact that we're not developing Perl 6 with the expectation that someone will buy it from us. But I still felt he had a point; so, earlier today, I took the question to #perl6, and got a set of good replies and musings by Su-Shee++, moritz++, vorner++ and mdxi++. If you have time, do read it.

I'll have to give the 'business case' train-of-thought a lot more time to mature before I can say anything coherent about it myself. But I'd like to say a bit more about notations.

Perl 6 isn't truly revolutionary in a lot of respects. It's mostly lots and lots of minor improvements. (The exception being, I think, things surrounding grammars. Those are truly revolutionary.)

What Perl 6 does do, is provide a 'strangely consistent' notation where a lot of thoughts, with practice, are easy to express. This is very much in the Perl spirit, and the main reason (according to me) to still call Perl 6 a language in the Perl family.

The notational convenience really consists of a thousand little things, but here are a few haphazardly chosen examples:

  • The prefix symbols ?, + and ~ have been co-opted to signify conversion to the 'contexts' Bool, Num and Str, respectively. This parallels their use in binary (infix) operators specific to those contexts, such as +, ~, ?&, +&, and ~&
  • The three short and common verbs is, has and does all do useful work in the OO system. Not only that, but they are a good fit for what they do, and summarize both established and modern OO research.
  • Some syntactic/semantic features are re-used where you least expect it, reducing the total number of independent components in the language. The left-hand side of a list assignment uses the same signature mechanism as do routines. (I.e. the (Bool $a, Int $b, Str $c) in my (Bool $a, Int $b, Str $c) = True, 42, 'foo'; is the same kind of beast as in sub foo(Bool $a, Int $b, Str $c) { ... }.) Smartmatching with ~~ is implicitly re-used in when expressions, and the given/when construct is re-used as the CATCH exception handling mechanism. And so on.

It's things like these that I think make Perl 6 a convenient, attractive notation for thinking about programming. Seeing that notation come alive, and seeing people use it in cool new ways for amazing ends, is the main reason I spend time helping with Perl 6.