[comp.lang.scheme] case-lambda syntax in Chez Scheme

pierce@lanai.cs.ucla.edu (10/19/88)

-
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.

An excerpt from the Chez Scheme Version 2.0 release notes follows.  It's
a simple idea that not only makes code easier to write and to understand,
but it also runs faster than the old way.  Maybe Kent Dybvig could
be encouraged to post a little more info about case-lambda?

-- Brad Pierce

------------------------------------------------------------------------
(below Copyright Kent Dybvig)

Optional Arguments

    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.   In essence, 
    each  bracketted item (parens may be used in place of the  brackets) 
    represents  a different "lambda" expression;  which one is evaluated 
    depends upon the number of arguments.  If the number of arguments is 
    a correct number for the first idspec,  evaluation proceeds with the 
    first body within the bindings implied by the first idspec.  If not, 
    then  if the number of arguments is a correct number for the  second 
    idspec, evaluation proceeds with the second body, etc.

Krulwich-Bruce@cs.yale.edu (Bruce Krulwich) (10/19/88)

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