I'd like to have a Maxima function to detect functions that have already been defined. This could be called is_function
, so that is_function(sin)
and is_function(exp)
would be true, but is_function(%pi)
and is_function(foo)
would be false (assuming that I have not defined foo
). Does this exist already?
The manual says
Some Lisp functions are shadowed in the Maxima package, namely the following ... functionp ...
I'm not sure exactly what this means, but functionp(sin)
returns false
, and functionp(foo)
also returns false
even if I define foo(x) := x;
. Also, fundef(sin)
and dispfun(sin)
fail with message fundef: no such function: sin
, although fundef(foo)
works if I define foo(x)
as before.
There are several ways to define functions, and Maxima doesn't really have a way to detect any of them.
UPDATE: An slightly expanded version of the previous solution can now be found at: https://github.com/maxima-project-on-github/maxima-packages in the folder robert-dodier/fboundp.
PREVIOUS SOLUTION: Here's an attempt which looks at the Lisp symbol properties to see what's there.
/* fboundp.mac -- detect different kinds of functions in Maxima
* copyright 2020 by Robert Dodier
* I release this work under terms of the GNU General Public License
*
* Examples:
*
/* Simplifying function defined in Lisp: */
fboundp(sin);
true;
fboundp_simplifying(sin);
true;
/* DEFUN (ordinary argument-evaluating) function defined in Lisp: */
fboundp(expand);
true;
fboundp_ordinary_lisp(expand);
true;
/* DEFMSPEC (argument-quoting) function defined in Lisp: */
fboundp(kill);
true;
fboundp_quoting(kill);
true;
/* Maxima ordinary function: */
(kill(foo),
foo(x) := x,
fboundp(foo));
true;
fboundp_ordinary_maxima(foo);
true;
/* Maxima array function: */
(kill(bar),
bar[x](y) := x*y,
fboundp(bar));
true;
fboundp_array_function(bar);
true;
/* Maxima macro: */
(kill(baz),
baz(x) ::= buildq([x], x),
fboundp(baz));
true;
fboundp_maxima_macro(baz);
true;
*
*/
fboundp(a) :=
fboundp_simplifying(a)
or fboundp_ordinary_lisp(a)
or fboundp_quoting(a)
or fboundp_ordinary_maxima(a)
or fboundp_array_function(a)
or fboundp_maxima_macro(a);
fboundp_simplifying(a) :=
symbolp(a) and ?get(a, ?operators) # false;
fboundp_ordinary_lisp(a) :=
symbolp(a) and ?fboundp(a) # false;
fboundp_quoting(a) :=
symbolp(a) and ?get(a, ?mfexpr\*) # false;
fboundp_ordinary_maxima(a) :=
symbolp(a) and ?mget(a, ?mexpr) # false;
fboundp_array_function(a) :=
symbolp(a) and ?mget(a, ?aexpr) # false;
fboundp_maxima_macro(a) :=
symbolp(a) and ?mget(a, ?mmacro) # false;
EDIT: I've made a separate function to test for each kind of function, and I put in a test for symbolp
to ensure that the property-inspection stuff (?get
and ?mget
) won't fail.