Reputation: 4282
I'm trying to create a function in elisp that returns another function. I looked at this answer to a similar question (how to return function in elisp) but did not understand the answer (I'm literally just starting learning elisp today, so please excuse my ignorance). I thought a simpler example would help. First, consider a function that test whether a number is divisible by 5:
(defun divisible-by-5 (x)
;; tests whether a number is divsible by 5.
(setq remainder (% x 5))
(if (= remainder 0) 1 0)
)
This works fine:
(divisible-by-5 25)
1
Now suppose I want to create a function that can create more of these kinds of test functions---something like:
(defun divisible-by-z (z)
(lambda (z)
(setq remainder (% x z))
(if (= remainder 0) 1 0))
)
This does not work. E.g.,
(defun divisible-by-3 (divisible-by-z 3))
(divisible-by-3 4)
returns an error. I think even seeing an elisp-idiomatic example of how one would implement this pattern would be helpful.
Upvotes: 1
Views: 1084
Reputation: 5274
Another (perhaps simpler) method is to include x
as a variable to be passed to the function:
(defun divisible-by-z (x z) "
Check if x is divisible by z.
If so, return 0.
If not, return the remainder."
(if (% x z) (% x z) 0))
thus:
(divisible-by-z 5 2) --> 1
(divisible-by-z 4 2) --> 0
Upvotes: 0
Reputation: 2600
First, make sure you have lexical-binding
enabled. The simplest way to do so is to evaluate (setq lexical-binding t)
in your current buffer. More information on the topic can be found here.
Your definition of divisible-by-z
is basically correct except that you have a mistype (naming both parameters z
; the lambda's parameter should be x
). Also, it would be more idiomatic to introduce the binding for remainder
with let
- setq
is generally reserved for mutating bindings that already exist. Here's the result:
(defun divisible-by-z (z)
(lambda (x)
(let ((remainder (% x z)))
(if (= remainder 0) 1 0))))
You can't use defun
to create divisible-by-3
in quite the way you've tried - it's expecting the argument list for a new function to be where you have the call to divisible-by-z
.
You could either create a global, dynamic binding with
(defvar divisible-by-3 (divisible-by-z 3))
Or a local, lexical binding with
(let ((divisible-by-3 (divisible-by-z 3)))
...)
Either way, you'll then need to use funcall
to call the function
(funcall divisible-by-3 9) ; => 1
Of course, you could also skip giving it its own name entirely and simply
(funcall (divisible-by-z 3) 10) ; => 0
funcall
is necessary because Emacs Lisp is (basically) a Lisp-2, meaning it can attach both a function and a value to a given symbol. So when you're treating functions as values (returning one from a function or passing one in to a function as a parameter) you essentially have to tell it to look in that value "cell" rather than the usual function cell. If you search for "Lisp-1 vs Lisp-2" you'll find more than you want to know about this.
Upvotes: 4
Reputation: 6293
A possible solution:
(defun divisible-by-3 (x)
(funcall (divisible-by-z 3) x))
Upvotes: 3