[comp.lang.eiffel] Variable arguments

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