3

The problem

Consider the following script written in Maxima

$ cat main.max
foo(a) ::= block(
    if a = 0 then return(0) else return(1)
)$

bar(a) ::= block(
    return(foo(a))
)$

foo(0);
bar(0);

Executing this script yields to

$ cat main.max | maxima --very-quiet
                                       0
                                       1

The question

Isn't it supposed that calling foo by itself results the same as if it is called from another function (in this scenario, bar)?

Here there is another example

$ cat main.max
foo(a) ::= block(disp(a))$
bar(a) ::= block(foo(a))$

foo(0)$
bar(0)$
$ cat main.max | maxima --very-quiet
                                       0

                                       a

In other words: Why isn't maxima replacing the argument that is passed to bar in the foo function call which is located within bar?

Additional context

This is the version that I'm currently using

$ maxima --version
Maxima 5.43.2
gfe
  • 157
  • 5

1 Answers1

3

::= defines a function which quotes (does not evaluate) its arguments, and the return value of the function is evaluated by the caller. Such a function is conventionally called a "macro" for historical reasons.

I think you want an ordinary, argument-evaluating function, which is defined by :=. Try substituting := for ::= in your function definitions -- when I try that, I get 0 for bar(0) as expected.

Macros are useful, but in relatively narrow circumstances. I think ordinary functions are much more common than macros.

As an aside, in the functions which you have shown, block and return are unneeded. My advice is to just leave them out and make the functions more succinct and therefore more clear. E.g.

foo(a) := if a = 0 then 0 else 1;
bar(a) := foo(a);

Finally, note that = is only literal comparison, not equivalence; equivalence is tested with equal. E.g. suppose x is not otherwise defined. Then is(x = 0) yields false, but is(equal(x, 0)) yields the expression equal(x, 0). Depending on what you're doing, one or the other might be appropriate.

Robert Dodier
  • 16,905
  • 2
  • 31
  • 48