Welcome to End Point’s blog

Ongoing observations by End Point people

Perl's Scalar::Util::dualvar

I just came across this fun Perl function that I can't think of a (good) use for, but have to share.

In the Scalar::Util module is the function dualvar:

dualvar NUM, STRING

Returns a scalar that has the value NUM in a numeric context and the value STRING in a string context.

    $foo = dualvar 10, "Hello";
    $num = $foo + 2;                    # 12
    $str = $foo . " world";             # Hello world

Using that in the right place could lead a future programmer down some fun debugging paths!


David Christensen said...

interesting factoid (based on empirical experimentation): boolean context must be determined in part based on string context

$ perl -MScalar::Util+dualvar -le 'print dualvar(0,"true") ? q{true} : q{false}'
> true

$ perl -MScalar::Util+dualvar -le 'print dualvar(1,"") ? q{true} : q{false}'
> false

$ perl -MScalar::Util+dualvar -le 'print dualvar(0,"true") + 0 ? q{true} : q{false}'
> false

So yes, interesting, and also very bug-possible. :-)

Brian J. Miller said...

How about in a dynamic sort routine? Perhaps this is fairly contrived in itself, but if you assigned the same "value" to both parts of the dualvar and then switched operators in a sort you'd get different results between say "cmp" and "<=>".

use Scalar::Util qw( dualvar );

my @list = (
dualvar(10, 10),
dualvar(11, 11),
dualvar(100, 100),
print "Numerical\n";
for (sort { $a <=> $b } @list) {
print "\t$_\n";
print "\nAlphabetical\n";
for (sort { $a cmp $b } @list) {
print "\t$_\n";

Granted it seems a little odd that such a value you'd want to sort both ways.

me said...

some cases where I use dualvar:

- a string which is '0' (which usually
casts to false) but nevertheless true,
like in while (read_next_char())

- to implement $! behavior, e.g. have
a useful error message in string context
but an integer for comparison as error