psholtz wrote:They say that Lisp is a "functional" language, so you'd think it should be straightforward, but after googling around I've found comments from people to the effect that "functional programming in elisp is difficult to impossible"..
I was curious about this, so I did a little tinkering.
In your example, you need to use funcall.
Code: Select all
(defun f (x)
(1+ x))
(defun x (y)
(funcall y 1))
(x #'f)
The hashquote is shorthand for (FUNCTION f).
Higher order functions work. We can recurse, use predicates, and there seems to be no problem.
Code: Select all
(defun my-mapper (pred lst-a lst-b)
(labels ((rec (a b acc)
(if (and a b)
(rec (cdr a) (cdr b)
(cons (funcall pred (car a) (car b)) acc))
acc)))
(rec lst-a lst-b nil)))
(my-mapper #'+ '(1 3 5 6) '(41 39 37 36))
...But is it doing proper tail-recursion?
Wikipedia wrote:Emacs Lisp (unlike some other Lisp implementations) does not do tail-call optimization.
Can we do closures?
Code: Select all
(defun my-adder (x)
(lexical-let ((var x))
(lambda (n)
(incf var n))))
(setq frobber (my-adder 8))
(funcall frobber 8) ;; => 16 24 32...
I think lexical-let was added only recently, but yes, that does seem to be a closure.
It may be that functional programming is "next to impossible" in Elisp just because of how heavy in side-effects Emacs programming is... I don't quite buy that, but the argument might hold water.
Anyway, I hope you found this informative. I certainly did. Not all Lisps are created equal, and there are certainly arguments to be made for an Emacs implemented in CL or Scheme. Something with support for threads.
A man can dream...

"If you want to improve, be content to be thought foolish and stupid." -Epictetus