Joxa (just like Clojure) is a Lisp1, thus maybe more apt http://joxa.org
Joxa (just like Clojure) is a Lisp1, thus maybe more apt http://joxa.org
I just prefer to pass around functions/closures as values, and being able to invoke them like any normal function, instead of having to call an helper `apply`/`invoke`/`call` function on them (depending on the language)
That's why I said: "maybe more apt"... if OP doesn't care at all about that difference, and it's not among the details that they'd want to replicate from Clojure, it's perfectly ok to ignore
In Common lisp to refer to a function as a variable you do (function f) or as (read-table) syntactic sugar #'f. You could easily use destructuring to write HOFs without funcall.
So instead of requiring people to write
(defun bad-map (f list)
"Maps function `f' over `list', inefficiently."
(when list (cons (funcall #'f (first list) (bad-map f (rest list)))))
(bad-map #'- '(1 2 3))
A hypothetical lisp-2 could just as well allow destructuring like this: (defun bad-map (#'f list)
"Maps function `f' over `list', inefficiently."
(when list (cons (f (first list) (bad-map #'f (rest list)))))
(bad-map #'- '(1 2 3))
The fact that higher order functions stick out a bit by the extra #' is not necessarily a bad thing IMO; it helps when reading unfamiliar code to know immediately what arguments are functions and which ones are just plain objects. (funcall #'f (first list) ...)
but (funcall f (first list)) ...
f is already a function object.We could write a macro for that or a new version of defun. Here just a macro lisp1fy:
(defmacro lisp2fy ((&rest calls) &body body)
`(flet (,@(loop for (f . args) in calls
collect `(,f ,args (funcall ,f ,@args))))
(declare (inline ,@(loop for (f . nil) in calls collect f)))
,@body))
(defun bad-map (f list)
"Maps function `f' over `list', inefficiently."
(lisp2fy ((f a))
(when list
(cons (f (first list))
(bad-map f (rest list))))))This means that Lisp-1 doesn't really fit anyway so why let it limit you?