Wart now supports a quick-n-dirty implementation of an infix scheme. Here's an excerpt from http://github.com/akkartik/wart#readme[1] with the details: wart> (3 + 1)
4
You don't need spaces around infix ops. wart> 3+1
4
Infix ops don't compromise homoiconicity; wart parses them into lisp forms so your macros don't have to worry about them: a+b
=> (+ a b)
Infix ops are always left-associative. a+b+c
=> (+ (+ a b) c)
Range comparisons are convenient as long as they return the last arg on success (because of left-associativity) and pass nils through: (a > b > c)
=> (> (> a b) c) ; watch out if b is nil!
(> nil x) ; should always return nil!
You can mix infix ops with regular prefix lisp: (a + (f b))
=> (+ a (f b))
(a + f.b)
=> (+ a (f b))
(fib n-1)
=> (fib (- n 1))
(f a + b c*d)
=> (f (+ a b) (* c d))
Operator precedence is not hardcoded. Instead, there is just one rule: operators surrounded by whitespace have lower precedence than operators that are not. (n * n-1)
=> (* n (- n 1))
You can create your own infix ops: def (<>) (a b) ; def <> (a b) would become <> def (a b)
(~iso a b)
wart> (1 <> 2)
1
To permit arbitrary infix ops, wart makes them distinct from regular symbols. Regular symbols can only contain letters, digits, and the characters ':', '?', '!' and '_'. Infix ops can only contain other characters. Thus, the sets of 'infix chars' and 'symbol chars' are disjoint. This implies that wart won't let you define some traditional lisp names that you might be used to: *global* ; I would just say Global
=> error
uppercase-char-p
=> (- uppercase (- char p)) ; probably not what you want
(char> a "p")
=> ((> char a) p) ; probably not what you want
To create multi-word symbols, use underscores or camelCase. I'm trying out capitalizing globals.While regular symbols can't be used in infix mode, infix ops can be used like regular symbols. (+ a b)
=> (+ a b)
To use an infix op in a higher-level function, wrap it in parens: (map ++ '(1 2 3))
=> Error: map is not a number
(map (++) '(1 2 3)) ; hello haskell!
=> (2 3 4)
Infix operators can coexist with paren-insertion: a +
b+c * d
=> (+ a (* (+ b c) d))
However, if your infix expressions need multiple lines, ask if they're worth
doing in infix. The following is actually harder to read in infix: (* some_function.some_argument
(+ some_other_function.some_other_argument
some_random_constant))
I prefer to use infix only for simple expressions with short variable names. And I never use infix in macro expansions. After all, macros are the whole
reason we have s-expressions.--- Comments, questions, criticisms? I'm wary that the interpreter is getting more complex, so this might be temporary. One open question: Can we represent some ssyntax in infix? ':' and '&' in particular seem like they should become infix operators, but there might be weird interactions with precedence. A more immediate issue is that I would lose keyword symbols like :a. I'm unsure whether it's a good idea to use infix for assignment; prefix seems to make mutations more salient. I'm also keeping equality checking in prefix because I love the name iso so much :) [1] http://github.com/akkartik/wart/tree/79476f0d230d1c5eb6b20ebc116507e0a12785de#readme to be precise. |