Skip navigation

Monthly Archives: December 2010

I’ve been meaning to write about this for a while, but truth be told I’m still not sure how it all works out. Still, I’m guessing some flawed knowledge is better than.. Well, No it’s not, but whatever.

But let’s introduce the topic first. Basically, I’m talking about this:


my $bad_example = '123456789';

substr($bad_example, 0, 6) = 'This sure is, ';

substr($bad_example, length($bad_example) -3, 3) = "\nA bad example";

say $bad_example;

This works because certain functions work as lvalues – But that does bring the question, what’s an lvalue anyway?
The simplest answer, an lvalue is the left part of an assignment. Conversely, an rvalue is the right side of an assignment.
That’s a hard one to shallow, isn’t it?

Anyway, there are a few builtins that you can use a lvalues. I saw ‘a few’, because frankly, I only know of three — There’s probably whole lot more of them out there. They are pos, substr, and vec.

pos is simple enough: it returns the position from which the next //g regex will start looking. Every scalar has it’s own pos, which is set automatically after every match with the g modifier,  or, more relevant to this post, you can set manually:


my $some_string = 'Why hello there';

pos($some_string) = 3;  #Mandatory parens!

say join ', ', $some_thing =~ /\w+/g;

Which will show “hello, there”, rather than all three words.

Assigning to substr, on the other hand, works something like a poor man’s four-argument substr – Rather than passing the replacement string as the final argument, you assign to the three-argument form:


my $other_string = "One day I'll get something entertaining to put in these.";

substr($other_string,  27, 12) = 'AWESOME'; #Mandatory parens!

say $other_string;

There are few reasons to actually use this, though. But for one, the three-argument form of substr has some magic in it, which you can see working in its perldoc entry. On the other hand, the four-argument form returns the substring replaced, and you don’t have to deal with any inner magic working behind the scenes, possibly against you.

Finally, vec. I don’t get vec, so this part might be lacking substance. More than the usual, anyway.


my $bitfield;

vec($bitfield, 0, 32) =  0x5065726C; #Guess what those parens are!

say unpack('b*', $bitfield);

I’m going to write an article about vec eventually, so any links, explanations, additions, or corrections, would all be welcome.

Well, that’s all for today. I would end these with some note of how cool what I just wrote about is, but either you already find it fascinating (here’s hoping!), or I’m not going to change your mind. Until next time, my non-existent readers!

(Apologies to my nonexistent readers for the delay between posts.. University/family/work been keeping me busy. This article is nothing special really, but it’s something that got me stuck for a couple of minutes.. Which is exactly how long I have to write this. Huzzah!)

This actually came up during work, but the language was Ruby; Apparently newer versions have a method that does something similar to Perl6’s .pick, but unfortunately we lacked this, so in the end, we ended up redefining the Array class and that was it. But while implementing it, I kept thinking of how I’d do it in Perl.

But let’s put this into context. Usually, if you wanted a random item from an array, you’d say:

my @array = 1..10;

my $random_element = $array[rand scalar @array];

That’s rather simple, eh? But what if you, for whatever reason, didn’t have the intermediate array? How would you do some like

my $rand_elem = (1..10)[rand(10)]

But without the luxury of knowing in advance how many elements the list has?

For me, well, the answer was cheating 🙂

my ($elem) = map { $_->[ rand scalar @$_ ] } [ (1..10) ];

We turn the list into an anonymous array, and pass the reference to the list as the single argument of a map – Inside the map, $_ is the arrayref, which we promptly derefer for the item in an index picked at random.

..So much for not using an intermediate array, I guess, but who cares. It also leaves the “random” part fairly non-random – But for a much better coverage of that than I could do, read brian d foy post here.

For those with an aversion to punctuation, this could be rewritten as

my $elem;

$elem = $array_ref->[ rand scalar @$array_ref ] for my $array_ref [ 1..10 ]

..But now you have to predeclare $elem.

If anyone ever reads this, post your solution!