Arc Forumnew | comments | leaders | submitlogin
Weak reduce
5 points by simonb 6172 days ago | 4 comments
I appreciate the elegant definition of reduce but it is also somewhat limiting as it forces all the boundary handling (<2 elements) into the combining function.

(Or am I missing something?)



3 points by parenthesis 6172 days ago | link

The current reduce is fine if the given function can take 0,1 or 2 arguments. E.g.

  (reduce + ()) -> 0
  (reduce + '(1)) -> 1
But if you were using, e.g.

  (def add (x y)
    (+ x y))
then the above cases wouldn't work.

But if reduce is redefined thus:

  (def reduce (f xs)
    (if (cddr xs) (reduce f
                          (cons (f (car xs) (cadr xs))
                                (cddr xs)))
        (cdr xs) (apply f xs)
        xs (car xs)
        nil))
Then

  (reduce add ()) -> nil
  (reduce add '(1)) -> 1

-----

4 points by simonb 6172 days ago | link

A somewhat messy attempt at mimicking CL's reduce:

  (let init-default (uniq)      
    (def reduce (f xs (o init init-default))
      ((afn (xs) 
         (if (cddr xs) (self (cons (f (car xs) (cadr xs)) (cddr xs)))
             (cdr xs) (apply f xs)
             xs (car xs)
             (f)))
       (if (is init init-default) xs (cons init xs)))))
For reference:

"In the normal case, the result of reduce is the combined result of function's being applied to successive pairs of elements of sequence. If the subsequence contains exactly one element and no initial-value is given, then that element is returned and function is not called. If the subsequence is empty and an initial-value is given, then the initial-value is returned and function is not called. If the subsequence is empty and no initial-value is given, then the function is called with zero arguments, and reduce returns whatever function does. This is the only case where the function is called with other than two arguments."

http://www.lispworks.com/documentation/HyperSpec/Body/f_redu...

-----

1 point by icemaze 6172 days ago | link

True, but sometimes you want some particular value for those special cases. In case of a sum (reduce add ()) should return 0, which is the (mathematically) "right" result.

Is there a way to know the arity of a function?

-----

1 point by parenthesis 6172 days ago | link

Yes, I suppose the real solution is an optional initial value argument (as in CL reduce)), thus you can provide an appropriate identity value (e.g. 0 in the case of add).

Edit: as simonb has simultaneously given.

-----