Calling forget on F(%phi, constant) gives a stack overflow:
(%i1) forget(F(%phi, constant));
INFO: Caught stack overflow exception (sp=0x0000000000412000); proceed with caution.
Maxima encountered a Lisp error:
Control stack exhausted (no more space for function call frames).
This is probably due to heavily nested or infinitely recursive function
calls, or a tail call that SBCL cannot or has not optimized away.
PROCEED WITH CAUTION.
Automatically continuing.
To enable the Lisp debugger set *debugger-hook* to nil.
INFO: Reprotecting control stack guard (0x0000000000411000+0x21000)
Also, forget incorrectly forgets facts that are in the global context:
(%i1) constantp(%phi);
(%o1) true
(%i2) forget(kind(%phi, constant));
(%o2) [kind(%phi, constant)]
(%i3) constantp(%phi);
(%o3) false
Finally, the user-documentation for forget says that forget "Removes predicates established by assume." Facts in global aren't established by a user using assume, but internally, at least effectively, they are established by assume. So arguably, the user-documentation isn't clear.
Also, calling
forgeton a mapatom causes a stack overflow:A version of
forgetthat might fix these bugs:But the check
($member pat ($facts '$global))seems to require a noticeable amount of time and space.Tracing KILL2 seems to show that it is calling itself recursively. Something about
F(%phi, constant)makes KILL2 think that recursion is needed -- what is going on there? I notice that the presence of%phiseems to be key -- if it'sfoo, then the error is avoided.About refusing to forget facts in the context
global, I think I'm OK with removing those, and instead fixing up the documentation to say that built-in assertions inglobalcan be forgotten. In general Maxima doesn't apply the same operations to built-in stuff as to user-defined; looks like this is an area in which it does. I think that's generally a good idea -- applying rules uniformly makes it easier to predict the outcome.I would argue that allowing to forget facts such as that
%piis a constant or the newly addedzeroa > 0,zerob < 0is basically never a good idea and creates inconsistent and surprising results.%pilike a constant or having a certain value, regardless of whether the factkind(%pi, constant)exists in the database or not.%piand other system constants, so it's only consistent to also forbid making or removing assumptions about them.killrestores the initial assumptions on%pietc. So allowing to forget that%piis a constant and then callingkill(%pi)would restore the initial assumptions, which is very surprising. One wouldn't expectkillto actually add assumptions, only remove them.forgetcall. In fact, a similar thing happened inrtest_limit_extra.mac, which contained aassume(zeroa > 0)followed by some tests and thenforget(zeroa > 0). After these facts were promoted to the global context, this test (inadvertently) removed them.DATAproperty, which makes the fact effectively forgotten.