* Should `indirect-function' be preferred over `fboundp'?
@ 2023-07-20 7:08 Ihor Radchenko
2023-07-20 7:42 ` Eli Zaretskii
` (3 more replies)
0 siblings, 4 replies; 12+ messages in thread
From: Ihor Radchenko @ 2023-07-20 7:08 UTC (permalink / raw)
To: emacs-devel
Hi,
I have recently stumbled upon the common Elisp pattern
(when (fboundp func) (funcall func)) failing.
This is happening when a symbol is declared as function alias to
non-existing function:
(defalias 'yant/foo 'yant/bar)
(fboundp 'yant/foo) ; => t
(funcall 'yant/foo) ; => ERROR: Symbol function definition is void: yant/foo
In contrast, `indirect-function' does a better job determining whether a
given symbol can be called as a function:
(indirect-function 'yant/foo) ; => nil
Is it something widely known?
Is it something to worry about?
(I can see that `fboundp' is used all over Emacs git sources, while
`indirect-function' is rarely used)
--
Ihor Radchenko // yantar92,
Org mode contributor,
Learn more about Org mode at <https://orgmode.org/>.
Support Org development at <https://liberapay.com/org-mode>,
or support my work at <https://liberapay.com/yantar92>
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: Should `indirect-function' be preferred over `fboundp'?
2023-07-20 7:08 Should `indirect-function' be preferred over `fboundp'? Ihor Radchenko
@ 2023-07-20 7:42 ` Eli Zaretskii
2023-07-20 8:23 ` Ihor Radchenko
2023-07-20 7:47 ` Andreas Schwab
` (2 subsequent siblings)
3 siblings, 1 reply; 12+ messages in thread
From: Eli Zaretskii @ 2023-07-20 7:42 UTC (permalink / raw)
To: Ihor Radchenko; +Cc: emacs-devel
> From: Ihor Radchenko <yantar92@posteo.net>
> Date: Thu, 20 Jul 2023 07:08:48 +0000
>
> (defalias 'yant/foo 'yant/bar)
> (fboundp 'yant/foo) ; => t
> (funcall 'yant/foo) ; => ERROR: Symbol function definition is void: yant/foo
>
> In contrast, `indirect-function' does a better job determining whether a
> given symbol can be called as a function:
>
> (indirect-function 'yant/foo) ; => nil
>
> Is it something widely known?
The ELisp manual says:
-- Function: fboundp symbol
This function returns ‘t’ if the symbol has an object in its
function cell, ‘nil’ otherwise. It does not check that the object
is a legitimate function.
So this is at least documented.
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: Should `indirect-function' be preferred over `fboundp'?
2023-07-20 7:08 Should `indirect-function' be preferred over `fboundp'? Ihor Radchenko
2023-07-20 7:42 ` Eli Zaretskii
@ 2023-07-20 7:47 ` Andreas Schwab
2023-07-20 8:25 ` Ihor Radchenko
2023-07-20 13:02 ` Alan Mackenzie
2023-07-21 1:08 ` Michael Heerdegen
3 siblings, 1 reply; 12+ messages in thread
From: Andreas Schwab @ 2023-07-20 7:47 UTC (permalink / raw)
To: Ihor Radchenko; +Cc: emacs-devel
On Jul 20 2023, Ihor Radchenko wrote:
> (I can see that `fboundp' is used all over Emacs git sources, while
> `indirect-function' is rarely used)
indirect-function used to signal an error when unbound.
--
Andreas Schwab, SUSE Labs, schwab@suse.de
GPG Key fingerprint = 0196 BAD8 1CE9 1970 F4BE 1748 E4D4 88E3 0EEA B9D7
"And now for something completely different."
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: Should `indirect-function' be preferred over `fboundp'?
2023-07-20 7:08 Should `indirect-function' be preferred over `fboundp'? Ihor Radchenko
2023-07-20 7:42 ` Eli Zaretskii
2023-07-20 7:47 ` Andreas Schwab
@ 2023-07-20 13:02 ` Alan Mackenzie
2023-07-20 13:08 ` Ihor Radchenko
2023-07-21 1:08 ` Michael Heerdegen
3 siblings, 1 reply; 12+ messages in thread
From: Alan Mackenzie @ 2023-07-20 13:02 UTC (permalink / raw)
To: Ihor Radchenko; +Cc: emacs-devel
Hello, Ihor.
On Thu, Jul 20, 2023 at 07:08:48 +0000, Ihor Radchenko wrote:
> Hi,
> I have recently stumbled upon the common Elisp pattern
> (when (fboundp func) (funcall func)) failing.
> This is happening when a symbol is declared as function alias to
> non-existing function:
> (defalias 'yant/foo 'yant/bar)
> (fboundp 'yant/foo) ; => t
> (funcall 'yant/foo) ; => ERROR: Symbol function definition is void: yant/foo
I don't think it affects the point you are making, but why are you using
funcall in the last line, rather than just calling the funcion as
(yant/foo)
? I initially got confused and thought you were doing
(funcall yant/foo)
, which would have been an obvious error.
> In contrast, `indirect-function' does a better job determining whether a
> given symbol can be called as a function:
> (indirect-function 'yant/foo) ; => nil
> Is it something widely known?
> Is it something to worry about?
> (I can see that `fboundp' is used all over Emacs git sources, while
> `indirect-function' is rarely used)
> --
> Ihor Radchenko // yantar92,
> Org mode contributor,
> Learn more about Org mode at <https://orgmode.org/>.
> Support Org development at <https://liberapay.com/org-mode>,
> or support my work at <https://liberapay.com/yantar92>
--
Alan Mackenzie (Nuremberg, Germany).
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: Should `indirect-function' be preferred over `fboundp'?
2023-07-20 13:02 ` Alan Mackenzie
@ 2023-07-20 13:08 ` Ihor Radchenko
0 siblings, 0 replies; 12+ messages in thread
From: Ihor Radchenko @ 2023-07-20 13:08 UTC (permalink / raw)
To: Alan Mackenzie; +Cc: emacs-devel
Alan Mackenzie <acm@muc.de> writes:
> I don't think it affects the point you are making, but why are you using
> funcall in the last line, rather than just calling the funcion as
>
> (yant/foo)
I stumbled upon this behaviour in Org mode's code that works with src
blocks:
#+begin_src language
<code>
#+end_src
Org uses heuristics to determine how to fontify such code blocks:
1. Org tries to derive the major mode name from language name
constructing a symbol as (format "%s-mode" language)
2. If the symbol is a function, Org proceeds running that function to
expedite fontification.
So, no, it would not be possible to write (language-mode) directly.
Function symbol string is calculated dynamically.
--
Ihor Radchenko // yantar92,
Org mode contributor,
Learn more about Org mode at <https://orgmode.org/>.
Support Org development at <https://liberapay.com/org-mode>,
or support my work at <https://liberapay.com/yantar92>
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: Should `indirect-function' be preferred over `fboundp'?
2023-07-20 7:08 Should `indirect-function' be preferred over `fboundp'? Ihor Radchenko
` (2 preceding siblings ...)
2023-07-20 13:02 ` Alan Mackenzie
@ 2023-07-21 1:08 ` Michael Heerdegen
2023-07-21 6:07 ` Ihor Radchenko
3 siblings, 1 reply; 12+ messages in thread
From: Michael Heerdegen @ 2023-07-21 1:08 UTC (permalink / raw)
To: emacs-devel
Ihor Radchenko <yantar92@posteo.net> writes:
> (I can see that `fboundp' is used all over Emacs git sources, while
> `indirect-function' is rarely used)
I'm actually not that surprised. I guess, most often code using an
`fboundp' test wants to test whether a function has already been defined
(e.g. by another package), or is available in the current Emacs version.
An alias is a definition. In most cases the definition as an alias is
intentional. If an alias points to an undefined function, I guess that,
in the majority of cases, this hints at some kind of problem so it's
better to have an error rather than to circumvent the problem by using
`indirect-function'.
Are aliases to undefined functions something to expect often? The
compiler warns in the case when the DEFINITION is the name of an unknown
function. It should be the responsibility of the alias creating code to
ensure that the alias is not broken.
Michael.
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: Should `indirect-function' be preferred over `fboundp'?
2023-07-21 1:08 ` Michael Heerdegen
@ 2023-07-21 6:07 ` Ihor Radchenko
2023-07-22 2:49 ` Michael Heerdegen
0 siblings, 1 reply; 12+ messages in thread
From: Ihor Radchenko @ 2023-07-21 6:07 UTC (permalink / raw)
To: Michael Heerdegen; +Cc: emacs-devel
Michael Heerdegen <michael_heerdegen@web.de> writes:
> An alias is a definition. In most cases the definition as an alias is
> intentional. If an alias points to an undefined function, I guess that,
> in the majority of cases, this hints at some kind of problem so it's
> better to have an error rather than to circumvent the problem by using
> `indirect-function'.
Fair point.
> Are aliases to undefined functions something to expect often? The
> compiler warns in the case when the DEFINITION is the name of an unknown
> function. It should be the responsibility of the alias creating code to
> ensure that the alias is not broken.
In my case, it was ob-lilypond.el aliasing a function in optional
dependency, although that is not a good style (I fixed that already).
Another possible scenarios is `define-obsolete-function-alias' when the
function is not loaded for some reason (like when it is defined in a
different file). We have plenty of these in org-compat.el.
Finally, user aliases defined in the user config, where accidentally not
loading some package is not unseen (especially with `use-package' and
friends that make it more forgiving to not have some packages
installed).
I think that part of the problem _for me_ is that
(defalias 'yant/foo 'yant/bar)
(fboundp 'yant/foo) ; => t
(funcall 'yant/foo) ; => ERROR: Symbol function definition is void: yant/foo
only shows an error for `yant/foo', which is somewhat confusing.
`yant/bar' is where function definition is truly void.
That's what took me some extra time to figure out what is wrong.
--
Ihor Radchenko // yantar92,
Org mode contributor,
Learn more about Org mode at <https://orgmode.org/>.
Support Org development at <https://liberapay.com/org-mode>,
or support my work at <https://liberapay.com/yantar92>
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: Should `indirect-function' be preferred over `fboundp'?
2023-07-21 6:07 ` Ihor Radchenko
@ 2023-07-22 2:49 ` Michael Heerdegen
2023-07-22 10:51 ` Ihor Radchenko
0 siblings, 1 reply; 12+ messages in thread
From: Michael Heerdegen @ 2023-07-22 2:49 UTC (permalink / raw)
To: emacs-devel
Ihor Radchenko <yantar92@posteo.net> writes:
> Another possible scenarios is `define-obsolete-function-alias' when the
> function is not loaded for some reason (like when it is defined in a
> different file). We have plenty of these in org-compat.el.
> Finally, user aliases defined in the user config, where accidentally not
> loading some package is not unseen (especially with `use-package' and
> friends that make it more forgiving to not have some packages
> installed).
These examples still sound like mistakes to me. One can either ensure
the library is loaded, or autoload the aliased function, or define the
alias only after the defining package is loaded (e.g. by using
`with-eval-after-load').
> I think that part of the problem _for me_ is that
>
> (defalias 'yant/foo 'yant/bar)
> (fboundp 'yant/foo) ; => t
> (funcall 'yant/foo) ; => ERROR: Symbol function definition is void: yant/foo
>
> only shows an error for `yant/foo', which is somewhat confusing.
> `yant/bar' is where function definition is truly void.
I see and understand. The error message can be misleading in this case.
When something like this happens, I suggest to start investigating using
`symbol-function' instead of `fboundp'.
It's probably also preferable to function quote the existing function name
when possible, like in
(defalias 'yant/foo #'yant/bar)
Michael.
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: Should `indirect-function' be preferred over `fboundp'?
2023-07-22 2:49 ` Michael Heerdegen
@ 2023-07-22 10:51 ` Ihor Radchenko
2023-07-23 2:37 ` Michael Heerdegen
0 siblings, 1 reply; 12+ messages in thread
From: Ihor Radchenko @ 2023-07-22 10:51 UTC (permalink / raw)
To: Michael Heerdegen; +Cc: emacs-devel
Michael Heerdegen <michael_heerdegen@web.de> writes:
>> I think that part of the problem _for me_ is that
>>
>> (defalias 'yant/foo 'yant/bar)
>> (fboundp 'yant/foo) ; => t
>> (funcall 'yant/foo) ; => ERROR: Symbol function definition is void: yant/foo
>>
>> only shows an error for `yant/foo', which is somewhat confusing.
>> `yant/bar' is where function definition is truly void.
>
> I see and understand. The error message can be misleading in this case.
Would it be of interest to add 2 new error types:
1. Qvoid_indirect_function
2. Qinvalid_indirect_function
It will make it more explicit that it is function indirection that has
problems.
--
Ihor Radchenko // yantar92,
Org mode contributor,
Learn more about Org mode at <https://orgmode.org/>.
Support Org development at <https://liberapay.com/org-mode>,
or support my work at <https://liberapay.com/yantar92>
^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2023-07-23 2:37 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-07-20 7:08 Should `indirect-function' be preferred over `fboundp'? Ihor Radchenko
2023-07-20 7:42 ` Eli Zaretskii
2023-07-20 8:23 ` Ihor Radchenko
2023-07-20 7:47 ` Andreas Schwab
2023-07-20 8:25 ` Ihor Radchenko
2023-07-20 13:02 ` Alan Mackenzie
2023-07-20 13:08 ` Ihor Radchenko
2023-07-21 1:08 ` Michael Heerdegen
2023-07-21 6:07 ` Ihor Radchenko
2023-07-22 2:49 ` Michael Heerdegen
2023-07-22 10:51 ` Ihor Radchenko
2023-07-23 2:37 ` Michael Heerdegen
Code repositories for project(s) associated with this public inbox
https://git.savannah.gnu.org/cgit/emacs.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).