Subject: Re: bug#9776: case-lambda should accept zero clauses

From: Ian Price <[email-masked]>
Date: Sun, 08 Jan 2012 04:45:45 +0000

[email-masked] (Ludovic Courtès) writes:

> Hi Göran,
>
> Sorry for the delay.
>
> Göran Weinholt <[email-masked]> skribis:
>
>> the case-lambda form is specified in r6rs-lib as accepting any number of
>> clauses, including zero. So this should not give an error:
>
> My interpretation of the ‘case-lambda’ implementation on p. 15 of
> r6rs-lib.pdf is that ‘case-lambda-help’ raises an assertion violation
> when ‘case-lambda’ is called with zero clauses.
The case-lambda-help macro is expanded from within
(lambda args
  (let ((n (length args)))
    (case-lambda-help args n
      (fmls b1 b2 ...) ...)))

So, the full expansion is
(lambda args
  (let ((n (length args)))
    (assertion-violation #f "unexpected number of arguments")))

and thus a procedure that always returns an assertion violation.

>
> The text itself doesn’t explicitly mention that zero clauses are
> supported.
I would disagree with this. Even without looking at the implementation, you
see the specification of case-lambda as
  (case-lambda <case-lambda clause> ...)

The traditional meaning of ..., as seen in syntax-rules, and elsewhere
in the r6rs, is 0 or more. Therefore a (case-lambda) form seems allowed
to me.

Oh, and an existence proof for good measure :)

scheme@(guile−user)> (import (rnrs))
scheme@(guile−user)> (define-syntax case-lambda
                       (syntax-rules ()
                         ((_ (fmls b1 b2 ...))
                          (lambda fmls b1 b2 ...))
                         ((_ (fmls b1 b2 ...) ...)
                          (lambda args
                            (let ((n (length args)))
                              (case-lambda-help args n
                                                (fmls b1 b2 ...) ...))))))
scheme@(guile−user)> (define-syntax case-lambda-help
                       (syntax-rules ()
                         ((_ args n)
                          (assertion-violation #f
                                               "unexpected number of arguments"))
                         ((_ args n ((x ...) b1 b2 ...) more ...)
                          (if (= n (length ’(x ...)))
                              (apply (lambda (x ...) b1 b2 ...) args)
                              (case-lambda-help args n more ...)))
                         ((_ args n ((x1 x2 ... . r) b1 b2 ...) more ...)
                          (if (>= n (length ’(x1 x2 ...)))
                              (apply (lambda (x1 x2 ... . r) b1 b2 ...)
                                     args)
                              (case-lambda-help args n more ...)))
                         ((_ args n (r b1 b2 ...) more ...)
                          (apply (lambda r b1 b2 ...) args))))
scheme@(guile−user)> (case-lambda)
$22 = #<procedure 905a980 at <current input>:734:0 args>
scheme@(guile−user)> ($22)
ERROR: ERROR: R6RS exception:
  1. &assertion
  2. &message: "unexpected number of arguments"
  3. &irritants: ()

Entering a new prompt.  Type `,bt' for a backtrace or `,q' to continue.
scheme@(guile−user) [1]> ,q
scheme@(guile−user)> 

-- 
Ian Price

"Programming is like pinball. The reward for doing it well is
the opportunity to do it again" - from "The Wizardy Compiled"