Re: Very poor Lisp performance / about Mathematica




> Richard Fateman wrote:
>> People seem to be taking on faith that Jon is correctly
>> characterizing Mathematica.

For the sake of argument, yes. I'm assuming he's correctly reporting
his personal experience interacting with Mathematica.

However, I have read your critique on Mathematica and have discussed
it with friends that are in a position to know about it. I don't
assume that Jon has the language design and semantics experience to
see the obvious flaws. I expect he has unconciously developed the
panglossian view that Mathematica is the best of all possible computer
algebra systems and that whatever flaws it has are justifiable because
all software has bugs and idiosyncracies.

>> In fact Mathematica is not even deterministic, and its results
>> depend on peculiarities like the virtual page shared by a variable
>> with other variables to determine the execution of rules.

> Jon Harrop <usenet@xxxxxxxxxxxxxx> writes:
>
> Yes, like most other languages, Mathematica has undefined behaviour under
> certain circumstances. The same applies to the order of evaluation of
> function arguments in OCaml, for example.

These are *completely* different kinds of problems. In OCaml
(presumably), the order of evaluation is not specified, but the
behavior is not undefined! OCaml is call-by-value, so the evaluation
*must* occur before the function is called. I haven't studied OCaml,
but I assume that these properties hold:

Argument evaluation must be consistent with *some* order.

Order of argument evaluation must not be detectable by pure
functional programs.

Writing code that depends on order of evaluation is strongly
discouraged.

Even in languages that have well-defined order of evaluation, it is
considered poor style to use that order to implicitly sequence
operations.

It is easy and straightforward to avoid order of evaluation
dependencies.


Does one have control over what virtual pages a variable occupies in
Mathematica? Can one control grouping so that two variables are
required or prohibited from sharing? Is it easy and straightforward
to avoid unexpected dependencies?

>> There are so many bad things about Mathematica's
>> syntax and semantics that most people trying to use
>> it will only experience a small subset of the possible
>> flaws.
>
> That is true for many complicated languages.

Unfortunately so, but it need not be the case. There are certain
principles of language design that were developed *years* ago (some of
the principles are *thousands* of years old) that have withstood the
test of time. The kinds of flaws that come from ignorance or
deliberate rejection of these principles are qualitatively different
from the ones that come from the unavoidable (but correctable) bugs in
the implementation. Mathematica's problems are of the first kind.

>> I view as particularly damning the fact that the
>> underlying algorithms are typically thousands and thousands
>> of lines of code in C (I think "objective C").
>
> Actually they're not...
>
>> Mathematica programmers by and large do not use functions.
>> They think they are defining functions but they are defining
>> rules by f[x_]:= ....;
>
> They are defining a mapping. That is a function.

There are BIG differences between mathematical functions and rewrite
rules. Even a rewrite rule that defines a function may not be the
function you think it is or expect. Lisp hackers, computer language
theorists, and especially computer language and computer algebra
theorists know that function definition is one of the trickiest parts
of semantics.

>> As for whether it makes an AST at all -- well, along the
>> way the parser does that, but Mathematica doesn't stop
>> there. As mentioned previously, you need to intersperse
>> Hold, HoldAll, Release, etc. in key places.
>
> Just as you use quote in a Lisp macro.

Here is a prime example.

Mathematica `evaluates' an expression by iteratively applying rewrite
rules until it reaches a fixed point (until `nothing changes').
This sounds like it may be a reasonable, if unorthodox, choice for
evaluation semantics, and newbies often think that Lisp or Scheme
works this way.

Lisp's `eval' routine takes an expression as list structure and
determines what value that expression means. It *may* be the case
that the value is itself a list structure that could be interpreted as
an expression. This is of no consequence to eval. The result of
evaluation is not itself iteratively evaluated.

Both Lisp and Mathematica have a mechanism for quoting, that is, for
embedding structure that superficially appears to be an expression.
In Lisp, this is QUOTE, and it's effect is simple: the value of a
QUOTE expression is the object quoted.

In Mathematica, however, this would not work. The value of a HOLD
expression cannot be the object that is held because *that* object
might be an expression (and thus get fed back into the Mathematica
evaluator). Instead, the value of a HOLD expression is the HOLD
expression itself.

There is a subtle difference: Lisp can embed *any* object in code
through use of QUOTE. Mathematica cannot embed objects in code, but
it can almost fake it because HOLD expressions end up being constant.
You may think this is a difference that makes no difference, but it
shows up when you write higher-order macros. A higher-order macro has
two stages of parameterization: the first occurs when you use the
higher-order macro to define another macro, the second occurs when you
use the macro that is defined. At which stage do you expand the
parameters that are introduced at stage 1? For some macros, those
parameters ought to be expanded at stage 1, but for others it might be
stage 2 (it could be both!). In Lisp, it is relatively
straightforward to control the stage at which a macro parameter is
expanded through use of the appropriate level of nesting of QUOTED
structure. At each stage of expansion, QUOTED list structure becomes
a literal expression for the next stage. In Mathematica, however, a
HOLD expression remains unchanged until you RELEASE it, so you can
*defer* evaluation, but you can't easily *undefer* it.

(In Lisp, QUOTE and EVAL respectively take you one step up and down
the syntactic reflect/reify tower. At each meta-level, additional
quotes take you further up, and additional EVALs take you further
down. In Mathematica, HOLD takes you a step up, but RELEASE takes you
*all the way down* to the bottom level.)

This is an example of being ignorant about language design principles.
If you have reflection in a language, you should make sure that each
reflective operator has a corresponding reification operator that
*exactly* undoes that reflection. If you don't, it will be either
painful or impossible to *use* the reflection in non-trivial ways.
Mathematica chose to ignore this principle, and guess what happens.

>> I think people are being inexplicably kind to spend
>> so much time to educate Jon H. Comp.lang.lisp has a long
>> tradition of having a short fuse. :) Maybe JH should get
>> a troll award.

I guess I don't think he's a lost cause, yet.

~jrm
.



Relevant Pages