tré on Github.
And yes, back then in 2008 it really took the edge off. Now with Internet Explorer as good as toast and HTML5, CSS3 and ES6 in all browsers things are closing in on how they should have been from the start. Still, PHP is a serious pain in the butt and as most people run their sites on some Linux/Apache/MySQL/PHP server, tré is still the remedy you might be looking for. However: tré brings you the power of Lisp metaprogramming.
Common Lisp is the highest low‐level language available and using it as is you'll inevitably end up with lots of parens. That's not only tedious but also downright ugly. tré is cutting them down by introducing a dot notation for accessing list elements:
; Get first element of list x: (car x) ; any lisp x. ; tré ; Get rest of elements of list x: (cdr x) ; any lisp .x ; tré ; Get second element of list x: (cadr x) ; any lisp .x. ; tré
You wouldn't believe how much better things get with this already. So let's take a regular piece of Common Lisp code:
; Return last list cell. (defun last (x) (cond ((cdr x) (last (cdr x))) x))
…and we're not wondering why the kids turn away in disgust. It's certainly a pleasure when building abstraction layers on top of it. Here's a version in tré:
; Return last list cell. (fn last (x) (? .x (last .x) x))
This every programmer worth her salt understands. No ringing in the ears. As you can see tré moves away from traditional identifiers and uses idioms better known from other languages.
The dot is also an alternative for CONS.
; Make a list cell. (cons 1 2) ; any lisp (. 1 2) ; tré
No LAMBDA keyword
Although not necessary, most Lisps want you to introduce anonymous functions with the LAMBDA form. You can use it with tré or just leave it off.
; Create anonymous function that returns its argument. #'(lambda (x) x) ; Old version #'((x) x) ; tré
There's another way to make anonymous functions with single arguments since they're used quite often: with brackets.
#'(lambda (_) (+ _ 1)) [+ 1 _]
tré will enforce the contents of brackets to be a list of statements. If you want to use an atom you'll have to use IDENTITY (which just returns its argument):
[t] becomes #'((_) (t)) ; Ouch! [identity t] becomes #'((_) (identity t))