proposing a simpler mechanism R. Kent Dybvig (13 Nov 2009 03:00 UTC)
Re: proposing a simpler mechanism Thomas Bushnell BSG (13 Nov 2009 04:23 UTC)
Re: proposing a simpler mechanism Taylor R Campbell (13 Nov 2009 04:31 UTC)
Re: proposing a simpler mechanism R. Kent Dybvig (13 Nov 2009 16:22 UTC)
Re: proposing a simpler mechanism Per Bothner (13 Nov 2009 16:56 UTC)
Re: proposing a simpler mechanism Thomas Bushnell BSG (13 Nov 2009 04:54 UTC)
Re: proposing a simpler mechanism Alex Queiroz (13 Nov 2009 13:44 UTC)
Re: proposing a simpler mechanism Marc Feeley (13 Nov 2009 14:24 UTC)
Re: proposing a simpler mechanism Thomas Bushnell BSG (13 Nov 2009 18:39 UTC)
Re: proposing a simpler mechanism Thomas Bushnell BSG (13 Nov 2009 18:36 UTC)
Re: proposing a simpler mechanism Alex Queiroz (13 Nov 2009 19:08 UTC)
Re: proposing a simpler mechanism Thomas Bushnell BSG (13 Nov 2009 19:21 UTC)
Re: proposing a simpler mechanism David Van Horn (13 Nov 2009 19:25 UTC)
Re: proposing a simpler mechanism Thomas Bushnell BSG (13 Nov 2009 19:36 UTC)
Re: proposing a simpler mechanism David Van Horn (13 Nov 2009 19:58 UTC)
Re: proposing a simpler mechanism Arthur A. Gleckler (13 Nov 2009 20:25 UTC)
Re: proposing a simpler mechanism David Van Horn (12 Jan 2010 18:51 UTC)

Re: proposing a simpler mechanism R. Kent Dybvig 13 Nov 2009 16:22 UTC

> > What do you expect procedure-arity to return for a procedure which
> > accepts any number of arguments?  IEEE +inf?

> -1, presumably.  The numerical value isn't significant; its
> representation as a bit string in two's-complement is what matters,
> and for -1 that is a bit string of all ones.

Right.  In effect, a two's complement number has an infinite number of
sign bits.  For negative numbers, the sign bits are all one (set), which
allows procedure-arity to represent the arity of a procedure that accepts
n or more arguments, for any n.

Here are some examples:

bitmask   two's complement    proc accepts:

0         #b0...00000         nothing, i.e., it raises raises an exception
                              no matter how many arguments it receives
1         #b0...00001         zero arguments
2         #b0...00010         one argument
4         #b0...00100         two arguments
6         #b0...00110         one or two arguments
5         #b0...00101         zero or two arguments

-1        #b1...11111         any number of arguments
-2        #b1...11110         one or more arguments
-4        #b1...11100         two or more arguments
-3        #b1...11101         zero or two or more arguments
                              (but not one argument)

Here's a procedure an implementation might use to compute a bitmask for a
single formal parameter list represented in the obvious way.

(define formals->bitmask
  (lambda (fmls)
    (let loop ([fmls fmls] [n 0])
      (cond
        [(null? fmls) (bitwise-arithmetic-shift-left 1 n)]
        [(symbol? fmls) (bitwise-arithmetic-shift-left -1 n)]
        [else (loop (cdr fmls) (+ n 1))]))))

(formals->bitmask '()) ;=> 1
(formals->bitmask '(a b)) ;=> 4
(formals->bitmask 'r) ;=> -1
(formals->bitmask '(a b . r)) ;=> -4

Here's another procedure that computes an aggregate bitmask for a list of
formal parameter lists, as for a case-lambda expression.

(define formals*->bitmask
  (lambda (fmls*)
    (apply bitwise-ior (map formals->bitmask fmls*))))

(formals*->bitmask '()) ;=> 0
(formals*->bitmask '((a) (a b))) ;=> 6
(formals*->bitmask '(() (a b . r))) ;=> -3

And for your bitmask-visualization pleasure:

(define print-bitmask
  (lambda (bitmask)
    (let f ([bitmask bitmask] [minbits 4])
      (cond
        [(= bitmask 0)
         (display "#b0...0")
         (display (make-string minbits #\0))]
        [(= bitmask -1)
         (display "#b1...1")
         (display (make-string minbits #\1))]
        [else
         (f (bitwise-arithmetic-shift-right bitmask 1)
            (max (- minbits 1) 0))
         (write-char (if (bitwise-bit-set? bitmask 0) #\1 #\0))]))))

(print-bitmask 3)
#b0...00011
> (print-bitmask -3)
#b1...11101