Goodbye fake multidimensional data structures

This is a chapter in Perl New Features, a book from Perl School that you can buy on LeanPub or Amazon. Your support helps me to produce more content.


Perl v5.36 disables by default a Perl 3 feature that you may have never seen, which I’ll cover in the next section. In a single-element access to a hash, you were able to use a list of indices to simulate a multidimensional data structure. This was long before Perl had references (and shortly before Taylor Swift was born). Yet, in v5.34, this still works:

use v5.34;
my %hash;
$hash{1,3} = 7;  # modern way is $array[1][3] = 7;

In v5.36, this still works as long as you specify a minimum Perl version with require instead of use:

require v5.36;
my %hash;
$hash{1,3} = 7;

With use, though, Perl loads the appropriate feature bundle, which turns off this feature:

use v5.36;
my %hash;
$hash{1,3} = 7;

The output shows that the multidimensional feature was removed from the list:

Multidimensional hash lookup is disabled at ...
Execution of ... aborted due to compilation errors.

This version also disables switch and indirect.

Enable multidimensional explicitly if you want to restore it, although you should only do this for legacy code since the feature is likely disappear completely:

use v5.36;
use warnings;
use feature qw(multidimensional);

Perl 4’s fake multidimensional hashes

Perl 4 did not have references, so it didn’t have a way include an array in an array. However, you could fake it with a special hash
key convention that Perl stole from Awk.

To make this work, you access a single element in the hash, but have a “list” of comma-separated index values as the hash key:

my %hash;
$hash{0,0} = "a";
$hash{1,1} = "b";

for( my $row = 0; $row <= 1; $row++ ) {
	for( my $col = 0; $col <= 1; $col++ ) {
		printf '% 2s', $hash{$row,$col} // 0;
		}
	print "\n";
	}

This outputs your tiny matrix:

 a 0
 0 b

To see what Perl is doing, dump that hash. The $Useqq variable from Data::Dumper encodes unprintables as their ordinal values in octal"

$Data::Dumper::Useqq = 1;
say Dumper(\%hash);
$VAR1 = {
		  "0\0340" => "a",
		  "1\0341" => "b"
		};

That \034 is (U+001C INFORMATION SEPARATOR FOUR):

printf '% 2s', $hash{ "$row\034$col" } // 0;

Perl calls that $; (or $SUBSCRIPT_SEPARATOR or $SUBSEP). Larry had wanted to use $, but that was already the output field separator. You can use this value directly:

printf '% 2s', $hash{ "$row$;$col" } // 0;

You can mix the forms too. This examples assigns with the comma notation but outputs it by constructing the key itself:

$row = 1;
$col = 3;

$hash{$row,$col} = 7;

printf '% 2s', $hash{ "$row$;$col" } // 0;

Change the separator

If \034 is something that might appear in your data, change the multidimensional separator to something that won't conflict:

local $; = '\000'

From the Perl documentation

switch removed from the v5.36 feature bundle

This is a chapter in Perl New Features, a book from Perl School that you can buy on LeanPub or Amazon. Your support helps me to produce more content.


We’re almost at the end of the tragic saga of given-when, a feature added in v5.10. It lost the lexical $_ in v5.24 after that feature was demoted to experimental in v5.14. Smart matching, almost the entire point of given-when, has already been demoted to experimental status. Then, v5.28 flirted with removing given-when before deciding that was too hasty. It’s been awhile, and it’s on to the next step.

The latest humiliation is that the switch feature (really given-when) is longer part of the list of the default features enabled by requiring a version of perl, as in use v5.26;.

The feature is still there if you want to use it, but you need to explicitly enable it:

use feature qw(switch);

But, don’t start using this feature now. You’ve had plenty of time to fix it and you can get most of what you need using for instead.

No more false postfix lexical declarations in v5.30

Before Perl v5.10 introduced state variables, people did various things to create persistent lexical variables for a subroutine. With v5.30, one of those constructs is now a fatal error.

Often you want a persistent variable to be scoped and private to a subroutine. But, once you leave that scope, normal lexical variables disappear because their reference count drops to zero. So, no persistence.

Continue reading “No more false postfix lexical declarations in v5.30”

Beware of the removal of when in Perl v5.28

[Although I haven’t seen an official notice besides a git commit that reverts the changes, by popular outcry these changes won’t be in v5.28. It’s not that they won’t happen but they won’t be in v5.28. People who depend on Perl should stay vigilant. My advice in the first paragraph stands—change is coming and we don’t know what it is yet.]

Perl v5.28 might do away with when—v5.27.7 already has. Don’t upgrade to v5.28 until you know you won’t be affected by this! This change doesn’t follow the normal Perl deprecation or experimental feature policy. If you are using given-when, stop doing that. If you aren’t using it, don’t start. And everyone should consider if a major change like this on such short notice is comfortable for them. It’s not a democracy but you can still let the core developers know which way you want your favorite language to go.

Continue reading “Beware of the removal of when in Perl v5.28”

Don’t use auto-dereferencing with each or keys

[Update: Perl v5.24 removes this experimental feature, for the reasons I list, among others.]

Perl 5.14 added an auto-dereferencing features to the hash and array operators, and I wrote about those in Use array references with the array operators. I’ve never particularly liked that feature, but I don’t have to like everything. Additionally, Perl 5.12 expanded the job of keys and values to also work on arrays. Continue reading “Don’t use auto-dereferencing with each or keys”

Use array references with the array operators

[Update: Perl v5.24 removes this experimental feature]

There’s a significant change in syntax showing up in Perl 5.14. The array operators push, pop, shift, and unshift previously only worked on named arrays or dereferenced references. Now, thanks to David Golden, they’ll work on array references. Not only that, they’ll work on references that you’ve stored in variables or that come as the return values from subroutine calls. This feature will show up in Perl 5.13.7, so you need to compile a development version to try this: Continue reading “Use array references with the array operators”