An idiosyncrasy, in how Maxima evaluates parameters.

One of the facts which I had written about Maxima in an earlier posting was, that it seems to have a number of functions, the purpose of which in English seemed to be, ‘Take a parameter or expression as input, but give me the value of this parameter.’ And what I had actually written was, that this availability of more than one similar function, could confuse me at one point in time, into not actually knowing what one specific function does. Yet, reflecting on the question outside the exercise that I was doing, brought back the gist of what that function really does. In the previous context, it was the function ‘ev()’.

A context which some other people have noticed instead, is that they’d like to use the Maxima ‘tex()’ function, in order to convert some expression into LaTeX, for another application to typeset, but in some cases the other users wanted to use previous lines of input directly, rather than to use previous lines of output. And what they found was, that the LaTeX version of what they had input, was a ‘verbatim’ block, different according to LaTeX, from what needs to be typeset as Math.

Both issues arise somewhere, because Maxima itself has been programmed in the language LISP. And, most of the time, LISP just seems to produce correct results, according to the way some people tend to interpret the meaning of the LISP function call. But in certain cases, people who either program in, or use LISP, need to form a mental, step-by-step picture of what the LISP interpreter actually does. LISP evaluates both atoms and lists, the latter of which could represent Mathematical expressions, but the former of which represent variables, in situations where their values are being referred to, and not the atom itself. At any point in the computation, LISP will actually evaluate an atom or a list, according to the same semantics. Given an atom, its value is returned, which could be another atom as easily as a list. And, given a list, to return its value means, to execute that list once.

The modern way to refer to what I’ve called an Atom here, is as a “Symbol”, which is really the name of a (LISP) Variable, that also has a value, at a given instant in time.

The way LISP generally defines lists, each of their elements may either be an atom or another list, ‘nested’ within its parent list. In LISP, lists are slightly more common, the first element of which is an atom, just because in such a case, this first element states which function is to be called on the remaining elements. But, in LISP, data is also represented as either a list or an atom, and then, in the case of a list, there is no specific need for the first element to be an atom, or one that represents a defined LISP function. (:1)

Obviously, most other Computing languages, including the one which Maxima interprets, states the function-name first, followed by one set of parentheses, around any argument-list, or around a parameter-list, in the case where the function is being defined. Infix operators are usually also represented internally, as predicates, in whatever data-format those can be represented. One major exception to this takes the form of ‘stack-based languages’, such as ‘FORTH’, and another exception exists in Assembler.

Aside: ‘Prolog’ represents both data and programming as an n-graph, meaning that in this language, each node of a tree may have an arbitrary number of branches, including zero, but additionally, an atomic predicate, stating whichever relationship between the other branches is to be satisfied.

The total number of times LISP evaluates a parameter is tightly defined, so that, if an atom represents a variable, which in turn has a list as its value, that item will result, but not be executed, unless the command is given explicitly, to evaluate the result of the previous evaluation. In LISP, the function which gives such an explicit command, is called ‘EVAL’, and the way to give that instruction, in any context where the variable ‘X’ is instantiated, is like so:

(EVAL X)

Because of the way LISP generally evaluates lists, since ‘X’ does not have a tick – a single quote – in front of it, ‘X’ was already evaluated once, before being passed to ‘EVAL’. And then, ‘EVAL’ evaluates whatever value ‘X’ had, a second time. Even according to Human thought, the fact that ‘X’ represented a value, can seem to disappear, so that Humans will also think, ‘Whatever is being referred to as X, evaluate that.’

Well, the way this works can be revealed, in certain uses of Maxima, such as, if the ‘tex()’ function is being called on an input identifier, when most of the time, it was meant to be used either, on an expression that has been parsed into a LISP structure, or, on a variable, which already evaluated to such an expression, before ‘tex()’ went to work on it.

Yet, because some people want to obtain the LaTeX representation of text, which they previously input, from Maxima, the following text-log displays where an extra step needs to be inserted, in order to accomplish this:

(Updated 7/14/2020, 22h15… )

(As of 7/14/2020, 11h30: )

To be sure, the polynomial that I used has no real roots. But for the moment I felt that a quadratic with exactly two complex roots is as good an example as any. Maxima shows that the roots are complex, by including ‘%i’ in its solutions, which is Maxima notation for the imaginary constant. When actually plotted, the following polynomial does not intercept the X-axis anywhere…

 


Starts dribbling to latex_input_1_dribble.txt (2020/7/14, 10:23:47).
NIL
(%o1)                                done
(%i2) 
eq: x^2 +x + 1 = 0;
                                 2
(%o2)                           x  + x + 1 = 0
(%i3) 
solve(eq,x);
                         sqrt(3) %i + 1      sqrt(3) %i - 1
(%o3)             [x = - --------------, x = --------------]
                               2                   2
(%i4) 
tex(%o3);
$$\left[ x=-{{\sqrt{3}\,i+1}\over{2}} , x={{\sqrt{3}\,i-1}\over{2}}
  \right] \leqno{\tt (\%o3)}$$
(%o4)                               (\%o3)
(%i5) 
[x=-(sqrt(3)*%i+1)/2,x=(sqrt(3)*%i-1)/2];
                      (- sqrt(3) %i) - 1      sqrt(3) %i - 1
(%o5)            [x = ------------------, x = --------------]
                              2                     2
(%i6) 
tex(%i5);
\begin{verbatim}
(%i5)[x = ((-sqrt(3)*%i)-1)/2,x = (sqrt(3)*%i-1)/2];
\end{verbatim}

(%o6)                                (%i5)
(%i7) 
/*
Why did this happen?

Because, Maxima has consistently been programmed, so that,
When an output identifier has been given, it is
not only evaluated to the line of output, but that line of
output is evaluated a second time, to reveal 'its meaning'.
I.e., Its text is evaluated, in order to reveal a parsed
LISP structure of symbols.

Alternatively, it could also be, that Maxima only
evaluates an output identifier once, leading directly to
the LISP structure of symbols.

In contrast, input identifiers are only evaluated once,
to reveal the literal text that was input.

Maxima has more than one syntax, which mean 'Evaluate the actual
parameter, but, evaluate the result an additional time.'

First, precede with a tick (a single quote) twice:
*/
tex(''%i5);
$$\left[ x={{-\sqrt{3}\,i-1}\over{2}} , x={{\sqrt{3}\,i-1}\over{2}}
  \right] $$
(%o7)                                false
(%i8) 
/*
Secondly, use the apply() function with an argument list:
*/
apply('tex,[%i5]);
$$\left[ x={{-\sqrt{3}\,i-1}\over{2}} , x={{\sqrt{3}\,i-1}\over{2}}
  \right] $$
(%o8)                                false
(%i9) 
/*
Actually, to have put a tick in front of the
function name was pedantic. In most computing languages,
to state the function name without any parentheses, already
evokes the function, and not, a function-call.

Thirdly, use the ev() function:
*/
tex(ev(%i5));
$$\left[ x={{-\sqrt{3}\,i-1}\over{2}} , x={{\sqrt{3}\,i-1}\over{2}}
  \right] $$
(%o9)                                false
(%i10) 
/*
What this last function does is, evaluate
the argument as usual, but then, treat the result as
though it was a typed-in command, to be evaluated for
a second time.

Also, the use of $$ in LaTeX is deprecated.
Use \[ and \] instead. The actual use of $$ or $
requires that there be no space on
the right, and then on the left, of $$ or $,
to denote either symbol as beginning or ending
a sequence of LaTeX code.

Some applications recognize \( and \)
as a replacement for $.
*/
quit();

 

Now, what some people might ask themselves could be, ‘Why did Dirk post a text-dribble, of a Maxima console session, when usually, Dirk posts Maxima usage, that has been typeset using wxMaxima?’ ‘wxMaxima’ is a graphical front-end for Maxima, and its main methods of exporting a worksheet rely on converting it into LaTeX each time, so that either a PDF File, or an HTML Page results, when ‘pdflatex’ or ‘latex’ is used on the resulting output.

What I’ve discovered the hard way is the fact, that wxMaxima will introduce certain errors, if the output from Maxima already was LaTeX, but if that LaTeX code needs to be escaped as such, as part of a larger LaTeX document. Further, the way wxMaxima stylizes the Maxima output as belonging to the same Cell each time, as one input, complicated LaTeX results, into which a block as follows cannot be inserted naively:

 


\begin{verbatim}

(...)

\end{verbatim}

 

 


 

Under ‘Plasma 5 / KDE’, there is also the graphical front-end named ‘Cantor’, and the question might be pursued, as to whether Cantor has the same bug. But the answer to this question would become irrelevant, if the goal is to perform some sort of operation on an output- or an input- identifier, because within Cantor, the lines of Maxima code do not have those identifiers. When using Cantor, the user must assign certain results to variables, if he or she is going to reuse those more than once.

Pursuing this line of questioning with the application named ‘Cantor’ reveals, that this graphical front-end is also not meant to have the ‘tex()’ function-call given directly to Maxima. Doing so causes some slight corruption to the session. However, when the user has entered their input to Cantor, resulting in output, which has been grouped as belonging to the same Cell, then, what the user may do is, to right-click on the actual output, and then to left-click on “Show Code” within the resulting context menu. What this will do is, to display the LaTeX which Cantor itself is basing the typeset equation on. After that, a right-click followed by a left-click on “Show Rendered” will toggle the output back to its typeset form.

But, my question was next, ‘How does Cantor export the worksheet to a single LaTeX File, if it contains both the rendered and the encoded form of some outputs?’

The answer is that, when instructed to do so, Cantor really still does not distinguish between these two forms correctly. However, the LaTeX which Cantor exports to is much simpler in syntax (than what wxMaxima exported), so that the user editing said LaTeX, is much more likely, to allow either the Rendered or the Code form of a Cell’s output to end up, as part of the eventual document…

The user may need to enable JavaScript, from my site, as well as from MathJax.org, to be able to view the following, simplistic example:



 

(Update 7/14/2020, 22h15: )

1:)

The reader would be correct in the knowledge, that the quick summary of LISP in this posting, is highly incomplete, and that it was based on an almost ancient form of LISP. Modern LISP has additional features, that affect how actual lists are evaluated, before any user-defined function is applied to them, and there may be more, important features, omitted below:

  • Keyword parameters, as opposed to positional parameters,
  • Namespaces,
  • Macros,
  • Object-Oriented features…

Keyword parameters can be stated in the function definition, after (positional) ‘required’, ‘&optional’ and ‘&rest’ parameters, as part of the same list, and they come after the keyword ‘&key’.

When a function with keyword parameters is called, the keyword occupies one position in the list, and the value to be passed in, is at the following position. In order for the keywords belonging to a function call actually to be associated by the keywords in the function definition, they need to have a colon in front of them in the function call (without any space), and, namespaces need to be implemented, such that the colon associates them with the keywords having the same name in the function definition…

What, exactly, Macros do, follows fromĀ  deprecated feature of LISP, that used to be referred to as an ‘NLAMBDA’ expression. By default, most of the behaviour of LISP follows ‘LAMBDA’ calculus. But, even early in the evolution of this language, the fact was recognized that, in order for it to be complete, a parallel way must exist to define ~functions~, without the supposition that arguments not preceded individually by a tick, should be evaluated the way I described the variable above as being so, before being passed to the function ‘EVAL’. Back in the early days, this was provided as an ‘NLAMBDA’ expression.

The developers of LISP decided at some point, that they could better extend the language by adding Macros. And what those essentially imply is, that during a first pass, the argument list is not evaluated when being passed in as parameters. The Macro then builds a list, with the understanding by the programmer, that whatever list it built, is eventually evaluated, in what amounts to an unstated, second pass (both passes resulting from the evaluation of the macro).

But, this posting was not mainly intended to explain LISP…


 

 

(Update 7/14/2020, 22h15: )

Contrarily to what I had previously believed, the construction of the list which is defined by a LISP Macro, takes place at the compile-time of the function it occurs in, while the evaluation of the list that results, takes place at run-time…

Dirk

 

Print Friendly, PDF & Email

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>