You may want to consider something non-traditional in Lisp circles: infix functions. Let me elaborate (and use the proposed new angle bracket syntax).
The "f:g" syntax is a nice idea for function composition, as is "~f" for negation, but the current syntax and semantics seem like a hack. What if we could do this instead:
(def f (x y) ...)
(infix f left)
<x f y> ; The compiler would transform this to (f x y)
<x f y f z> ; And this to (f (f x y) z) (evaluate from the left)
(infix f right)
<x f y f z> ; And now to (f x (f y z)) (evaluate from the right)
; Use in "normal" syntax:
(= foo <x f y>) ; --> (= foo (f x y))
; So, we could do this:
(infix + right)
(= foo <1 + 2>) ; Would evaluate/transform to (= foo (+ 1 2))
(= foo (+ 1 2 3 4)) ; And we could still use the ordinary function call syntax.
; Or maybe even:
(infix + associative)
(= foo <1 + 2 + 3 + 4>) ; Transforms to (+ 1 2 3 4) if the function is n-ary, or
; some arbitrary evaluation order if not.
; And now for the interesting bit.
(def : (f g) (fn (x) (f (g x)))))
(infix : right)
(map <f : g> list) ; What currently is (map f:g list)
; Why not extend the idea?
(def ~ (f) (fn (x) (not (f x))))
(unary ~)
(if (<~ predicate> arg) ...)
; No, that doesn't have any benefit over ((~ predicate) arg).
Problems:
- How do you define precedence levels? Once you are in this swamp, you can't get out. Maybe all infix functions would have the same precedence to side-step the issue.
- Is it possible to do with only the < > notation? But how would you parse the following without the additional information that + is infix?
<+ + + + +>
- Is it worth the two more characters and whitespace?
Precendence levels and such are a known problem and have a known solution. There are rather easy algorithms out there that deal with this. The only problem is that because you lack typing, you could end up with things that are not parsable: