[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: proposing a simpler mechanism

This page is part of the web mail archives of SRFI 102 from before July 7th, 2015. The new archives for SRFI 102 contain all messages, not just those from before July 7th, 2015.

> > 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])
        [(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])
        [(= bitmask 0)
         (display "#b0...0")
         (display (make-string minbits #\0))]
        [(= bitmask -1)
         (display "#b1...1")
         (display (make-string minbits #\1))]
         (f (bitwise-arithmetic-shift-right bitmask 1)
            (max (- minbits 1) 0))
         (write-char (if (bitwise-bit-set? bitmask 0) #\1 #\0))]))))

(print-bitmask 3)
> (print-bitmask -3)