This weekend I attended PPW2011 - I think this is my 3rd PPW, and my fourth perl conference in Pittsburgh (YAPC::NA 2009 was there).
The theme this year was "DevOps", and I think maybe that was not quite to my taste (though does seem practical). I like talks that push my understanding and stretch my mind, whereas the talks tended toward solid best practices for corporate environments. I gave a talk on debugging, and I even feel that my own talk went that way a bit :)
Favorite talks:
That last one was a set of mini-talks by Mark-Jason Dominus, which included one of my all-time favorites, Debugging the de Bruijn Sequence. Highly recommended!
Last Tuesday was our monthly DC Perl Mongers meeting.
We dove right in, talking about how perl caches various values for a variable to be used in different contexts. So, for example, let's say you start off with a number, but then use it in string context, perl will cache both the string and the number. This can be shown using Devel::Peek like this:
main:001:0> use Devel::Peek
main:002:0> my $x = "34"
34
main:003:0> Dump($x)
SV = PV(0xb22d558) at 0xb237290
REFCNT = 2
FLAGS = (POK,pPOK)
PV = 0xb249458 "34"\0
CUR = 2
LEN = 4I often use Devel::REPL at meetings so that we can interactively explore things as a group, which is what I'm doing here.
The first time we dump $x, you can see it has a "PV" which holds the string "34". But after we use it in a number context, adding 17 to it, you can see that the dump shows both the original string version, and a new "IV" containing the integer version:
main:004:0> $x + 17
51
main:005:0> Dump($x)
SV = PVIV(0xa0fe6b8) at 0xb237290
REFCNT = 2
FLAGS = (IOK,POK,pIOK,pPOK)
IV = 34
PV = 0xb249458 "34"\0
CUR = 2
LEN = 4So this, as far as I know, is mainly an efficiency hack that perl does, the theory being that if you used it once in string context or number context or whatever, maybe you'll do it again.
Very quickly the question came up as to what happens when you change $x, and how does perl know what cached values to trust. Well that's where the 'FLAGS' part of the SV dump comes in. It shows which of the cached values are OK to use. So when we increment $x numerically:
main:006:0> $x++
34
main:007:0> Dump($x)
SV = PVIV(0xa0fe6b8) at 0xb237290
REFCNT = 2
FLAGS = (IOK,pIOK)
IV = 35
PV = 0xb249458 "34"\0
CUR = 2
LEN = 4The flags have been trimmed down. I don't remember what all the flags mean, but you can look at perlguts or other docs for that :) . Notice that the string version of the original "34" is still there! Perl doesn't waste time erasing it. Instead, if string context is used again a new cached value will overwrite the existing one.
Well that was surely a good start to the meeting :)
A while back I wrote about Funky Function Filters. Let me refresh your memory - we have a Python and a Ruby snippet and we translate it into Perl5. The code is a toy to show some fancy shmancy lambda (unnamed functions) usage. The idea is to take a list of functions, filter them, and then with the remaining ones show what happens with parameters from -10 to 10.
Python example:
for f in filter(lambda f: f(-1)>=f(1),
[lambda x:x, lambda x:x**2, lambda x:x**3]):
for x in range(-10, 11):
print x, f(x)Ruby translation:
for f in [lambda { |x| x }, lambda { |x| x**2 }, lambda { |x| x**3 }
].select { |f| f.call(-1) >= f.call(1) }
for x in -10..10
print x, f.call(x)
end
endMy perl5 translation:
for my $f (grep { $_->(-1) >= $_->(1) }
((sub{shift}, sub{(shift)**2}, sub{(shift)**3})) {
for my $x (-10..10) {
print "$x: ",$f->($x),"\n";
}
}Today I thought I'd give a stab at a perl6 translation (using the 2011.01 Rakudo Star release). I started with a straightforward translation from the perl5, then switched to perl6 idioms.
Perl6 translation:
for (* ** 1, * ** 2, * ** 3).grep({ $_.(-1) >= $_.(1) }) -> $f {
for -10 .. 10 -> $x {
say "$x: { $f.($x) }"
}
}The first line is a doozy! This is similar in some ways to the perl5 translation, though the grep now shows up on the righthand-side of the list like in Ruby. The biggest difference to me is in the list of lambdas:
(* ** 1, * ** 2, * ** 3)I mean... what does THAT mean?! Let's take the last one, "* ** 3". Translated into English:
Whatever to-the-power-of 3Wait wait... "whatever"? The Whatever-Star is a fancy thing from perl6 that took me a while to work out, and there may still be some nuances that I'm missing. In this context it magically makes a closure... er... lambda, that takes one parameter which it puts where you see the '*'.
# Whatever-Star notation
* ** 3
# Pointy-block notation
-> $x { $x ** 3 }
# Subref notation
sub ($x) { $x ** 3 }(Note: that last one should be SLURPY! But I don't know how to do that apparently)
Enjoy... Whatever!
The "Whatever-Star" was at first alarming to me! I first noticed it when I learned how to shuffle an entire list. The Whatever-Star can do some other stuff, too. But that's ok, we'll start with this.
my @shuffled = < alice bob carol dave erik frank >.pick(*);Now... in the past I've tried ".pick(1)" which gets me one name at random. Then ".pick(2)" will give me two, and not repeat. If I put in too many then it'll only give me back what it can, in this case all six names. But ".pick(*)" ... that doesn't even look valid! The documentation says (though I can't recall where) that it is the same as ".pick(Inf)". When I picked more than there were, it stopped when there was nothing to pick. So this makes sense... try to pick an infinite number and we'll just get them all. Nice. Still kinda weird about the '*' though.
So then I, mistakenly, thought that maybe "pick" was special. Maybe they hooked the parser up so that it could, like, "know" that pick could be passed this '*', which I learned is named "Whatever". I couldn't have been closer to the truth! Except without the "special" bit. Time to do a bit of exploring!
Let's try to figure out how this works without resorting to such tedious things as reading documentation, source code, or IRC, shall we? RTFM my eye. If pick is special, then I shouldn't be able to add something that behaves similarly. Wait, let's do this formal like.
THEOREM: (1,2,3,4).pick(*) is somehow special, and can't be replicated without modifying the compiler.
PROOF:
Let's start by assuming that it is NOT special, and attempt to do a proof-by-contradiction (constructivists be damned¹). Then we should be able to create our own method that can behave specially when '*' is passed.
First, what class is .pick(*) working on, anyway? Let's ask rakudo.
> (1,2,3,4,5).WHAT
Parcel()Parcel. OK, whatever that is. So all we gotta do is slap a new method on there and see what we get. (google... google... irc... (yes, contrary to the overall anti-research basis. But it's ok because we're in parenthesis)). OK, here we go.
> use MONKEY_TYPING; augment class Parcel { method yo($x) { say "I like to eat $x." } }
!class_init_384
> (1,2,3,4,5).yo('fishies')
I like to eat fishies.Well that was easy :) . Now for the BIG TEST!
> (1,2,3,4,5).yo(*)
I like to eat Whatever()<0xb2f5a7c>.OMG it worked! So I actually get a parameter, and it is an instance of Whatever. Well then.
THEOREM DISPROVED.
I then decided to actually cast about for how things use this. Here's a great example, the Rakudo Any-list pick whatever implementation. You can see that they use multi-methods to easily deal with the Whatever case separately from other passed values.
[1] I actually like constructivists, and welcome a constructive version of this non-proof.
On my way to Safeway, I stopped in at Filter Coffee to see how they are doing. The nearby Safeway (The Secret Safeway) is closed, but this is still roughly on the way to The Soviet Safeway anyhow. A seat was open so down I plopped.
First they played the entire Rage Against The Machine, Battle of Los Angeles album, and now we're on to the Ramones with Blitzkrieg Bop. Sounds like they're going to play this whole album too.
Good music, good mocha. Where was I on my way to again?
META INFORMATION: This is the technical blog and wiki of Brock Wilcox (awwaiid). Entries focus on my current projects, interests, and sometimes life events. If you'd like you can check out the list of All Entries or the RSS Feed. I also have a LiveJournal syndication feed for LJ friends.