Arc Forumnew | comments | leaders | submitlogin
2 points by rocketnia 5186 days ago | link | parent

If the behavior were in a different utility named 'v+ or something, you wouldn't have a "two libraries extending the same case" conflict (just a "two libraries defining the same variable" one :-p ), and you'd also be able to have (v+ '(1 0 0) '(0 1 0)) be '(1 1 0) without conflicting with Arc's existing result of '(1 0 0 0 1 0).

Using 'extend generally also has the drawback that existing code that expects to get an error from something like (+ 1 '(1 2 3)) won't get that error anymore. This is less of a problem when using a tagged type that people are very unlikely to be using already, but numbers and lists are especially common.

For fun, here's an implementation. ^_^

  (def v+ (first . rest)
    (iflet (second . rest) rest
      (apply v+ (v+binary first second) rest)
      first))
  
  (def v+binary (a b)
    (err:+ "Can't " (tostring:write `(v+ ,a ,b))))
  
  (extend v+binary (a b) (and number.a number.b)
    (+ a b))
  
  (extend v+binary (n xs) (and number.n alist.xs)
    (map [v+ n _] xs))
  
  (extend v+binary (xs n) (and alist.xs number.n)
    (map [v+ _ n] xs))
  
  (extend v+binary (xs ys) (and alist.xs alist.ys
                             (is len.xs len.ys))
    (map v+ xs ys))
  
  (extend v+binary (xs ys) (and single.xs alist.ys (~single ys))
    (v+ car.xs ys))
  
  (extend v+binary (xs ys) (and alist.xs (~single xs) single.ys)
    (v+ xs car.ys))

  arc> (v+ '((1 0) (0 1)) '((2 0) (0 2)))
  ((3 0) (0 3))
  arc> (v+ 1 2 '(10 20) '(100 200) '(20) 1)
  (134 244)