It's very reminiscent ... also of using little dots, as in "4·x·y".
Wow, I missed that. XD I was mainly thinking of juxtaposition.
The only possible problem I can think of is difficulty of (efficient) implementation.
Yeah, certainly an issue. Optimized code can use (* 4 a c) like usual though.
Other thing
Custom types should already use 'annotate when they need custom 'defcall behavior, right? For instance, if ax^2+bx+c is built using (annotate 'poly (list a b c)), you can index it using rep._.i and call it using _.i. If you're talking about having polynomial calls do polynomial multiplication instead when they're called, then you may have a design conflict (although I think the cases are mostly distinguishable here).
Anyway, as you sorta suggest, the multiplication of diverse things is still a bit weird in general. The concern I have in mind is that multiple dispatch rears its head. I think I'd end up doing something like this (untested!):
; Extend numbers so that they use '* as their call behavior.
(mac defmulttype type
`(defcall ,type form (apply * form)))
defmulttype.int
defmulttype.num
; Define another variable bound to '* so we won't lose track of it
; when we redefine it.
(= *-base *)
; Define an extensible binary version of '*. This part's rudimentary
; for laziness's sake.
(def *-binary (a b)
(err:+ "Can't multiply " a " by " b "."))
(def fn-defmult (test-a test-b body)
(zap testify test-a)
(zap testify test-b)
(let old-*-binary *-binary
(= *-binary (fn (a b)
(if (and do.test-a.a do.test-b.b)
(do.body a b)
(do.old-*-binary a b))))))
(mac defmult (test-a test-b . body)
`(fn-defmult ,test-a ,test-b (fn (a b) ,@body)))
; Define '* in terms of '*-binary. It's left-associative.
(def * args
(case args nil 1
(reduce *-binary args)))
; Make multiplication with a nonnegative integer on the left use '+.
(defmult [and (isa _ 'int) (<= 0 _)] [do t]
(apply + (n-of a b)))
; Provide the multiplication cases that used to be built in,
; overriding the integer rule in the process.
(defmult number number
(*-base a b))
This gives just enough multiple dispatch for people to put (defmult [isa _ 'poly] [isa _ 'int] ...) in one library and (defmult [isa _ 'poly] [isa _ 'snargle] ...) in another one, and they can use (defmult 'poly [do t] ...) if they only need single dispatch.
I'd also give an actual example of using polynomials, but I'm out of time. :-p It would have just been an exploration of having (defmult [isa _ 'poly] isa-poly-arg ...) and (defmult [isa _ 'poly] [isa _ 'poly] ...) be separate cases.