In Eiffel all arguments of routines are pure input arguments. There is no possibility to return an argument. The only possibility is to write a function and return a value as "Result".
Furthermore Eiffel has command query separation, i.e. a command can change states and a query should only return a result and do nothing beside that. Command query separation -- allthough not yet enforced by the language and its compilers -- is a very powerful software principle which allows us to reason about our software and use queries within assertions.
However there are routines which are commands (because they change state) and have a result. E.g. the feature `read_character' of class FILE advances the cursor of the file (therefore it changes state and is a command), but has as a result the read character. The only possibility in Eiffel is currently to store the read character in the file object and provide a query `last_character' which returns the last read character.
The disadvantages are:
- bad performance (because the runtime stack or registers cannot be used to transport the results)
- blown up objects (each file has a
last_integer', last_natural', `last_string', etc.)
For these cases it would be good to have output arguments by keeping the distinction between commands and queries.
E.g. we could invent a mechanism which allowed us to write
with the effect of reading a character from `file' and store the result in the local variable (or attribute) `ch. This is common practice in many programming languages. However it contradicts the Eiffel principle that everything shall be as explicit and readable as possible. The reader of `file.read_character(ch) cannot see immediately whether `ch' is an input or an output argument. He would have to look into the definition of `read_character' to see that. Therefore some syntactic sugar is useful to make that distinction, e.g. the invocation of the command can be
and the feature can be declared as
In general the definition of a command could be
and its general use
- A function cannot have output arguments (only Result)
- Output arguments must be initialized properly
- Output arguments can occur in postconditions, but not in preconditions.
- strict command query separation
- leaner objects
- higher performance
- good expliciteness and readability
In your example
In your example
Do you have the value of ch stored in the object upon return? (In last_character for instance). If not, can't you obtain the same behavior with a function returning a TUPLE result containing all values o1, o2... ?
command query separation
A function returning a TUPLE breaks command query separation. If you do that, you can use the function within an assertion and then you have an assertion with side effects. This shall never happen.
This post would be stronger if you actually could have come up with a single example that last_character and such is slower. It isn't. Trust me.
Come up with a non-trivial piece of code and the Eiffel way is as fast as C if not faster.