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.