Horror stories about Perl programmer. With hints and solutions.

Home
About
Authors
Why?
rss
@perltrapcom
Email subscription
Michael once read that constants in Perl can be made out of functions that return constant expressions.

Michael tried the following:

```
#!/usr/bin/perl
use strict;
use warnings;
# legs of one ant
sub AN_ANT_LEGS { 6 };
print "1 ant has ".AN_ANT_LEGS." legs\n";
print "7 ants have ".(AN_ANT_LEGS * 7)." legs\n";
```

Download the source code.

The progtram worked, but Michael was unhappy with the result. Why did it happen?

Zoological note: ants are insects, every insect has 6 legs. So one ant has 6 legs, and 7 ants have 42 legs.

Michael tried this:

```
for my $i (1 .. 100){
print "$i ant".($i > 1 ? "s" : "")
." ".($i > 1 ? "have" : "has")
." ".(AN_ANT_LEGS * $i)." legs\n"
;
}
```

Download the source code.

He got compilation error:
`Can’t use string (”1”) as a symbol ref while “strict refs” in use`

And what about this?

`sub AN_ANT_LEGS() { 6 };`

Originally subroutine `AN_ANT_LEGS`

interprets
the following `* 7`

as parameter.
It’s possible,
as `*7`

is reference to typeglob named `7`

.

But the subroutine doesn’t use any parameter and still returns 6.

So the first program prints:

```
1 ant has 6 legs
7 ants have 6 legs
```

The program with loop has a similar problem.

In hint #3 empty prototype explicitly specified that subroutine uses no parameters, so multiplication works as expected.

Module constant.pm does exactly the same: it creates subroutines with empty prototype and each subroutine returns a constant.