Function Namespace
rontolisp is a Lisp-2, following Common Lisp: functions and variables live in separate namespaces.
- A bare symbol evaluates as a variable. Evaluating
caralone is an error (The variable car is unboundin the interpreter; a compile error in the compilers). - A symbol in call position
(f args...)resolves in the function namespace only. A variable namedcarnever shadows the functioncar:(let ((car 5)) (car (list car 2)))returns5. - A function becomes a value through
#'name(reader syntax for(function name)),#'(lambda ...), or(symbol-function 'name). This works for built-in operators (#'+,#'car,#'1+,#'cadr), userdefuns, and lambdas. funcall/mapcar/reducealso accept a symbol naming a function (a function designator):(funcall 'car '(1 2))returns1. The compilers support this when the symbol is a quoted literal.defundefines into the function namespace and returns the function name.(setq f (lambda ...))binds a variable to a function value; call it with(funcall f ...), not(f ...).#'of a macro or special operator (e.g.#'if,#'defun) is an error.
Function values can be passed as arguments, returned from functions, and stored in data structures in all three execution modes.
Higher-order functions:
Closures (capture by reference):
Lambda as argument:
Built-in operators as first-class values:
Built-in operators like +, car, 1+ can be passed to higher-order functions via #':
Compiler restrictions. In the JVM/WASM compilers, #'name resolves against the
functions known at compile time (user defuns and built-in operators). #'reduce and
#'apply themselves are not available as values there (the interpreter has them);
#'mapcar, #'mapcan, #'sort and #'funcall are. symbol-function requires a quoted
symbol literal argument. In
--dynamic mode an unresolved #'name is deferred to the runtime eval environment like
any other unresolved reference. In compiled code apply/funcall dispatch by the actual
argument count against a fixed-arity wrapper synthesized for each built-in operator. The
naturally variadic operators -- +, -, *, /, list, min, max -- have variadic
wrappers, so (funcall #'+ 1 2 3), (apply #'list ...) and the like accept any argument
count. Every other multi-argument built-in keeps a fixed wrapper arity: #'cons,
#'append, #'gcd and the comparison chains (#'<, #'=, ...) are binary, so applying
them to a different count is unsupported on the compile path (matching the
Compiled eval limitations); use a user-defined function
or a lambda for other arities. The interpreter has no such restriction.
Redefining a COMMON-LISP function
(defun random ...), (defun length ...) and the like are undefined behavior in
Common Lisp (CLHS 11.1.2.1.2), and rontolisp's backends genuinely differ:
- the interpreter resolves the call through the function cell, so your definition runs;
- the JVM and WASM compilers recognize the standard operator at the call site and compile it inline, so your definition does not run there. They print a compile-time warning naming the operator and the position of the first such call site, so the divergence is never silent.
#'random names your definition on every backend, which is why the warning says the
definition is still reachable that way. To have one definition everywhere, give it a
name of your own or shadow the symbol into a package of your own. A defmethod on a
built-in name is a different case and does work on every backend: it becomes the
generic's default method.