Barak.Pearlmutter@F.GP.CS.CMU.EDU (12/06/89)
In Oaklisp, Kevin and I used a somewhat ideosyncratic solution to the rest args problem. A form like (lambda (a b . c) BODY) makes a procedure of at least two arguments, and BODY can refer to the first two, A and B. But the token C is not a variable; it is special syntax indicating that an indeterminite number of rest arguments are being passed. Since it is just syntax, it can't be closed over. It can be used in only one context: in a tail recursive call that gets you out of BODY, you must terminate the call with ". C". And all exits from body must be tail recursive, and must do this. For instance, you could write (define (foo a b . c) (list a 'aye b 'bee . c)) There is a way to find out how many extra arguments were passed, as in the following form. REST-LENGTH is syntax though, not a procedure. I'm still not sure if this was a good idea, although it is simple enough to provide. (define (foo a b . c) (if (> (rest-length c) 5) (list 'lots 'of . c) (list 'little . c))) A number of utility functions are provided for manipulating the rest arguments. For instance, LISTIFY-ARGS takes at least one argument, a procedure, which it calls on a list made up of any additional arguments. So to write a function which takes an arbitrary number of arguments and returns its second, you could write (define (second-arg a x . rest) (listify-args (lambda (l) x) . rest)) Other functions useful for rest argument consumption are also provided. We felt that this mechanism provided the bare minimum of functionality necessary in the base level language to work with rest arguments, without imposing undue implementation constraints. In using it, we found that almost all uses of rest arguments fit naturally into the paradigm, and very rarely is there any reason to listify the rest arguments. In particular, this is true of things like + and * which can basically eat there arguments left to right until they're all gone. [ In passing, I should mention that the compatibility package makes dotted rest args behave in the usual ugly but standard way. ]
gateley@m2.csc.ti.com (John Gateley) (12/07/89)
In article <Tue.Dec.5.18:48:04.1989.bap@F.GP.CS.CMU.EDU> Barak.Pearlmutter@F.GP.CS.CMU.EDU writes: >In Oaklisp, Kevin and I used a somewhat ideosyncratic solution to the >rest args problem. A form like (lambda (a b . c) BODY) makes a >procedure of at least two arguments, and BODY can refer to the first >two, A and B. But the token C is not a variable; it is special syntax >indicating that an indeterminite number of rest arguments are being >passed. ... I am strongly opposed to this approach because it introduces a second-class data type into Scheme. The rest-arg object, which you can think of as being bound to 'c' above, has several restrictions on its use. The philosophy of Scheme is that everything is first class. If you were talking about CL on the other hand, where they care about efficiency more, then the above seems reasonable. John gateley@m2.csc.ti.com