Perl and the Least Surprised

| 5 Comments

Imagine you're the language designer today. What should this code produce?

my $x = 1;
my $y = 2;

print $x + $y;

What should this code produce?

my $x = 'hello';
my $y = 'world';

print $x + $y;

Easy, right? It gets more fun:

my $x = '10';
my $y = '20';

print $x + $y;

How about:

my $x = '99';
my $y = 'bottles of root beer on the wall';

print $x + $y;

If I were cruel, I'd suggest an example such as:

my $x =   10;
my $y = 0.10;

print $x + $y;

After all, consistency is important.

Here's something even stranger:

my $x = (77, 'seventy seven')[rand 2];
my $y = (99, 'ninety nine')[rand 2];

print $x + $y;

If you object to non-deterministic static typing in tuples, consider:

my $x = readline();
my $y = 'is my extension';

print $x + $y;

Or:

my $x = readline();
my $y = 99;

print $x + $y;

Or (because you can argue that simple variable interpolation is syntactic sugar for repeated string catenation):

my $x = readline();
my $y = readline();

print "#$x is $y's jersey number";

Or:

my $x = readline();
my $y = readline();

print $x + $y;

Without manifest typing, how do you design your language for the least amount of surprise in these cases? More importantly, after you give all of your answers, ask yourself "Why?" and don't stop with "Language X does it this way, which is obviously correct," as the designers of Language X had to ask these questions too.

(For bonus points, defend the thesis "Strings are obviously arrays of characters!" in light of the polymorphic overload of addition in the integer/rational case.)

5 Comments

Hmm. Seems to me Perl already solved this problem: the arguments are determined by the operator, not the operands. This is different than other languages, but no less understandable. For example, here's a snippet of Objective-C:

NSString*str =[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:NULL];

"What? Those square brackets, I don't get what they're dereferencing!" Oh, that's right, different language, different context.

In Perl, + means "convert my arguments on the left and right side of me to numbers, then add them." Once readers get that, it becomes immediately obvious why adding two strings won't work: there's nothing to convert them to! It also becomes immediately obvious why "77 camels" + "99 lhamas" equals 176 - a "to num" operation was run on them, because you asked it to.

Incidentally, with warnings on, your code snippet from above makes a whole lot of sense, for even a novice:

use 5.012;
use warnings;

for (0..3) {
my $x = (77, 'seventy seven')[$_%2];
my $y = (99, 'ninety nine')[$_ say $x + $y;
}
^D
use 5.012;
use warnings;

for (0..3) {
my $x = (77, 'seventy seven')[$_%2];
my $y = (99, 'ninety nine')[$_<2?1:0];
say "$x + $y : ", $x + $y;
}
^D
Argument "ninety nine" isn't numeric in addition (+) at - line 7.
77 + ninety nine : 77
Argument "ninety nine" isn't numeric in addition (+) at - line 7.
Argument "seventy seven" isn't numeric in addition (+) at - line 7.
seventy seven + ninety nine : 0
77 + 99 : 176
Argument "seventy seven" isn't numeric in addition (+) at - line 7.
seventy seven + 99 : 99

The way I teach people about Perl is that scalars are NOT integers, they are NOT floats, and they are NOT character arrays. I teach them that a scalar is a bucket. It holds one thing, and one thing only. It can hold any "one thing", be it a class instance, a reference, a file handle, a number, a string, a character, but it's always just one thing, and that's what makes it unique. Then I teach them that Perl uses that "one thing" differently, based on the operators.

Once people realize that a scalar is fundamentally different than "a number" or "a string", and think of it as "a storage location for something I'm concerned about", it becomes immediately obvious that a + on two scalars has the effect it does. They realize that the container has no idea what it contains, and doesn't care - it's simply how you USE the data that matters.

Exactly. Perl is an operator-oriented language with typed containers. You must understand that to be adept with Perl.

I like operator overload and syntactic sugar, it makes life more simple.

Add two numbers: sum

Add two strings: concat

Add a number and a string: the string cannot always be converted to a number, but the number can always be converted to a string (you typed it!) convert it and then add two strings. If it can *always* be done it is less surprising than something that may or may not happen.

Add an integer and a float: those are two numbers to me. The result should not lose precision if the computer can handle it in a feasible way (should I explain what is feasible?, maybe other day) that means a float should be used.

Random of two 'things': one of them. Should I explain what is a owl:Thing? Computers seem to have that concept quite clear.

Do you mean "typed containers" as in operators coerce the contents of the containers to behave as certain types?

Operators do coerce container contents, but I meant that the primary types in Perl 5 are scalar, array, and hash.

Modern Perl: The Book

cover image for Modern Perl: the book

The best Perl Programmers read Modern Perl: The Book.

sponsored by the How to Make a Smoothie guide

Categories

Pages

About this Entry

This page contains a single entry by chromatic published on May 17, 2010 12:11 PM.

A Modern Perl Fakebook was the previous entry in this blog.

The Perlegorical Imperative and the Will to Contribute is the next entry in this blog.

Find recent content on the main index or look in the archives to find all content.


Powered by the Perl programming language

what is programming?