Path: utzoo!utgpu!water!watmath!clyde!att!osu-cis!tut.cis.ohio-state.edu!rutgers!cmcl2!yale!Krulwich-Bruce From: Krulwich-Bruce@cs.yale.edu (Bruce Krulwich) Newsgroups: comp.lang.scheme Subject: Re: case-lambda syntax in Chez Scheme Message-ID: <40661@yale-celray.yale.UUCP> Date: 19 Oct 88 01:45:01 GMT References: <16934@shemp.CS.UCLA.EDU> Sender: root@yale.UUCP Reply-To: Krulwich-Bruce@cs.yale.edu (Bruce Krulwich) Distribution: na Organization: Computer Science, Yale University, New Haven, CT 06520-2158 Lines: 63 In-reply-to: pierce@lanai.cs.ucla.edu In article <16934@shemp.CS.UCLA.EDU>, pierce@lanai writes: >Some good person replied to my example in Re: Limitation with Lambda. >This person pointed out that the "case-lambda" syntax is not standard >Scheme. My apologies, case-lambda is from Chez Scheme Version 2.0, >and I have found it so useful (I use it a *lot*) that I just forgot >that users of other Scheme systems might not know what it meant. ... > Procedures with a variable number of arguments could only be defined > in earlier versions using the "lambda dot" interface, which requires > allocation of a list to hold all but the required parameters. > Version 2.0 supports a variant of "lambda", called "case-lambda", > that allows procedures with variable numbers of arguments to be > defined efficiently. "case-lambda" has the form: > > (case-lambda [idspec-a exp1-a exp2-a ...] > [idspec-b exp1-b exp2-b ...] ...) > > where the idspecs are normal "lambda" parameter lists. The following is an implementation of CASE-LAMBDA in T. The only things that it uses that may not be standard are the use of a () argument as an ignored argument and the function INTS-TO-N which must return a list of any N items. (define-syntax (case-lambda . lambda-specs) (let* ((min-len (apply min (map (lambda (spec) (length (car spec))) lambda-specs))) (const-args (map (lambda (()) (generate-symbol 'arg)) (ints-to-n min-len))) (rest-arg (generate-symbol 'rest)) (len-var (generate-symbol 'length)) ) `(lambda (,@const-args . ,rest-arg) (let ((,len-var (length ,rest-arg))) (cond ,@(map (lambda (spec) `((eq? ,len-var ,(fx- (length (car spec)) min-len)) (apply (lambda ,(car spec) ,@(cdr spec)) ,@const-args ,rest-arg))) lambda-specs) (else (error "Wrong number of args to a CASE-LAMBDA")) ))) )) This implementation is efficient in the sense that it will cause the smallest possible rest-arg to be CONSed for every procedure, but it would obviously more efficient to do this as a low-level construct (as I think is done in Chez-Scheme) so that no rest-arg would be CONSed. My question, though, is just how useful this construct is. It seems to me that most of the uses of procedures with variable arguments is for the first few of them (the constant ones) to have the same use regardless of the optional (rest) arg's, and for the main block of code of the procedure to be the same once the optional values are decoded and defaults are set if necessary. The CASE-LAMBDA construct specifies completely disjoint blocks of code for each of the argument configurations. It seems awkward. Can someone who has used CASE-LAMBDA and likes it post or send to me examples of its use (presumably examples that show it being used beneficially)?? Bruce Krulwich