Saturday, February 17, 2007

 

Eiffel and Perl

I just converted an extremely small Perl program into Eiffel. That led me to ponder a few differences between these two languages. First of all the task: any time a line is received in standard input, write the current unix time (number of seconds since the epoch which is 1970) plus 7 seconds to standard output.

The Perl program is brief:
#!/usr/bin/perl
$| = 1;
while () {
print time() + 7, "\n";
}
The Eiffel variant is considerably longer:
class

TIMESTAMPS

inherit

STDC_CURRENT_PROCESS

CAPI_TIME
export
{NONE} all
end

creation

make

feature {NONE} -- Initialization

make is
local
s: STRING
future: INTEGER
do
stdout.set_no_buffering
from
create s.make (16)
until
False
loop
stdin.read_line
future := posix_time + interval
future.append_in (s)
s.append_character ('%N')
stdout.put_string (s)
s.wipe_out
end
end

feature -- Access

interval: INTEGER is 7
-- Number of seconds

end
That the Eiffel program is much longer is due to the fact that it is written to be a bit longer, for example the number of seconds has become a constant, something that is good practice, but more naturally done in Eiffel.

Also in Perl many things are somehow available. For example access to standard input. Although they are in SmartEiffel as well, that would lead to code that is not portable. And one can argue that standard input should not always be available. What is the meaning of standard input on a mobile? For a GUI program? There is no such thing. So I have to pull those in explicitly using the STDC_CURRENT_PROCESS class. Just as well as for the definition to retrieve the Unix time using CAPI_TIME. Both are eposix classes by the way.

A couple of lines in the Eiffel program are taken up by building the string. Of course, I could have written:
 stdout.put_string ((posix_time + interval).out + "%N")
But that would have required the inclusion (and minor overhead) of the garbage collector. Because this program runs in a loop, is of minimal importance and should therefore not really bother the CPU, I didn't want to include a garbage collector. So I could not call a query like out which creates a new string every time it is called. I would run out of memory after a few months. So I had to use some SmartEiffel specific code here to very careful turn the integer into an existing string. This string s is created only once. No other objects are created in the loop, so no garbage collector needs to be included.

Perl probably creates new objects in its loop and has to garbage collect them. But the Perl interpreter contains a garbage collector anyway.

The readability is also different. The integer to string conversion in the Eiffel code is its most unreadable part, the other lines are self explanatory. But in Perl, what does the line:
 $| = 1;
do? From the Eiffel code we can learn it turns off buffering of standard output. Actually the whole story behind this line is rather long. It actually means to turn off buffering for the hot file handle. Insert rant here (see section "Bad documentation").

A line like
while () {
isn't also not immediately readable. It has something to do with standard input, and it looks like a loop that while there is something on standard input do something.

The run-time overhead is probably also different, but with todays CPU cycles not really relevant.

The last thing is installation. The Eiffel program has no dependencies except on standard system libraries. To run the Perl program the Perl interpreter must be installed on the target system.

So this particular program is perhaps not the best use case for Eiffel. But it is always fun to write Eiffel code, so the more lines of Eiffel, the more fun.

Labels:


Comments:
I would add that writing the Eiffel version also involves writing an ACE file or equivalent (or having an IDE write it for you).

Although the Perl solution has a dependency on a Perl interpreter, that also has the upside of providing platform independence. Move the Eiffel solution from Linux to Windows and you need a recompile.
 
Actually, not strictly true. We [Eiffel Software] are calling for feedback on Compilation Without Configuration.

It will allow developers or new users to simply copy and paste examples from the web and compile them without a configuration file. I've called for the #! usage to ignored by the parser so we can implement a build and run mechanism, allowing the Eiffel files to be executed from a shell.
 
You do
print time() + 7, "\n";
with "\n" - it means that you don't need to turn off buffering in Perl.

If you still need it, for better readability you can write
use English qw( -no_match_vars ) ;
$OUTPUT_AUTOFLUSH=1;


or (preferred)

use IO::Handle;
STDOUT->autoflush(1);

 
You quote http://www.cs.usyd.edu.au/~sholden/pythonperl.html - but it is very old article (some of what is described there was changed at least 7 years ago). Many anti-Perl articles are written by people who read very old tutorials.

P.S. You can create executable from Perl program with PAR.
P.P.S. I have studied more than 10 computer languages, but I cannot guess what this lines mean:
from
create s.make (16)

 
Post a Comment



<< Home

This page is powered by Blogger. Isn't yours?