Suggestions for improving Eiffel

Introduction

We already believe that Eiffel is the best high level statically typed language around. However there are a number of issues with the current Eiffel compilers and IDE:s that we feel need to be addressed. From a pure language point of view, that is to say the language as specified in the ECMA standard, Eiffel is fantastic! But when we look at the environment around the current Eiffel compilers there remains a lot that can be improved.

The issues we discuss here have to do with a) facilitating the use of Eiffel and b) making it easy to reuse code. We challenge the notion of code reuse primarily being a question of quality and specification. We mean it is equally important that it is easy to reuse code.

We believe that Eiffel can learn a lot from the world of scripting languages, especially Python, as to how to make programmers' lives as easy, as enjoyable and as productive as possible!

We are here mainly concerned with  EiffelStudio and the  Gobo Eiffel compiler, but we are happily aware of the existance of other Eiffel compilers like  tecomp. The world can only be a better place if there are more Eiffel compilers! :-)

The issues

Eiffel culture

The Eiffel spirit is characterized by properties like clarity, explicitness, unambiguity, simplicity and elegance.

Yet the power of Eiffel and ambitious projects can lure Eiffel developers into the murky waters of system complexity, over-generalization and monolithism.

We believe it is vital for Eiffel as a language and the Eiffel community to care about the Eiffel spirit and try to foster a pragmatic culture that encourages the above mentioned properties.

We believe the  Zen of Python can be just as well expressed as the Zen of Eiffel as Daniel Moisset ( 1 &  2) already has done. Here' is a slightly modified version of the Zen of Python adapted to Eiffel:

The Zen of Eiffel

  • Beautiful is better than ugly.
  • Explicit is better than implicit.
  • Simple is better than complex.
  • Complex is better than complicated.
  • Flat is better than nested.
  • Sparse is better than dense.
  • Readability counts.
  • Special cases aren't special enough to break the rules.
  • Although practicality beats purity.
  • Errors should never pass silently.
  • Unless explicitly silenced.
  • In the face of ambiguity, refuse the temptation to guess.
  • There should be one-- and preferably only one --obvious way to do it.
  • Although that way may not be obvious at first unless you're French!
  • Now is better than never.
  • Although never is often better than *right* now.
  • If the implementation is hard to explain, it's a bad idea.
  • If the implementation is easy to explain, it may be a good idea.
  • There are languages other than Eiffel and there are systems outside your Eiffel system!

Hello world & programming code drafts

The "Hello World" challenge. How many steps and how many lines of code are needed?

Testing ideas and programming code drafts. How easy is it to set up a new project and run the compiled code?

It should be possible for a user 'gustave' to write, compile and run a Hello World program with (substitute 'edit' for your favorite editor and 'ecompile' for your favorite Eiffel compiler):

/home/gustave/proj/hello$ edit hello.e
/home/gustave/proj/hello$ ecompile hello.e
/home/gustave/proj/hello$ ./hello
Hello world!

Note that no Ace/ECF file was used. A good compiler should be able to fall back on default settings and behaviour. For example 'ecompile' could:

  1. Assume the first class found in hello.e is the root class and that the first creation routine in that class is the root creation feature.
  2. Use default directories for locating kernel classes and other compiler and Eiffel environment specific classes.
  3. Assume that the the current directory also should be scanned for user space classes.
  4. Assume that the user wants to compile a program, ie. not a shared library/DLL.
  5. Use default settings for assertions, code optimizations etc.

If the user 'gustave' wants to know what is going on a '--verbose' flag could be provided which would make 'ecompile' output something like the following:

/home/gustave/proj/hello$ ecompile --verbose hello.e
Config file: /etc/ecompile/ecompile.conf
Root class: HELLO (hello.e)
Root creation feature: HELLO.make
Assertions: require
Target binary: program
Target name: hello
Scanning directories for classes:
 kernel: /usr/lib/ecompiler/lib/kernel
 spec: /usr/lib/ecompiler/lib/spec
 hello: /home/gustave/proj/hello
Pass 2 ... ok
Pass 1 ... ok
Pass 0 ... ok
Generating ANSI C code ... ok
gcc hello.c
ld hello.o -ohello
done

Also a '--generate-ace-file' flag could be provided in order to tell 'ecompile' to also generate an ace/ecf file 'hello.ace'/'hello.ecf', which would be used in subsequent compilations.

Shared libraries

It must be possible and easy to build shared libraries in Eiffel. Period. Let's start with .so files on Linux.

The Ace/ECF file problem

Syntax matters! XML is bad for human beings.

What are the requirements for a Eiffel system specification language?

Unicode support

Current Unicode support is patchy. The Gobo UC_* solution has drawbacks.

There should be two classes UNICODE_CHARACTER and UNICODE_STRING with features like:

class UNICODE_CHARACTER

feature -- Initialization

   make (a_code: NATURAL_32)

feature -- Access

   code: NATURAL_32
           - Code point

   utf8: OCTET_SEQUENCE
           - UTF8 representation

   utf16: OCTET_SEQUENCE
           - UTF16 representation

end -- class UNICODE_CHARACTER

class UNICODE_STRING

feature -- Initialization

   make_from_utf8 (os: OCTET_SEQUENCE)

   make_from_utf16 (os: OCTET_SEQUENCE)

feature -- Access

   characters: LIST [UNICODE_CHARACTER]
           - Code point

   utf8: OCTET_SEQUENCE
           - UTF8 representation

   utf16: OCTET_SEQUENCE
           - UTF16 representation

end -- class UNICODE_STRING

As can be seen a class OCTET_SEQUENCE would be useful. It represents a memory sequence of octets. It would basically be the same as the current STRING class. It should have the following (incomplete) interface:

class OCTET_SEQUENCE

feature -- Initialization

    make (a_size: INTEGER_32)

    make_from_c (p: POINTER, a_size: INTEGER_32)

feature -- Access

    to_c: POINTER

We also need support for literal UNICODE_CHARACTERs and UNICODE_STRINGs as well as basic "string" operations on UNICDOE_STRINGs such as concatenation (+), splitting etc.

Performance

Eiffel can theoretically have performance on par with C and C++. In many cases it does so in the real world too, but there is room for improvement.

Using third party libraries

How should third party libraries be packaged, distributed and installed in order to facilitate reuse?

Principles for the directory footprint of Eiffel class libraries:

1. Respect the  Linux/Debian FHS.

2. Ensure different releases of the same class library can coexist on the same machine.

Thus a standard root directory for Eiffel class libraries could be:

/usr/local/eiffel/<LIBRARY>/<VERSION>

Where <LIBRARY> is the name of an Eiffel library and <VERSION> is a specific release of that library. For example, Gobo and some of it's releases would go here:

/usr/local/eiffel/gobo/gobo38
/usr/local/eiffel/gobo/gobo39
/usr/local/eiffel/gobo/gobo-dev

The convention of suffixing '-dev' to the name of a library can be used for working with bleeding edge code from the source code repository of the library.

By adopting a standard file hierarchy layout for Eiffel libraries we can:

1. Write tools for keeping track of installed Eiffel libraries.

2. Write tools for downloading and installing Eiffel libraries.

3. Facilitate communication between Eiffel programmers.

Class library design

How should class library interfaces be designed? What is the difference between a class interface and a class library interface?

Example: In Python a file can be line parsed like this:

f = open ('foo.txt', 'r')
lines = f.readlines ()
f.close ()
for line in lines do:
    do_something_with_line (line)

The above is a fundamental and common thing to do in programs. Note also that the above solution is platform independent. In Eiffel we need to do:

TBD

Interfacing with the rest of the world

Why is the Internet not recompiled every morning, yet scales flawlessly and remains usable?

Why can't mashups be done in the framework of a universal type system? Why is duck-typing the type system of choice for the web?

What does HTTP-based REST API:s learn us about system interfaces?

Why Eiffel and modern scripting languages not only can coexist, but must coexist! Otherwise Eiffel will continue to be marginalized.

A procedure for documenting suggested improvements to Eiffel

A lightweight yet formalized for documenting improvements to Eiffel would be valuable for the Eiffel community. The Python PEP conventions are excellent and could be easily adapted to Eiffel.

References:

  1.  PEP 1 -- Purpose and Guidelines.
  2.  PEP 9 -- Sample Plaintext PEP Template.

References

  1. TBD.