A little experiment in reducing verbosity in Common Lisp, inspired by BODOL (https://github.com/bodil/BODOL - no affiliation).
To try it out in your REPL you can use (ql:quickload :glyphs) if you have added to your ASDF load path in local projects.
Update: Now that it's in quicklisp, simply:
(ql:quickload :glyphs)
glyphs:
(ƒ factorial
0 → 1
α → (* α (factorial (1- α))))
vs.:
(defun factorial (x)
(cond ((equal x 0) 1)
(x (* x (factorial (1- x))))))
result:
(factorial 8)
40320
(ƒ factorial
0 → 1
(and (numberp α) (> α 0)) → (* α (factorial (1- α)))
α → (error "Non-numbers (or negatives) don't work real well with factorials!"))
vs.:
(defun factorial (x)
(cond ((equal x 0) 1)
((and (numberp x) (> x 0)) (* x (factorial (1- x))))
(t (error "Non-numbers (or negatives) don't work real well with factorials!"))))
(ƒ→ factorial (integer → integer)
0 → 1
α → (* α (factorial (1- α))))
glyphs:
(ƒ reverse*
(cdr α) → (append (reverse* (cdr α)) `(,(car α)))
α → α)
glyphs:
(mapcar (λ "cat" → (print "Cats rock")
"dog" → (print "Dogs do too!")) '("cat" "dog" "mouse"))
vs.:
(mapcar (lambda (x)
(cond ((equal x "cat") (print "Cats rock"))
((equal x "dog") (print "Dogs do too!")) '("cat" "dog" "mouse"))))
result:
"Cats rock"
"Dogs do too!"
NIL
glyphs:
(ƒ double-odds-half-evens
(oddp α) → (* x 2)
(evenp α) → (/ x 2))
vs.:
(defun double-odds-half-evens (x)
(cond ((oddp x) (* x 2))
((evenp x) (/ x 2))))
result:
(double-odds-half-evens 4)
2
(double-odds-half-evens 3)
6
You can use multiple values by prefixing a variable in the statement portion of the code with either a 'α' or an '?'.
glyphs:
(mapcar (λ α → (+ α αb αc)) '(1 2 3) '(4 5 6) '(7 8 9))
vs.:
(mapcar (lambda (a b c) (+ a b c)) '(1 2 3) '(4 5 6) '(7 8 9))
result:
(12 15 18)
Make sure to use the readtable that comes with it first:
(in-readtable glyphs:syntax)
Or these little readtable shortcuts will not work.
glyphs:
(ƒ any-cats?
~"cat"~ → (print "yes!"))
vs.:
(defun any-cats? (x)
(when (cl-ppcre:scan "cat" x)
(print "yes!")))
result:
(any-cats? "I see some cats")
"yes!"
glyphs:
(ƒ no-cats
~"(were|cat)"~ → |"dog"|)
vs.:
(defun no-cats (x)
(let ((regex "(were|cat)"))
(when (cl-ppcre:scan regex x)
(cl-ppcre:regex-replace-all regex x "dog"))))
result:
(no-cats "there were dogs and there were cats")
"there dog dogs and there dog dogs"
Add to `.emacs'
;; Keybindings for glyphs
(global-set-key (kbd "M-l") (lambda () (interactive) (insert "\u03bb"))) ; λ lambda
(global-set-key (kbd "M-f") (lambda () (interactive) (insert "\u0192"))) ; ƒ function
(global-set-key (kbd "M--") (lambda () (interactive) (insert "\u2192"))) ; → right arrow
(global-set-key (kbd "M-a") (lambda () (interactive) (insert "\u03b1"))) ; α alpha
(global-set-key (kbd "M-y") (lambda () (interactive) (insert "\u03c8"))) ; ψ psi
Add to `.vimrc'
" Keybindings for glyphs
:inoremap <A-l> <C-v>u3bb<Space> ; λ lambda
:inoremap <A-f> <C-v>u192<Space> ; ƒ function
:inoremap <A--> <C-v>u2192<Space> ; → right arrow
:inoremap <A-a> <C-v>u03b1<Space> ; α alpha
:inoremap <A-y> <C-v>u03c8<Space> ; ψ psi
Add to `~/Library/KeyBindings/DefaultKeyBinding.dict'
{
"~l" = ("insertText:", "\U03BB"); /* alt + l ~> λ lambda */
"~f" = ("insertText:", "\U0192"); /* alt + f ~> ƒ function */
"~-" = ("insertText:", "\U2192"); /* alt + - ~> → right arrow */
"~a" = ("insertText:", "\U03b1"); /* alt + a ~> α alpha */
"~y" = ("insertText:", "\U03c8"); /* alt + y ~> ψ psi */
}
(defmacro defkeys-top (&rest keys)
(let ((ks (mapcar #'(lambda (k) (cons 'defkey-top k)) keys)))
`(progn ,@ks)))
(defcommand xdo-lambda () ()
(run-shell-command "xdotool type λ"))
(defcommand xdo-fn () ()
(run-shell-command "xdotool type ƒ"))
(defcommand xdo-alpha () ()
(run-shell-command "xdotool type α"))
(defcommand xdo-arrow () ()
(run-shell-command "xdotool type →"))
(defkeys-top
("s-l" "xdo-lambda")
("s-f" "xdo-fn")
("s--" "xdo-arrow")
("s-a" "xdo-alpha"))
If you're absolutely opposed to non-ascii characters, you can use:
λ == /.
ƒ == f
→ == ->
See LICENSE.md