Is there a terse idiomatic way of calling a function in the manner of
funcall (dereferencing function symbols) when that function may have a variably shorter function signature?
Say for example: a hook assumes a signature of (VALUE PARENT), but for convenience it would be nice to also allow functions with the signature (VALUE) or (). Evaluation using
funcall will throw an error if the signature is any shorter than the arguments of the funcall invocation.
Here's a demonstration of the behavior I'm looking for:
(require 'dash) (defun my/foo (a) (* a a)) (defun my/bar (a b) (* a b)) (defun my/easy-going-funcall (fn &rest args) "" (let ((num-args (length (cadr (if (symbolp fn) (symbol-function fn) fn))))) (apply fn (-slice args 0 num-args)))) (my/easy-going-funcall #'my/foo 2 3 4) ;; 4 (my/easy-going-funcall #'my/bar 2 3 4) ;; 6 (my/easy-going-funcall (lambda () 42) 2 3 4) ;; 42
What equivalent does elisp have for something like
P.S. I realize this method of reflection doesn't work for built-in C functions and breaks down with argument keywords, but I don't know any better yet!
This really boils down to syntactic sugar for users and developers of a library. From the user's perspective, if a hook expects functions with signature
(ARG1 ARG2 ARG3) and their function ignores all three arguments they could write
(lambda (&rest _unused) ...) for legibility. If the hook itself has a mechanism to reliably call functions with shorter signatures (as this question asks) then the user may omit
&rest _unused entirely and write
(lambda () ...) as a matter of convenience.
On the flip-side, developers have additional flexibility in defining hooks. Adding an additional argument to a hook signature does not need to be a breaking change.
(lambda () (foo "bar"))vs
(lambda (arg1 arg2 arg3 arg4) (foo "bar"))). Users need not declare unused parameters and it offers the package designer some additional flexibility in extending the hook signature. I hope that answers your question.