0

In order to understand what the symbol funcall means I have checked out its documentation. If I understand it right after reading the docs this symbol represents a function which in my eyes can be always easily removed from the elisp expression without changing the outcome:

(funcall '+ 1 2) ; returns 3
(+ 1 2)          ; returns 3

Also in the code example provided in the funcall function documentation the expression works OK after skipping funcall from it:

(funcall 'cons 'x 'y) ;returns (x . y)
(cons 'x 'y)          ;returns (x . y)

What is the difference between the two code versions giving funcall the right to exist?

Is it just for fun there in order to be able to obfuscate:

(+ 3 2)

expressing it as:

(defun 3+ (x) (+ x 3)) (3+ 2)
(funcall (lambda (x) (+ x 3)) 2)
;; with finally: 
(funcall (setq 3+ (lambda (x) (+ x 3))) 2)

?

Or is it there to fix the problem if someone erroneously misused the value slot of a symbol to store there a function?

In other words: is there a code example able to demonstrate a meaningful usage of funcall?


@Drew : elisp is able to distinguish between the value and the function "slots" of a symbol without usage of funcall from the context of symbols usage. Run following piece of code in Emacs 29 to see it yourself:

(setq  f    2)
(defun f () 3)
(message "val: %s  func: %s  symb: %s" f (f) 'f)

which gives:

"val: 2  func: 3  symb: f"

@Drew : to my knowledge in elisp ALL symbols and expressions are ALWAYS evaluated. Also 'f becomes evaluated and it equals to f only because ' is a syntactical sugar for a special form quote returning f as the value of to it passed parameter without evaluating it.

12
  • funcall is a function, which in Lisp means that all of its args are evaluated. Consider that you can pass a variable whose value is a function to a funcall sexp. That sexp can then invoke whatever function is the variable's value. You can, e.g., use funcall in a higher-order function that takes a function as one of its arguments, and that invokes that function. This is how higher-order functions such as mapcar work.
    – Drew
    Apr 17, 2023 at 1:53
  • 1
    I really suggest you read about Lisp a bit. Maybe read the manual Introduction to Programming in Emacs Lisp, which is provided with Emacs (C-h i).
    – Drew
    Apr 17, 2023 at 1:53
  • 2
    Again, don't try to learn about this just from some comments here. Read a bit about Lisp. That's a suggestion.
    – Drew
    Apr 17, 2023 at 2:01
  • 1
    Of course Emacs Lisp can distinguish between the value cell and the function cell of a symbol. The question is how to call a function that is stored in the value cell of a symbol: it's for that you need funcall. Why you would want to store a function in the value cell of a symbol? See my answer for a "real" example.
    – NickD
    Apr 17, 2023 at 4:02
  • 2
    Do NOT write: ((lambda (...) ...) ...), see 10.2.4: “This form is rarely used and is now deprecated.
    – shynur
    Apr 17, 2023 at 7:09

3 Answers 3

1

Virtually all of the "real" examples are variations of the following theme: you have a list of functions and you want to call each function in turn (e.g. hooks are lists of functions - when the hook is run, we march down the list and call each function in turn). You cannot march down the list with car and cdr and for each element call it. E.g. this does not work:

;; make a list of a couple of functions
(setq my-hook nil)
(add-hook 'my-hook (lambda () (message "foo")))
(add-hook 'my-hook (lambda () (message "bar")))

;; march down the list, calling each function in turn
(dolist (element my-hook) (element))
==> Debugger entered--Lisp error: (void-function element)
  (element)
  (let ((element (car tail))) (element) (setq tail (cdr tail)))
  (while tail (let ((element (car tail))) (element) (setq tail (cdr tail))))
  (let ((tail my-hook)) (while tail (let ((element (car tail))) (element) (setq tail (cdr tail)))))
  (progn (let ((tail my-hook)) (while tail (let ((element (car tail))) (element) (setq tail (cdr tail))))))
  eval((progn (let ((tail my-hook)) (while tail (let ((element (car tail))) (element) (setq tail (cdr tail)))))) t)

element is bound to each element of the list in turn, but through its value cell, not its function cell, so you cannot call it as a function any more than you can do:

(setq foo (lambda () (message "foobar")))
(foo) ==>  
Debugger entered--Lisp error: (void-function foo)
  (foo)

But you can funcall it:

(funcall foo) ==> nil ;; i.e. no error

Similarly for the my-hook list of functions, you can do:


(dolist (element my-hook) (funcall element))

In both cases, you can check *Messages* to see that the functions were indeed called (and in the correct order in the case of the list).

As I said, this is how hooks are run. There are complications of course, which is why simple examples are used to get the concepts across before you have to worry about all the additional wrinkles that have to be ironed out with real hooks.

0
0

Let's consider the case that you have plenty of functions in your Emacs initialization file to which you pass 1 as parameter:

(desktop-save-mode 1)
;; ... many other functions ...
(show-paren-mode   1) 

Now you want to avoid repetition of the parameter value 1 and the calls replacing the above with only one function call to which you pass a list of functions taking this parameter. The code which accomplishes this would be hard to write without using funcall:

;; Run multiple functions with the same passed to them parameter
(mapcar (lambda (f) (funcall f 1)) '(
    desktop-save-mode 
;; ... many other functions ...
    show-paren-mode
))

because in this kind of code design elisp is somehow not able to recognize from the context that f will represent a symbol storing a function and must be instructed with funcall in order not to fail with the message: "Symbol’s function definition is void: f" while running the code.

As explained in the answer by NickD the "somehow not able" is caused by the elisp mechanism of taking items from a list of items in order to provide them as item symbol to the item processing code block.

This mechanism is not capable of recognizing the context and therefore does not differentiate between list symbols representing functions and list symbols representing values. In other words this mechanism provides the list items just always in a value cell instead of the function cell in case the list items are functions. The consequence of this fact is the necessity of using funcall to avoid elisp runtime errors.

0

Symbols can't just hold a value (as variables). Symbols can also hold a function definition (see Symbol Components). That is, a symbol can act as both a variable and a function.

funcall just calls the function definition stored in a symbol.

A real example from my repo: org-shoplist is a testing-function:

(defun org-shoplist-test-test-in-buffer (func-in-buffer)
  (org-shoplist-test-test
   (lambda ()
     (unwind-protect
         (with-current-buffer (get-buffer-create org-shoplist-test-default-buffer)
           (funcall func-in-buffer)) ;; <--- function called which is stored in the arguemnt
       (kill-buffer org-shoplist-test-default-buffer)))))

This function executes a test in temp-buffer and leaves everything in same state as before. ‘FUNC-IN-BUFFER’ is what should be done in the temp-buffer.

Concrete call of this function would look like this:

(ert-deftest org-shoplist-test/recipe-read-one-ing ()
  (org-shoplist-test-test-in-buffer
   (lambda ()
     (setq org-shoplist-inital-factor nil)
     (insert "* Test
- (200g Nuts) mahlen")
     (goto-char (point-min))
     (should (equal (list "Test" nil 'org-shoplist--recipe-read-ings-current
                          (list (org-shoplist-ing-create "200g" "Nuts")))
            (org-shoplist-recipe-read 'org-shoplist--recipe-read-ings-current))))))

I pass a concrete function (the test-case) into another more general function (which has the funcall-call). funcall helps writing lesser code, because I can extract the general parts and pass in the concrete ones by argument.

6
  • Hmmm ... What is func-in-buffer? Is it what I suggested to be "erroneously misusing a value slot for storing a function"? At the first glance the code looks for me like an obfuscated (+ 3 2) or result of a confusion of its programmer. Sorry ... it's to complex for me - I have no idea what org mode is for too having same problems to see a meaningful example of its usage.
    – Claudio
    Apr 17, 2023 at 1:40
  • Hi Claudio, I added a concret test-case to illustrate my example a bit more. Beaware that a symbol has 2 slots. One for values, and one for function definition. Why is it wrong to store a function definition in a symbol?
    – lordnik22
    Apr 17, 2023 at 1:56
  • Nothing wrong with storing a function in the function slot of a symbol. But storing a function in the value slot in spite of the fact that it's possible doesn't make sense to me. And yes, I am aware that symbols can store functions and values. But storing functions in a symbol using (setq instead of (defun does not make much sense. The "finally" line of the obfuscated code in my question uses funcall exactly for the "purpose" of running a function which was stored as a value.
    – Claudio
    Apr 17, 2023 at 2:07
  • Funny:: "200g Nuts", but "mahlen" not "grind" :) or ... "Nuts" instead of "Nüsse" :)
    – Claudio
    Apr 17, 2023 at 2:11
  • I have checked out the code in your repo. For example you don't need the funcall in (funcall #'org-mode) which makes it only an obfuscated way of coding (org-mode). Anyway the org-mode symbol does not have a value, so it does not make sense to indicate explicit that you use it's function cell either. I suggest you reconsider your coding style getting rid of funcall in cases it is unnecessary polluting the code.
    – Claudio
    Apr 17, 2023 at 11:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.