Re: Can't parse "a # not b", but parses "a # (not b)" and prints it as "a # not b"

Stavros Macrakis <[email protected]> Sun, 21 Jun 2026 16:04:45 -0400
Newsgroups gmane.comp.mathematics.maxima.general
Message-ID <CACLVabUJ2xxgm0wOUCr-uuNe1egy04Jgh+KL3PSheV72dCd+nA@mail.gmail.com>
--===============0518475629018155427==
Content-Type: multipart/alternative; boundary="0000000000006c08460654c90a8e"

--0000000000006c08460654c90a8e
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

I strongly disagree with any change that parses *a=3Db>c* as *(a=3Db)>c*
or *a=3D(b>c)
*or that interprets *a=3Db=3Dc *as *(a=3Db)=3Dc* or *a=3D(b=3Dc)*.

It's not that "it's a bit of a stretch to figure out what a=3D b > c means.=
"
Of course users can "figure it out" in principle, but we should design
according to the principle of least surprise
<https://en.wikipedia.org/wiki/Principle_of_least_astonishment>, not the
principle of "only your language lawyer knows for sure".

Old programming languages like C and PL/I parsed a=3D=3Db=3D=3Dc as ((a=3D=
=3Db)=3D=3Dc,
notoriously leading to counterintuitive behavior and bugs. Their grammar
was inherited by C++ and Javascript.

Java and C# are more strictly typed, and give a type error. Rust and Go
also forbid it and tell the user to add parentheses, precisely because it
is an "attractive nuisance".

Python treats *a=3D=3Db=3D=3Dc *the way a mathematician would expect: as *(=
a=3D=3Db)
and (b=3D=3Dc)*. For mathematicians, scientists and engineers -- our users =
--
that is the only interpretation that makes sense. Similarly, the only
interpretation of *a<b>=3Dc *that makes sense is (*a<b) and (b >=3Dc)* (but
only evaluating each term once).



On Sun, Jun 21, 2026 at 1:21=E2=80=AFAM Robert Dodier <robert.dodier@gmail.=
com>
wrote:

> I guess I'm a little late to the party. Anyway, about these changes.
>
> (1) change RPOS and LPOS for =3D and #.
>
> (2) change RBP and LBP for inequality operators.
>
> These are both OK by me. These both make it possible to parse some
> expressions which trigger errors now, and don't change any existing
> expressions which don't trigger an error (right?).
>
> It doesn't bother me that it's a bit of a stretch to figure out what a
> =3D b > c means. By assigning binding powers, we give it an unambiguous
> representation -- it must be a =3D (b > c). What does that "mean"? We
> don't need to know. If that's not suitable for some use, then we just
> say "Don't do that." We set up the rules and let the user figure out
> what is meaningful to them  -- that is, I claim, the mathematical
> approach.
>
> I think (1) was somewhat less controversial than (2). Maybe if we
> can't get everybody on board for (2), we can still consider (1).
>
> FWIW & all the best.
>
> Robert
>
> On Tue, Jun 9, 2026 at 10:59=E2=80=AFPM David Scherfgen via Maxima-discus=
s
> <[email protected]> wrote:
> >
> > Dear all,
> >
> > as Stavros noted in this bug report, Maxima fails to parse this:
> >
> > a # not b
> > Error: "Found LOGICAL expression where ALGEBRAIC expression expected"
> >
> > However, a # (not b) with parentheses parses perfectly, but is printed
> without parentheses. This means that Maxima cannot parse its own output.
> (The same for =3D.)
> >
> > Proposed fix:
> > In nparse.lisp, change lpos and rpos for the =3D and # operators from
> $expr to $any. Also, increase the binding powers of  <, <=3D, >=3D and > =
from
> 80 to 85. Note that this is in accordance with most programming languages=
,
> where <, <=3D, >=3D and > have a higher binding power than =3D=3D and !=
=3D, for the
> exact same reason of being able to compare logical expressions. Maxima
> currently has them all the same.
> >
> > If we make this change, the following expressions will parse directly
> without requiring parentheses, building the exact same trees they already
> do:
> >
> > a # not b
> > a =3D not b
> > a =3D b =3D c (parses as (a =3D b) =3D c)
> > a > b =3D c (parses as (a > b) =3D c)
> > c =3D a > b (parses as c =3D (a > b), wouldn't parse with the original
> binding powers)
> >
> > Would this have any unintended side-effects?
> >
> > Best regards
> > David Scherfgen
> > _______________________________________________
> > Maxima-discuss mailing list
> > [email protected]
> > https://lists.sourceforge.net/lists/listinfo/maxima-discuss
>
>
> _______________________________________________
> Maxima-discuss mailing list
> [email protected]
> https://lists.sourceforge.net/lists/listinfo/maxima-discuss
>

--0000000000006c08460654c90a8e
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><div class=3D"gmail_default" style=3D"font-family:georgia,=
serif;font-size:small;color:#330000">I strongly disagree with any change th=
at parses <b>a=3Db&gt;c</b>=C2=A0as <b>(a=3Db)&gt;c</b>=C2=A0or <b>a=3D(b&g=
t;c) </b>or that interprets <b>a=3Db=3Dc </b>as <b>(a=3Db)=3Dc</b>=C2=A0or =
<b>a=3D(b=3Dc)</b>.</div><div class=3D"gmail_default" style=3D"font-size:sm=
all;color:rgb(51,0,0)"><font face=3D"georgia, serif"><br></font></div><div =
class=3D"gmail_default" style=3D"font-size:small;color:rgb(51,0,0)"><font f=
ace=3D"georgia, serif">It&#39;s not that &quot;<span style=3D"background-co=
lor:transparent;color:rgb(34,34,34)">it&#39;s a bit of a stretch to figure =
out what a</span><span style=3D"background-color:transparent;color:rgb(34,3=
4,34)">=3D b &gt; c means.&quot; Of course users can &quot;figure it out&qu=
ot; in principle, but we should design according to the <a href=3D"https://=
en.wikipedia.org/wiki/Principle_of_least_astonishment">principle of least s=
urprise</a>, not the principle of &quot;only your language lawyer knows for=
 sure&quot;.</span></font></div><div class=3D"gmail_default" style=3D"font-=
size:small;color:rgb(51,0,0)"><font face=3D"georgia, serif"><span style=3D"=
background-color:transparent;color:rgb(34,34,34)"><br></span></font></div><=
div class=3D"gmail_default" style=3D"font-size:small;color:rgb(51,0,0)"><fo=
nt face=3D"georgia, serif"><span style=3D"background-color:transparent;colo=
r:rgb(34,34,34)">Old programming languages like C and PL/I parsed a=3D=3Db=
=3D=3Dc as ((a=3D=3Db)=3D=3Dc, notoriously leading to</span></font><span st=
yle=3D"background-color:transparent;color:rgb(34,34,34);font-family:georgia=
,serif">=C2=A0counterintuitive behavior and bugs. Their grammar was inherit=
ed by C++ and Javascript.=C2=A0</span></div><div class=3D"gmail_default" st=
yle=3D"font-size:small;color:rgb(51,0,0)"><span style=3D"background-color:t=
ransparent;color:rgb(34,34,34);font-family:georgia,serif"><br></span></div>=
<div class=3D"gmail_default" style=3D"font-size:small;color:rgb(51,0,0)"><s=
pan style=3D"background-color:transparent;color:rgb(34,34,34);font-family:g=
eorgia,serif">Java and C# are more strictly typed, and give a type error.=
=C2=A0</span><span style=3D"font-family:georgia,serif;background-color:tran=
sparent;color:rgb(34,34,34)">Rust and Go also forbid it and tell the user t=
o add parentheses, precisely because it is an &quot;attractive nuisance&quo=
t;.</span></div><div class=3D"gmail_default" style=3D"font-size:small;color=
:rgb(51,0,0)"><span style=3D"background-color:transparent;color:rgb(34,34,3=
4);font-family:georgia,serif"><br></span></div><div class=3D"gmail_default"=
 style=3D"font-size:small;color:rgb(51,0,0)"><span style=3D"background-colo=
r:transparent;color:rgb(34,34,34);font-family:georgia,serif">Python treats =
<b>a=3D=3Db=3D=3Dc </b>the way a mathematician would expect: as <b>(a=3D=3D=
b) and (b=3D=3Dc)</b>. For mathematicians, scientists and engineers -- our =
users -- that is the only interpretation that makes sense. Similarly, the o=
nly interpretation of <b>a&lt;b&gt;=3Dc </b>that makes sense is (</span><b =
style=3D"background-color:transparent;color:rgb(34,34,34);font-family:georg=
ia,serif">a&lt;b) and (b &gt;=3Dc)</b><span style=3D"background-color:trans=
parent;color:rgb(34,34,34);font-family:georgia,serif">=C2=A0(but only evalu=
ating each term once).</span></div><div class=3D"gmail_default" style=3D"fo=
nt-size:small"><br></div><div class=3D"gmail_default" style=3D"font-family:=
georgia,serif;font-size:small;color:#330000"><b><br></b></div></div><br><di=
v class=3D"gmail_quote gmail_quote_container"><div dir=3D"ltr" class=3D"gma=
il_attr">On Sun, Jun 21, 2026 at 1:21=E2=80=AFAM Robert Dodier &lt;<a href=
=3D"mailto:[email protected]">[email protected]</a>&gt; wrote:<=
br></div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8e=
x;border-left:1px solid rgb(204,204,204);padding-left:1ex">I guess I&#39;m =
a little late to the party. Anyway, about these changes.<br>
<br>
(1) change RPOS and LPOS for =3D and #.<br>
<br>
(2) change RBP and LBP for inequality operators.<br>
<br>
These are both OK by me. These both make it possible to parse some<br>
expressions which trigger errors now, and don&#39;t change any existing<br>
expressions which don&#39;t trigger an error (right?).<br>
<br>
It doesn&#39;t bother me that it&#39;s a bit of a stretch to figure out wha=
t a<br>
=3D b &gt; c means. By assigning binding powers, we give it an unambiguous<=
br>
representation -- it must be a =3D (b &gt; c). What does that &quot;mean&qu=
ot;? We<br>
don&#39;t need to know. If that&#39;s not suitable for some use, then we ju=
st<br>
say &quot;Don&#39;t do that.&quot; We set up the rules and let the user fig=
ure out<br>
what is meaningful to them=C2=A0 -- that is, I claim, the mathematical<br>
approach.<br>
<br>
I think (1) was somewhat less controversial than (2). Maybe if we<br>
can&#39;t get everybody on board for (2), we can still consider (1).<br>
<br>
FWIW &amp; all the best.<br>
<br>
Robert<br>
<br>
On Tue, Jun 9, 2026 at 10:59=E2=80=AFPM David Scherfgen via Maxima-discuss<=
br>
&lt;<a href=3D"mailto:[email protected]" target=3D"_blan=
k">[email protected]</a>&gt; wrote:<br>
&gt;<br>
&gt; Dear all,<br>
&gt;<br>
&gt; as Stavros noted in this bug report, Maxima fails to parse this:<br>
&gt;<br>
&gt; a # not b<br>
&gt; Error: &quot;Found LOGICAL expression where ALGEBRAIC expression expec=
ted&quot;<br>
&gt;<br>
&gt; However, a # (not b) with parentheses parses perfectly, but is printed=
 without parentheses. This means that Maxima cannot parse its own output. (=
The same for =3D.)<br>
&gt;<br>
&gt; Proposed fix:<br>
&gt; In nparse.lisp, change lpos and rpos for the =3D and # operators from =
$expr to $any. Also, increase the binding powers of=C2=A0 &lt;, &lt;=3D, &g=
t;=3D and &gt; from 80 to 85. Note that this is in accordance with most pro=
gramming languages, where &lt;, &lt;=3D, &gt;=3D and &gt; have a higher bin=
ding power than =3D=3D and !=3D, for the exact same reason of being able to=
 compare logical expressions. Maxima currently has them all the same.<br>
&gt;<br>
&gt; If we make this change, the following expressions will parse directly =
without requiring parentheses, building the exact same trees they already d=
o:<br>
&gt;<br>
&gt; a # not b<br>
&gt; a =3D not b<br>
&gt; a =3D b =3D c (parses as (a =3D b) =3D c)<br>
&gt; a &gt; b =3D c (parses as (a &gt; b) =3D c)<br>
&gt; c =3D a &gt; b (parses as c =3D (a &gt; b), wouldn&#39;t parse with th=
e original binding powers)<br>
&gt;<br>
&gt; Would this have any unintended side-effects?<br>
&gt;<br>
&gt; Best regards<br>
&gt; David Scherfgen<br>
&gt; _______________________________________________<br>
&gt; Maxima-discuss mailing list<br>
&gt; <a href=3D"mailto:[email protected]" target=3D"_bla=
nk">[email protected]</a><br>
&gt; <a href=3D"https://lists.sourceforge.net/lists/listinfo/maxima-discuss=
" rel=3D"noreferrer" target=3D"_blank">https://lists.sourceforge.net/lists/=
listinfo/maxima-discuss</a><br>
<br>
<br>
_______________________________________________<br>
Maxima-discuss mailing list<br>
<a href=3D"mailto:[email protected]" target=3D"_blank">M=
[email protected]</a><br>
<a href=3D"https://lists.sourceforge.net/lists/listinfo/maxima-discuss" rel=
=3D"noreferrer" target=3D"_blank">https://lists.sourceforge.net/lists/listi=
nfo/maxima-discuss</a><br>
</blockquote></div>

--0000000000006c08460654c90a8e--


--===============0518475629018155427==
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: inline


--===============0518475629018155427==
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

_______________________________________________
Maxima-discuss mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/maxima-discuss

--===============0518475629018155427==--