Apparently I solemnly swore in the last p6cc blog
post that this blog
post would appear sooner than after a two-month break. Apparently I suck at
living up to what I solemnly swear. Anyway, kudos to $dayjob for keeping me
healthily occupied with things, and a big thanks to all people related to Perl
6 who gently reminded me to keep up with the reviewing.
(Or maybe I didn't specifically mean "the next
p6cc blog post", but just "the
next blog post"? I wish I could make myself believe that. No, the real answer
is that reviewing stuff takes time and effort, and my time and effort have been
Let's talk about crossing wires in elegant ways! Here, I'll let the description
refresh your mind:
## Arrange wire crossings to rearrange wires
Ten wires are come in from the left. Ten wires leave to the right. Write a
program that, given a permutation of the digits 0..9, arranges crossings on a
grid that places the wires in the order designated by the permutation.
The output consists of a grid whose elements connect the left and right sides.
Each cell of the grid is either *empty* (in that it just lets the wires
through), or a *crossing* (in that it lets the wires trade places). Two
crossings can never be placed vertically adjacent to each other. (This is
equivalent to saying that the wires never split or merge, they only permute.)
Often, solutions require crossings to be spread out not just vertically but
also horizontally. It is considered elegant not to make the grid wider than it
has to be.
0 _ _ 1
1 _/\_ 0
2 _ _ 3
3 _/\_ 2
4 _ _ 5
5 _/\_ 4
6 _ _ 7
7 _/\_ 6
8 _ _ 9
9 _/\_ 8
(This permutation is simply flipping wires pairwise.)
0 _ _________________ 1
1 _/\ _______________ 2
2 ___/\ _____________ 3
3 _____/\ ___________ 4
4 _______/\ _________ 5
5 _________/\ _______ 6
6 ___________/\ _____ 7
7 _____________/\ ___ 8
8 _______________/\ _ 9
9 _________________/\_ 0
(The simplest way to bubble 0 to the bottom.)
0 _________ _ 5
1 _______ /\_ 0
2 _____ /\___ 1
3 ___ /\_____ 2
4 _ /\_______ 3
5 _/\ _______ 6
6 ___/\ _____ 7
7 _____/\ ___ 8
8 _______/\ _ 9
9 _________/\_ 4
(The simplest way to bubble 4 and 5 simultaneously.)
The reviews are in. To get the full enjoyment out of this blog post, I highly
recommend that you read the
reviews as well as
this post. The solutions are a varied bunch, and there's lots of nice code in
How would a program find a nice, short solution to the write-crossing problem?
Wait, can we even be sure there always is a solution? If the fundamental
operation is crossing two adjacent wires, can we really generate the full space
of permutations? (As opposed to, say, only half the space, like in the 15
We can generate the full space of permutations. The quickest way to convince
ourselves of that is to think of sorting algorithms, many of which use "flip
two adjacent values" as its fundamental operation. Sorting algorithms can sort
anything, hence the wire-crossing problem always has a solution.
(Wouldn't it be weird to live in a world where sometimes you'd pass in a list
to be sorted, and the computer would come back and say "sorry, this is one of
those unsortable lists of values". What a bummer!)
In fact, many of the solutions took the sorting analogy to heart, producing
something like a bubble sort with
slightly modified rules. In bubble sort, the same value can be transposed
several times during one run, something that isn't possible in the wire
universe: you flip two writes, and you then have to wait until the next column
to flip either of those wires again. But with that little restriction added,
bubble sort seems to solve this problem just fine.
As always, it's nice to see how people's styles differ broadly. I never see two
identical solutions, but this time around, it felt especially varied. Maybe
because the problem is relatively small, and one wouldn't think there were that
much to vary. But just watch as people apply dynamic variables, feed operators,
enums, junctions, sequence operators, metaoperators, and many other things to
solve the same problem. There Is indeed More Than One Way To Do It.
As of last review post, we were down to five finalists. Now we're down to four.
[...] what makes me the most optimistic about the Perl 6 effort: after a few years of watching things evolve, I've noticed that while Perl 6 is being developed top-down on the outermost scale, it's actually a series of bottom-up projects that drive Perl 6 forwards.
Over the years, Perl 6 users have seen a descending sequence of components being replaced and improved, each one furthering our reach. It reads almost like a nursery rhyme, though with a positive spin:
When we had junctions, we got ourselves a method dispatch that served them better.
When we had method dispatch, we got ourselves an object system that served it better.
When we had an object system, we got ourselves 6model that served it better.
And people have been talking about taking the obvious next step with this: building a runtime, or retrofitting an existing runtime, that would serve 6model better.
Imagine taking all the lessons learned about Perl 6 and VMs, and factoring them into a project like this. jnthn's article goes on to list all the things that MoarVM does:
lightweight and focused
quick and easy build
JIT compilation (to be explored in the future)
The really nice aspects of this can be read between the lines: MoarVM is lightweight, so it starts up faster than the JVM, and even before the real optimization and JIT work begins, its runtime performance already shows some promise.
There's no historical baggage, and there's not a sense that the project is fighting technical debt when moving forward. Since MoarVM is designed for nqp from day one — in a very real sense, MoarVM is an nqp backend — we're guaranteed both a nice direct focus on Rakudo, as well as the ability to support other higher-level languages long-term. Things are factored in a way that we can build Perl 6 on. Hard-earned VM lessons from 2001 up until today are coded into the foundation.
In other words, MoarVM reboots the whole VM idea for Perl, based on experience with Parrot, without many of the flaws of Parrot.
On May 1st I learned what happens if you tell a bunch of people on the
Internet, not all of whom you've met before, that you're going to teach Perl (5
and 6) for free on an IRC channel for four hours.
It worked well. Actually, it worked well beyond my expectations.
Prepare. I had written a bunch of material; short-ish texts mixed with
exercises. I didn't hear any feedback about the texts, but people threw
themselves on the exercises. Which was lucky, because I basically didn't
have time to interact much with people. Everyone did their own thing.
Map. The week before the workshop, I was taking a walk, and it occurred
to me that the topics for the workshop should be laid out on a subway map.
That turned out to work unexpectedly well. People followed the structure,
I think. The material was pretty clear that they were free to skip/jump
around if they wanted, so some did that.
Github. People suggested fixes and improvements to the material during
the workshop. I handled the easy ones, and delegated what could be delegated.
If anything about the workshop felt 2013-futuristic, it was the fact that
participants were hacking on the workshop in real time, as it was being
played out. Github was totally right for this.
tadzik++ did an exercise and got a solution that I didn't expect. We
agreed that a test was missing to force people to do the right thing,
so he went ahead and added it.
LlamaRider++ added hyperlinks between all the files.
grtodd++ made the subway map clickable.
choroba++ added hyperlinks to a file that I added later.
Newbies. This was never a workshop for total beginners. Still, we got
a number of those. I'm not sure how many. If there's a next time, I'll
want to add a track for the people who haven't done Perl before.
Exercises. Based on the tasks that people actually
solved, I got a
lot of feedback on what worked and what didn't. Which exercises served the
overall message of the course, and which ones didn't.
Message. After the workshop, I know much better what I wanted the
whole thing to be about. I think I can go back and make that even more
clear. I'm still surprised at how well it worked already the first time
around... but some bits in there can certainly be improved.
So... what was the real message of the workshop? What is "masakism"?
Testing gets you far.
My pain threshold for writing things without tests is half a screen of
code. If I have more than that, there's probably something I should
be writing tests for.
That said, there's no need to be a fundamentalist about anything. I'm
just saying that tests are good, and still somewhat undervalued
sometimes. But it's always a question on spending time testing the
stuff that matters. Of course.
Even with tests, there's no substitute for knowing what you're doing
and where you're going. Tests help a lot, but they don't write the
program for you.
Keep it small and simple.
"Inside every big interesting problem is a small interesting problem,
struggling to get out."
The realization that you can write objects that focus entirely on
your core problem, is a strong one.
People tend to bring in persistence too early, "polluting" their core
classes with database code. Hindering testability. This is backwards.
Your program should be like an onion, with the most precious stuff
in the middle, and layers around that. Outer layers should point to
inner layers, but not vice versa.
So, should we do another #masakism workshop?
Yes, maybe we should. People seemed to like this first one. I'm open to finding
a datetime for another one.