So combining the easiness of interactive development with performance when it was time to ship the product.
It was also available before Java was a thing.
This is what I always kind of missed with Java and .NET, the previous generation of languages (Eiffel, Modula-3, Oberon(-2)) all had a mix of interactive development and AOT compilation for shipping release builds.
The Eiffel compiler required four distinct sequential processes (note: not phases. I really mean that four programs needed to be run in sequence, and each of these four programs implemented who knows how many passes). Eiffel generated C++, huge executables, was incredibly slow (even with contract stuff turned off).
It was very hard to debug, with gdb routinely giving up on the complex .o generated. It was a very verbose language that implemented all known features under the sun, a bit like Ada and Scala.
Eiffel didn't take off for some very solid reasons.
This was not an inherent problem of the language, but one of the implementation.
I know this because I wrote a compiler for an Eiffel dialect for my Ph.D. thesis and there have been other Eiffel compilers without these shortcomings.
Also, EiffelStudio – which seems to be what you are talking about –
generated C code, not C++ and had the option to generate an intermediate representation instead that could be mixed with compiled code.
> It was a very verbose language that implemented all known features under the sun, a bit like Ada and Scala.
It was actually pretty minimalist, not at all like Ada or Scala.
Code was verbose because (1) programmers were encouraged to annotate methods with contracts and (2) exactly because it was minimalist and didn't have a lot of alternative ways of expressing the same functionality.
Edit: There are two hard parts about writing an Eiffel compiler.
1. Getting the semantics of feature renaming during inheritance right. If you aren't careful, it's easy to introduce errors during this step.
2. Doing separate compilation for mutually dependent classes. This is where much of the complexity of the EiffelStudio compiler comes from. Java solved the problem by simply not allowing separate compilation in those cases. If class A has a member of type B and B has a member of type A, they need to be compiled together.
Everything else that's involved in writing an Eiffel compiler does not require more than than what you learn in your typical compiler course. (Though, obviously, experience will get you better results.)
I think that must be what I was referring to by my mention about melting or freezing in a nearby comment. Didn't remember the technical details. Interesting feature. Wonder if other languages have something like that.
(Edit: Reading over it again, I realize that this may be read as criticism. To clarify, while I disagree with Meyer on some things, this isn't about disagreement. He is a teacher at heart – in fact, a very good teacher – and you can see some of his habits for keeping students engaged sometimes carry over into his writing.)
You don't see this approach really anymore, because these days it's so cheap to just generated unoptimized native code if compilation speed is an issue.
Obviously, if you have a JIT-compiler, then something similar happens internally in that some methods will be compiled, while others will be left in IR form (and sometimes, methods will even revert to using their IR). This was technology from back when CPU speed was still expressed in MHz.
OCaml had and still has both a bytecode and a native code format (for similar reason), but they cannot be mixed. OCaml's bytecode still sees use for (1) the bootstrap process, which allows you to build OCaml from scratch, (2) to run OCaml code on oddball architectures that the native compiler doesn't support, (3) to run code in the timetraveling debugger, and (4) when you need compact rather than fast executables.
OCaml's bytecode interpreter makes use of the fact that OCaml is statically typed and therefore doesn't incur nearly as much of a performance penalty as bytecode interpreters for dynamically typed languages.
>Obviously, if you have a JIT-compiler, then something similar happens internally in that some methods will be compiled, while others will be left in IR form (and sometimes, methods will even revert to using their IR).
I was going to say (in my parent comment to which you replied) that maybe that Eiffel's Melting Ice tech is something like Java JIT tech, but wasn't sure if they were the same thing.
The others already replied why.
Why on earth would one need to use gdb, given the nice graphical debugger of EiffelStudio?
Also it was way faster than code produced by Java, which I remind only got a JIT with version 1.3 and to this day only third party commercial JDKs do offer support for AOT to native code.
Java is also quite verbose. Verbose languages are quite good for large scale development.
On real life the majority of code is read not written, so I rather have it verbose and comprehensible than trying to make sense of a line full of hieroglyphs.
(Haven't worked much on Java recently, but did use it a fair amount some years ago.)
Isn't Java roughly equally verbose as Eiffel?
>that implemented all known features under the sun
At least based on looking at the Wikipedia article for Eiffel, it does not seem to have implemented functional programming, unless the article is out-of-date, or unless the agent mechanism supports FP somehow (not sure about that last bit).
That sounds like unrelated to the semantics of the language.
I seem to remember that there was some intermediate form of language translation too - something called melting or freezing or some such (might have been two different things). This was for EiffelStudio, probably, not generic Eiffel stuff.
>This is what I always kind of missed with Java and .NET, the previous generation of languages (Eiffel, Modula-3, Oberon(-2)) all had a mix of interactive development and AOT compilation for shipping release builds.
Interesting. Didn't know that that generation had both. As an aside, I had read a good description about Modula-2 (not -3) in a BYTE article (IIRC, years ago), and it seemed to me at the time that it was a good language. Having had a good amount of Pascal background before doing a lot of C, I was interested to try out Modula-2, but probably didn't have access to any compiler for it at the time. Later I read that Delphi's feature of units for modularity may have been inspired by Modula-2's modules, along with the concept of separate compilation.
The OOP features in Turbo Pascal are based on Object Pascal, which was designed at Apple for their Lisa and Mac OS systems programing language, with input from Niklaus Wirth.
Turbo Pascal was the reason why most PC developers never had too much love for Modula-2, because by Turbo Pascal 4.0 we had all the goodies from Modula-2 with case insensitive keywords.
Also, the compilers were more expensive than Turbo Pascal ones.
Incidentally Martin Odersky was the author of Turbo Modula-2, the short lived Modula-2 compiler sold by Borland.
I usually thank my technical school for having us go through Turbo Basic and Turbo Pascal before getting into Turbo C.
We were using Turbo Pascal 5.5 (I already knew 3.0 and 4.0) and 6.0 was still hot out of Borland's factory, which is why I've always been a fan of strong typed systems programming.
Turbo Pascal was the Pascal I'd used too, for a good while. Loved that environment. Really fast dev time and a fun language to work in.