rtoy / maxima

A Clone of Maxima's repo
Other
0 stars 0 forks source link

declare(foo, constant) interferes with foo as a function argument #2284

Open rtoy opened 3 months ago

rtoy commented 3 months ago

Imported from SourceForge on 2024-07-05 22:42:03 Created by matan-bebop on 2016-11-23 14:59:27 Original: https://sourceforge.net/p/maxima/bugs/3251


(%i1) declare(l1, constant)$

(%i2) facsum(a);

#0: facsum(_l=[a])(genut.mac line 130)
 -- an error. To debug this try: debugmode(true);

What causes the problem directly is the function in the file from the error message,

setlist(lst,l1,l2) :=
  (l1::first(lst),l2::last(lst))$

I wasn't able to reproduce the behaviour with a user-defined function:

(%i1) setsmth(l1,val) := l1::val$

(%i2) setsmth(a, 4)$ a;
(%o3)                                  4
(%i4) declare(l1, constant)$

(%i5) setsmth(b, 5)$ b;
(%o6)                                  5
(%i7) setsmth1(l1,val) := l1::val$

define: in definition of setsmth1, found bad argument l1
 -- an error. To debug this try: debugmode(true);

However, I am not sure this is correct either.

BTW, my current workaround for this bug is

facsuml1l2(e) := block(local(l1, l2), facsum(e, [l1, l2]));
rtoy commented 3 months ago

Imported from SourceForge on 2024-07-05 22:42:04 Created by robert_dodier on 2016-12-10 00:51:01 Original: https://sourceforge.net/p/maxima/bugs/3251/#f0cb


rtoy commented 3 months ago

Imported from SourceForge on 2024-07-05 22:42:08 Created by robert_dodier on 2016-12-10 00:51:01 Original: https://sourceforge.net/p/maxima/bugs/3251/#9613


Thanks for the bug report. This is a known problem, but I don't see any other bug reports for it. I've changed the description of the report to indicate that it is a broader topic.

Anyway the problem is that Maxima considers all instances of a symbol to be the same. So when you have declare(foo, constant) in your program and then bar(foo) := ..., then the foo in bar(foo) is the same as the foo in declare(foo, ...). This is part of Maxima's general policy of "dynamic scope".

A different approach which would avoid this problem is "lexical scope" in which instances of foo in different contexts actually represent distinct symbols. Lexical versus dynamic scope comes up pretty often (at least once a year I'd say) but there is not yet a specific proposal to change to lexical scope at this point.

I don't know a better workaround than the one you posted.

rtoy commented 3 months ago

Imported from SourceForge on 2024-07-05 22:42:11 Created by matan-bebop on 2023-01-26 10:28:26 Original: https://sourceforge.net/p/maxima/bugs/3251/#9613/7b4f


Could it be that in this very case it is enough that function arguments not only "treated in exactly same way as the variables in a block" (from ? Function) -- that is, their value is removed and restored, but also any properties of the argument are removed and restored (just like the local does)?

Maybe doing this also cures the following?


(%i1) callfun(fun) := fun()$
(%i2) foo() := print("Hey")$
(%i3) callfun(foo)$
Hey 
(%i4) fun() := print("Bye")$
(%i5) callfun(foo)$ /* One expects to hear "Hey" again */
Bye 
(%i6) fun(x) := print("Bye,", x)$
(%i7) callfun(foo)$

Too few arguments supplied to fun(x); found: []
#0: callfun(fun=foo)
 -- an error. To debug this try: debugmode(true);

I recently got this kind of nuisance in my project. That's a second time I do a relatively large project in Maxima and it seems I have a trouble that is related to the one I got 7 years ago in my first project.

rtoy commented 3 months ago

Imported from SourceForge on 2024-07-05 22:42:15 Created by matan-bebop on 2023-01-26 11:47:18 Original: https://sourceforge.net/p/maxima/bugs/3251/#0eed


Actually, the original bug now does not reproduce for me (5.46.0 with GCL x86_64-redhat-linux-gnu)...

rtoy commented 3 months ago

Imported from SourceForge on 2024-07-05 22:42:18 Created by robert_dodier on 2023-01-26 18:37:23 Original: https://sourceforge.net/p/maxima/bugs/3251/#4538


rtoy commented 3 months ago

Imported from SourceForge on 2024-07-05 22:42:22 Created by macrakis on 2023-01-26 19:24:14 Original: https://sourceforge.net/p/maxima/bugs/3251/#c699/a048


I suppose that the lexical scope code does not allow binding system constants like true, false, %e, %pi, %i, etc.

rtoy commented 3 months ago

Imported from SourceForge on 2024-07-05 22:42:25 Created by robert_dodier on 2023-01-27 03:31:12 Original: https://sourceforge.net/p/maxima/bugs/3251/#c699/a048/c80f


@macrakis Yes, built-in constants are excluded in the current implementation of lexical symbols, as are user-declared constants, any symbol defined via DEFMVAR in the source code (these are built-in global variables), and any symbol declared global.

It bothers me a little that there is potential for the same action-at-a-distance bugs as soon as there is a way to bypass lexicalization via declarations. Strictly speaking it is not logically necessary for built-in constants, although it seems actually necessary for global variables -- if global variables are not excluded from lexicalization, block([globvar: smthng], ...) doesn't have the expected effect.