Closed guicho271828 closed 5 years ago
here are my thoughts:
the first cases, self-evaluating symbols, there are no problem.
constant variables. The issue is it is impl-dependent if the vars are already evaled/bound in the compile time. I think this case can be covered easily by just wrapping the eval with handler-case / UNBOUND-VARIABLE and falling back to t.
quoted form --- this is already handled separately.
some impl-dependent form --- Reading carefully,
file:///usr/share/doc/hyperspec/Body/f_consta.htm
An implementation is permitted, but not required, to detect additional constant forms.
And the definition of constant forms is
file:///usr/share/doc/hyperspec/Body/26_glo_c.htm#constant_form
constant form n. any form for which evaluation always yields the same value, that neither affects nor is affected by the environment in which it is evaluated (except that it is permitted to refer to the names of constant variables defined in the environment), and that neither affects nor is affected by the state of any object except those objects that are otherwise inaccessible parts of objects created by the form itself. ``A car form in which the argument is a quote form is a constant form.''
So, constantp never returns true for forms that are affected by the environment. Forms that constantp returns true should evaluate to the same value in any environment, how different they are. Also, evaluation should not affect the external environment, thus the following forms are not constant:
(defvar *a* 0)
(let ((b 1)) (+ b *a*)) ; not constant, affected by the global environment
(let ((b 1)) (setf *a* b) b) ; not constant, affects the global environment
Thank you for working on this.
One thing - I am not sure whether it is safe to EVAL forms that are CONSTANTP, because the compilation environment might be different from the run time environment. We recently had a discussion about this on IRC: https://irclog.tymoon.eu/freenode/%23lisp?around=1546955930#1546955930