Can't pass user-defined symbols to apply


#1

ulisp 3.3 on esp32 but it’s likely the same in all versions:

(defun my (x y) (+ x y))
(defvar handlers '(my))
(apply (first handlers) '(0 1)) 
Error: not valid here: my

With builtins it works as expected:

(defvar handlers '(cons))
(apply (first handlers) '(0 1))
(0 . 1)

Yes I can do (defvar handlers (list my)) but then I lose the ability to easily check later if 'my is in the list.
Or I can do (apply (eval (first handlers)) '(0 1)) but apply should probably evaluate its first argument by default, as it does in common lisp.


#2

Yes this is a bug; thanks for finding it.

I think the following change should fix it; in the definition of:

object *apply (symbol_t name, object *function, object *args, object *env)

replace the first if block with:

  if (symbolp(function)) {
    symbol_t fname = function->name;
    if (fname <= ENDFUNCTIONS) {     
      checkargs(fname, args);
      return ((fn_ptr_type)lookupfn(fname))(args, env);
    } else function = eval(function, env);
  }

If no further problems are found I’ll incorporate this into the next release.

Note that it affects all platforms, and also affects other functions that take a function argument, such as funcall, mapc, mapcar, sort, etc.


#3

Thanks, the patch works fine!


#4