[comp.lang.eiffel] Initialising data structures

rick@tetrauk.UUCP (Rick Jones) (10/29/90)

Something I am finding rather cumbersome in Eiffel code is creating initialised
complex objects.  I am interested in other opinions on this problem;  please
bear with the following while I explain what I mean ...

As an example, I need to create an ARRAY of STRINGS where the
strings themselves are literal values  The code goes something like:

	...
	local
		string_list: ARRAY[STRING] ;
	do
		string_list.Create (1,5) ;
		string_list.put (1, "first") ;
		string_list.put (2, "second") ;
		string_list.put (3, "third") ;
		string_list.put (4, "fourth") ;
		string_list.put (5, "fifth") ;

		object.routine (string_list) ;
	...

The ultimate purpose is simply to invoke "routine" on "object" with some
arbitrary number of strings.

If the array contains not strings but other objects it gets even more clumsy,
since each item has to be created individually, e.g:

	...
	local
		thing_list: ARRAY[THING] ;
		thing: THING ;
	do
		thing_list.Create (1,5) ;
		thing.Create ("first") ; thing_list.put (1, thing) ;
		thing.Create ("second") ; thing_list.put (2, thing) ;
		thing.Create ("third") ; thing_list.put (3, thing) ;
		thing.Create ("fourth") ; thing_list.put (4, thing) ;
		thing.Create ("fifth") ; thing_list.put (5, thing) ;

		object.routine (thing_list) ;
	...

Some of my classes, especially inherited ones, end up containing little more
than the sort of code above.  The deferred classes do all the work, the
implemented classes are differentiated by the lists of objects they define to
be operated on (this is as succinct a precis as I can manage without going into
long boring details of the design).

Due to the repetitive nature of this sort of stuff, I have in fact written some
shell-scripts to generate chunks of Eiffel code (ouch!).  Given a skeleton, any
required version of the above block of code can be generated simply by knowing
how many strings there are and their names;  i.e. in the above example, all I
really need to know is the 5 strings "first", "second", "third", "fourth", &
"fifth".

There seems to be something at odds here with the notion of powerful code
re-use.  I am having to duplicate lumps of virtually the same code simply to do
things in an object-oriented way, a concept which is supposed to avoid the need
for duplicating code!

In C (I will refrain from ++ :-), static initialised structures can easily be
declared, e.g:

char *names[] = {"first", "second", "third", "fourth", "fifth", 0};

but since Eiffel has no notion of static data, it seems difficult to incoporate
this sort of declaration into the language structure.


I have heard some mention of syntactic extensions to Eiffel for version 3 which
would affect Create routines, and also an idea for variable argument lists.
Either of these could solve this sort of problem if done in the right way.
E.g. the first example could simply become:

	object.routine ("first", "second", "third", "fourth", "fifth") ;

(Obviously "object.routine" would need recoding - I am not suggesting that such
a variable list should be interchangeable with an array)

Various possibilities suggest themselves for the second example:

a.	THING_LIST could be a class which inherits from ARRAY[THING], and whose
	Create routine takes variable arguments -

	...
	local
		thing_list: THING_LIST ;
	do
		thing_list.Create ("first", "second", "third", "fourth", "fifth") ;
		object.routine (thing_list) ;
	...

	One essential requirement for this solution is that the called routine
	must be able to find the actual number of arguments BEFORE traversing
	them in order to create the array with the proper size.

b.	If the notion of a "new" operator applied to a class-name is supported,
	we could have something like:

	object.routine (new THING_LIST ("first"),
			new THING_LIST ("second"),
			new THING_LIST ("third"),
			new THING_LIST ("fourth"),
			new THING_LIST ("fifth")) ;

	I make no claims as to the viability of the syntax, just a suggestion
	of semantics.


I would be interested to know:

a.	Have any other Eiffel users encountered this sort of problem?

b.	Has anyone got any more elegant techniques using the current language?

c.	Do ISE (or should it now be NICE?) have any long-term plans for the
	language which would offer an improvement - either similar to the ideas
	above or otherwise?

-- 
Rick Jones
Tetra Ltd.  Maidenhead, Berks, UK
rick@tetrauk.uucp	Absence of .signature is not .signature of absence

bertrand@eiffel.UUCP (Bertrand Meyer) (10/31/90)

A very simple extension will be present in version 3 and should
address the problem pointed out by Rick Jones. The Kernel Library
will contain a class TUPLE [T] describing finite sequences of objects
of type T, with arbitrary length. (This also addresses cases in which
a routine needs an argument list of variable size.)

This class is straightforward and its interface similar to
that of LIST, LINKED_LIST etc. It can in fact be written
in the current language. The only syntactic extension
is support for manifest constants of tuple type:

	<a, b, c, d, e>

giving TUPLE a status similar to that of STRING (``normal''
class, but with special syntax for manifest constants).

Classes such as ARRAY will have procedures for initializing
from a tuple, e.g.

	a.load (<a, b, c, d, e>, 3)

where the second argument is the starting position. 


A note on initialization in the current state of the language/environment:
in many cases it is useful to rely on the persistence facilities
to avoid re-executing initialization code. In the example quoted
by Mr. Jones, one may consider having two systems: an initialization system
that creates the data structures and ends its execution with

	x.store (f)

and the ``real system'' which begins by loading the initialized data
structures by executing

	x.retrieve (f)

instead of the actual initialization code.

As a final comment, it would be inappropriate to have C-like
static initialization in an object-oriented context. Initializing
with literal values (integers, strings, ...) is only one possible case;
in general one wants to initialize with arbitrary objects. However, as
Mr. Jones points out, the simple case of literal values is currently not
very elegantly handled. The tuple facility, combined with the
facilities for storing and retrieving persistent objects, should
remove this problem.
-- 
-- Bertrand Meyer
bertrand@eiffel.com

yost@DPW.COM (David A. Yost) (11/02/90)

In article <437@eiffel.UUCP> bertrand@eiffel.UUCP (Bertrand Meyer) writes:
>As a final comment, it would be inappropriate to have C-like
>static initialization in an object-oriented context.  [because?] Initializing
>with literal values (integers, strings, ...) is only one possible case;
>in general one wants to initialize with arbitrary objects.

>The tuple facility, combined with the facilities for storing and retrieving
>persistent objects, should remove this problem.

I see two issues here:

1.  Syntax for instantiating unnamed complex objects

Emphasis on 'unnamed', not 'constant'.  Clearly it is
good to have syntax that can express unnamed constants.
It would be a pain to have to declare a temporary
variable and execute some run-time code every time you
wanted to use a number or string in the code.  The same
is true for more complex objects, and it's not really a
matter of whether they are made up of constants or not.
It's a nice thing to be able to instantiate an unnamed
object on the fly just as one does with numbers and
strings.  It appears that the new tuple mechanism only
helps for things like lists and arrays.

(C isn't a very potent straw man for your argument.
After all, in C you can only express unnamed complex
objects in initializations, not at arbitrary points
in the code, and all the elements must be constants.
Other languages do very well with unnamed complex
objects.)

2. Run-time code vs. compile-time data statements

In Eiffel, most kinds of initialization must be
expressed as run-time code.  This is nice as a
language simplification.  (Why have two ways of
expressing how to store data somewhere when you can
have just one?)  The only problem I see here is that
the compiler is not yet smart enough to optimize out
constant-initialization code and generate appropriate
compile-time data initialization statements.

I hope some day Eiffel compilers will do that.

 --dave yost
   yost@dpw.com or uunet!esquire!yost
   Please don't use other mangled forms you may see
   in the From, Reply-To, or CC fields above.