1

I'm playing around with apply-partially and I'm confused about what gets returned when calling this function. The documentation states that apply-partially returns a function, but then I'd expect to be able to do the following:

(defun add-numbers (a b)
  (+ a b))
(defun add2 (apply-partially 'add-numbers 2))

and then call the function:

(add2 3)

OR:

(funcall add2 3)

Unfortunately this throws an error. When I do everything inside of a let, however, it does work and I get "5" back:

(let ((add2 (apply-partially 'add-numbers 2)))
  (funcall add2 3))

I thought maybe the difference was that let doesn't use defun, as I do above, but then I would expect the following to work:

(defvar add2 (apply-partially 'add-numbers 2))
(funcall
 add2 3)

but that doesn't work either. So what am I missing? Is it not possible to assign the return value of apply-partially outside of a let?

jch
  • 5,680
  • 22
  • 39
flooose
  • 511
  • 6
  • 14
  • Wait, I see now, that my `(defun add2 (....))` can't work because `defun` sees `(apply-partially 'add-numbers 2)` as an argument list. `apply-partially` never actually gets called here. So that means the `(defun add (...))` call CAN'T work, leaving only the `(defvar add2 (...))` towards the bottom. – flooose May 18 '18 at 12:16
  • You could also use `defalias` – npostavs May 18 '18 at 12:36
  • You're right, using `defalias` allows me to call the return value of `apply-partially` in the following way: `(add2 3)`, i.e. as a normal function. `(funcall add2 3)` doesn't work, but that's also not a problem. Thanks :) – flooose May 18 '18 at 12:41

1 Answers1

1

I figured it out. As noted in my comment above, my code:

(defun add2 (apply-partially 'add-numbers 2))

can't work because defun is a special form and (apply-partially 'add-numbers 2) is seen as the argument list to the special form, i.e. apply-partially never gets evaluated.

This leaves us with the challenge of saving the call (apply-partially 'add-numbers 2) to something else that can either be called directly, i.e. (add2 3) or with (funcall add2 33). As mentioned, my attempt with defvar above doesn't work:

(defvar add2 (apply-partially 'add-numbers 2))

I found the answer here, and has to do with the fact "... that in Emacs Lisp, symbols have a value cell and a function cell, which are distinct. When you evaluate a symbol, you get its value. When you evaluate a list beginning with that symbol, you call its function. This is why you can have a variable and a function with the same name."

So can replace defvar with setq and (funcall add2 3) will work as expected. Otherwise, we can also use fset to set the returned value of apply-partially directly to add2's function cell:

(fset 'add2 (apply-partially 'add-numbers 2))

and then we can simply call the function: (add2 3)

flooose
  • 511
  • 6
  • 14
  • The `defvar` + `funcall` example works for me. – npostavs May 18 '18 at 12:39
  • Am I using `defvar` wrong? I keep getting "Symbol's function definition is void: nil" when I use `defvar` + `funcall` – flooose May 18 '18 at 12:47
  • 1
    Maybe you have set the `add2` variable earlier in the session? See the docstring of `defvar`: `...set SYMBOL, only if SYMBOL's value is void.` – npostavs May 18 '18 at 14:13