rick@tetrauk.UUCP (Rick Jones) (11/17/90)
Following my recent posting about variable argument problems, and Bertrand Meyer's response concerning TUPLEs to be introduced in version 3, I decided to reconsider the problem (I can't defer the whole problem until V3 is released!). I also looked again at some prototype class code I was sent some time ago by ISE which tried to address the problem of formatted print. The result is a class VLIST which allows variable size lists to be effectively coded "in-line". The code for VLIST is given below, its usage is best explained by first giving an example: class EXP -- experiments on building string lists inherit STD_FILES feature Create is local vl: VLIST[STRING] ; -- a variable list do vl.Create ; lprint (vl -- VLIST is filled as part of the call .v ("This") -- to lprint .v ("is") .v ("a") .v ("sentence") ) ; end ; lprint (l: LIST[STRING]) is -- prints all the strings in the list do from l.start until l.offright loop putstring (l.item) ; putchar (' ') ; l.forth ; end ; new_line ; end ; end When run, this will print "This is a sentence". VLIST inherits from LINKED_LIST and exports a single feature "v" whose argument is an object of the type which it contains. The return value is the object itself. This allows indefinite cascading of calls to feature "v". This is what is shown in the Create routine above, and since the return value of the complete chain of calls is the list itself, this can be passed directly as a LIST argument to the required routine. The cascading calls are coded on multiple lines, since this separates the items clearly. A more conventional format would be: lprint (vl.v("This").v("is").v("a").v("sentence")) ; The VLIST class is as follows: ---------------------------------------------------------------------- class VLIST [T] -- variable-argument list export v inherit LINKED_LIST [T] feature v (t: T): like Current is require new: offright ; do put_left (t) ; Result := Current ; ensure inserted: t = last ; grown: count = old count + 1 ; end ; end ---------------------------------------------------------------------- A similar class can be based on FIXED_LIST, which has the advantage that the resulting object conforms to both LIST and ARRAY: ---------------------------------------------------------------------- class VALIST [T] -- variable-argument list using FIXED_LIST export v inherit FIXED_LIST [T] rename Create as f_create feature Create is do f_create (0) ; end ; v (t: T): like Current is local up: INTEGER ; do -- must cater for an empty list when upper < lower -- (this only arises because an empty array is always -- initialised with lower=0 and upper=-1. If it were done -- so that lower=minindex and upper=lower-1 it would be -- more consistent and avoid this extra check) -- if upper > 0 then up := upper end ; -- else default value = 0 ; force (t, up + 1) ; Result := Current ; ensure inserted: t = last ; grown: count = old count + 1 ; end ; end ---------------------------------------------------------------------- Although this breaks a rule of the Eiffel philosophy - "A function which returns a value should not have side effects", it clearly provides extremely useful functionality. I hope this may prove useful to other Eiffel users who have experienced similar problems. Since the resulting C code is a nest of function calls, too many arguments can cause compiler overflow. My compiler (SCO Unix V/386, which is more limited than many) can manage up to 14 string arguments before it gives up. To change the subject, I recently posted an article on exception handling, with the code of a class which allowed an object to be passed from an exception to the rescue clause which traps it. However, my system's comms link was in a mess that night and several things disappeared into a black hole! Could someone email me if they have seen this article? If nobody did I shall re-post it. Thanks. -- Rick Jones Tetra Ltd. Maidenhead, Berks, UK rick@tetrauk.uucp Absence of .signature is not .signature of absence