Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

scope all wrong? in Mathematica 4.1

11 views
Skip to first unread message

Richard Fateman

unread,
Dec 5, 2001, 7:04:13 AM12/5/01
to
Consider the mathematica definition

rr[x_] := Block[{x}, x = 5; Print["x is ", x]]

what do you expect here?

rr[z] --> x is 5 is printed.
but you might not expect

rr[4] --> "Block::"lvsym": "Local variable specification{4} contains 4
which is not a symbol or an assignment to a symbol."

If you use Module instead of Block, you get
the same.

However,
Block[{x = 4}, Block[{x}, x = 5; Print["x is ", x]]]

prints x is 5

Using pattern matching for
substituting 4 for x in rr[4] even when x is bound seems
to be counter to what most programming language designers
would expect.

Now look at

uu[x_?((x = 5; Print["x is ", x]; True) &)] := x

Usually when one defines a program, nothing is printed.
Here, we get
x is 5
5
x is 5

If we do this:
x =400
uu[70]
x is 5 printed
the value returned is 70
and the global x is 5.

Try this:
Module[{x}, uu[x_?((x = 5; Print["x is ", x]; True) &)] := x;
Print["in Module, x is " , x]]

The expectation in a system supporting lexical scope
with Module
is that no use of x inside the module would escape.
But it does. The global x is set to 5.


The reason this all came up is in correspondence suggesting
that programs in one computer algebra system could be
translated into another. If systems are semantically
"surprising", it is more difficult. I wonder how much
of mathematica internally depends on wrong scope, or how
much of the code is susceptible to bugs because of unexpected
capture of names. (I suspect that this has caused a proliferation
of package names e.g. MySecretNameSpace`x in Mathematica
routines).

RJF


Allan Hayes

unread,
Dec 7, 2001, 6:23:05 AM12/7/01
to
Richard,

Richard,
I have found a feature amongst your examples that came as a surprise: the
way in which SetDelayed is evaluated. The outputs from your examples seem
to be consequences of this and the standard evaluation process - I'll come
back to them later {in the notebook below].
My understanding was that h[e]:=r evaluates h then e to given h1[e1]:=r;
then stores the rule for this (without looking for rules that might change
it as a whole); it then returns the value Null.
It seems however that more is going on: the rule is stored is as expected
from the above, but it seems that after making later rules; some kind of
evaluation is triggered, as though trying to evaluate the left sides using
the other rules (the rules themselves are not altered). These evaluations
may be due to working out the order in which to store or replace existing
ones. It seems to me that it would be better if these evaluations were done
in private. However, the same kind of evaluations will occur when the rules
are used, and any unwanted assignments can be avoided in both circumstances
by suitable localisation of symbols inside tests and conditions, though
unwanted printing would still occur.

Please see the notebook below for details.

--
Allan

---------------------
Allan Hayes
Mathematica Training and Consulting
Leicester UK
www.haystack.demon.co.uk
h...@haystack.demon.co.uk
Voice: +44 (0)116 271 4198
Fax: +44 (0)870 164 0565


(************** Content-type: application/mathematica **************

Mathematica-Compatible Notebook

This notebook can be used with any Mathematica-compatible
application, such as Mathematica, MathReader or Publicon. The data
for the notebook starts with the line containing stars above.

To get the notebook into a Mathematica-compatible application, do
one of the following:

* Save the data starting with the line of stars above into a file
with a name ending in .nb, then open the file inside the
application;

* Copy the data starting with the line of stars above to the
clipboard, then use the Paste menu command inside the application.

Data for notebooks contains only printable 7-bit ASCII and can be
sent directly in email or through ftp in text mode. Newlines can be
CR, LF or CRLF (Unix, Macintosh or MS-DOS style).

NOTE: If you modify the data for this notebook not in a Mathematica-
compatible application, you must delete the line below containing
the word CacheID, otherwise Mathematica-compatible applications may
try to use invalid cache data.

For more information on notebooks and Mathematica-compatible
applications, contact Wolfram Research:
web: http://www.wolfram.com
email: in...@wolfram.com
phone: +1-217-398-0700 (U.S.)

Notebook reader applications are available free of charge from
Wolfram Research.
*******************************************************************)

(*CacheID: 232*)


(*NotebookFileLineBreakTest
NotebookFileLineBreakTest*)
(*NotebookOptionsPosition[ 17734, 662]*)
(*NotebookOutlinePosition[ 19618, 717]*)
(* CellTagsIndexPosition[ 19362, 707]*)
(*WindowFrame->Normal*)

Notebook[{
Cell["\<\
Richard,
I have found a feature amongst your examples that came as a surprise: \
the way in which SetDelayed is evaluated. The outputs from your \
examples seem to be consequences of this and the standard evaluation \
process - I'll come back to them later.
My understanding was that h[e]:=r evaluates h then e to given \
h1[e1]:=r; then stores the rule for this (without looking for rules \
that might change it as a whole); it then returns the value Null.
It seems however that more is going on: the rule is stored is as \
expected from the above, but it seems that after making later rules; \
some kind of evaluation is triggered, as though trying to evaluate \
the left sides using the other rules (the rules themselves are not \
altered). These evaluations may be due to working out the order in \
which to store or replace existing ones. It seems to me that it \
would be better if these evaluations were done in private. However, \
the same kind of evaluations will occur when the rules are used, and \
any unwanted assignments can be avoided in both circumstances by \
suitable localisation of symbols inside tests and conditions, though \
unwanted printing would still occur.
Here are some examples\
\>", "Text"],

Cell[CellGroupData[{

Cell["Extra evaluations", "Section"],

Cell[BoxData[
\(a = 88; b = 99;\)], "Input"],

Cell["Define a one-place function for uu:", "Text"],

Cell[BoxData[
StyleBox[\(uu[_?\((\(({a = 3, b, Print[F[a, #]]};
True)\) &)\)]\ := \ 2\),
FormatType->StandardForm]], "Input"],

Cell["The value of a is not changed", "Text"],

Cell[CellGroupData[{

Cell[BoxData[
\(a\)], "Input"],

Cell[BoxData[
\(88\)], "Output"]
}, Open ]],

Cell["The stored rule is as expected", "Text"],

Cell[CellGroupData[{

Cell[BoxData[
\(Definition[uu] // InputForm\)], "Input"],

Cell["uu[_?(({a = 3, b, Print[F[a, #1]]}; True) & )] := 2", "Output"]
}, Open ]],

Cell[TextData[{
"Now, define another one-place function for ",
StyleBox["uu",
FontFamily->"Courier"]
}], "Text"],

Cell[CellGroupData[{

Cell[BoxData[
StyleBox[\(uu[
y_ /; \(({b = 4, a, Print[G[b, y]]}; True)\)]\ := \ 2\),
FormatType->StandardForm]], "Input"],

Cell[BoxData[
\(F[3, y_ /; \(({b = 4, a, Print[G[b, y]]}; True)\)]\)], "Print"],

Cell[BoxData[
\(G[4, _?\((\(({a = 3, b, Print[F[a, #1]]};
True)\) &)\)]\)], "Print"]
}, Open ]],

Cell[TextData[{
"The printouts indicate the extra evaluation that I referred to, as \
do the changes in the value of ",
StyleBox["a",
FontFamily->"Courier"],
" and ",
StyleBox["b",
FontFamily->"Courier"],
" shown below"
}], "Text"],

Cell[CellGroupData[{

Cell[BoxData[
\({a, b}\)], "Input"],

Cell[BoxData[
\({3, 4}\)], "Output"]
}, Open ]],

Cell["\<\
However, the stored rules are still as we expected - unaffected by \
the extra evaluations:\
\>", "Text"],

Cell[CellGroupData[{

Cell[BoxData[
\(Definition[uu] // InputForm\)], "Input"],

Cell["\<\
uu[_?(({a = 3, b, Print[F[a, #1]]}; True) & )] := 2

uu[y_ /; ({b = 4, a, Print[G[b, y]]}; True)] := 2\
\>", "Output"]
}, Open ]],

Cell[TextData[{
"Even defining a simple one-place function for ",
StyleBox["uu",
FontFamily->"Courier"],
" (without condition or test)\ntriggers the extra evaluations"
}], "Text"],

Cell[CellGroupData[{

Cell[BoxData[
StyleBox[\(uu[z_]\ := \ 2\),
FormatType->StandardForm]], "Input"],

Cell[BoxData[
\(F[3, z_]\)], "Print"],

Cell[BoxData[
\(G[4, z_]\)], "Print"]
}, Open ]]
}, Closed]],

Cell[CellGroupData[{

Cell["Outputs in your posting", "Section"],

Cell["\<\
I have modified your examples slightly to make some points - please \
allow for these in interpreting the quotes from your posting.\
\>", "Text"],

Cell[BoxData[
\(Clear["\<`*\>"]\)], "Input"],

Cell["> Consider the Mathematica definition", "Text"],

Cell[BoxData[
\(rr[x_] := Block[{x}, x = 5; Print["\<x is \>", x]]\)], "Input"],

Cell[CellGroupData[{

Cell[BoxData[
\(rr[4]\)], "Input"],

Cell[BoxData[
\(Block::"lvsym" \(\(:\)\(\ \)\)
"Local variable specification \!\({4}\) contains \!\(4\) which \
is not a symbol or an assignment to a symbol."\)], "Message"],

Cell[BoxData[
\(Block[{4}, 4 = 5; Print["x is ", 4]]\)], "Output"]
}, Open ]],

Cell["\<\
This is nothing to do with Block: it occurs because passing (5) \
across rule is never blocked, though it does cause re-naming in \
scoping constructs, for example\
\>", "Text"],

Cell[BoxData[
\(f[x_] := \ Function[x, x + y]\)], "Input"],

Cell[CellGroupData[{

Cell[BoxData[
\(f[4]\)], "Input"],

Cell[BoxData[
\(Function::"flpar" \(\(:\)\(\ \)\)
"Parameter specification \!\(4\) in \!\(Function[\(\(4, \(\(4 + \
y\)\)\)\)]\) should be a symbol or a list of symbols."\)], "Message"],

Cell[BoxData[
\(Function[4, 4 + y]\)], "Output"]
}, Open ]],

Cell[BoxData[
\(f[y_] := \ Function[x, x + y]\)], "Input"],

Cell[CellGroupData[{

Cell[BoxData[
\(f[4]\)], "Input"],

Cell[BoxData[
\(Function[x$, x$ + 4]\)], "Output"]
}, Open ]],

Cell[">If you use Module instead of Block, you get the same.", "Text"],

Cell["Yes, for the same reason.", "Text"],

Cell[">However,", "Text"],

Cell[CellGroupData[{

Cell[BoxData[
\(Block[{x = 4},
Block[{x}, x = 5; Print["\<x is \>", x]]]\)], "Input"],

Cell[BoxData[
InterpretationBox[\("x is "\[InvisibleSpace]5\),
SequenceForm[ "x is ", 5],
Editable->False]], "Print"]
}, Open ]],

Cell["\<\
This is because inside the inner Block x is temporarily set the \
value 5. No passing of values across rules is involved. The mechanism \
is to do with the use of temporary rules, not passing.\
\>", "Text"],

Cell["\<\


>Using pattern matching for
>substituting 4 for x in rr[4] even when x is bound seems
>to be counter to what most programming language designers
>would expect.

This general point is better made with the example above that uses \
Function: Block does not bind - as remarked earlier it effect is via \
temporay rules and ordinary evaluation.

>Now look at\
\>", "Text"],

Cell[BoxData[
\(uu[x_?\((\((x = 5; Print["\<x is \>", A[x]]; True)\) &)\)] :=
x\)], "Input"],

Cell["\<\


>Usually when one defines a program, nothing is printed.
>Here, we get
>x is 5
>5
>x is 5

As you see, I did not get anything.\
\>", "Text"],

Cell[">If we do this:", "Text"],

Cell[CellGroupData[{

Cell[BoxData[{
\(\(x = 400;\)\), "\n",
\(uu[70]\), "\[IndentingNewLine]",
\(x\)}], "Input"],

Cell[BoxData[
InterpretationBox[\("x is "\[InvisibleSpace]A[5]\),
SequenceForm[ "x is ",
A[ 5]],
Editable->False]], "Print"],

Cell[BoxData[
\(70\)], "Output"],

Cell[BoxData[
\(5\)], "Output"]
}, Open ]],

Cell["\<\


>x is 5 printed
>the value returned is 70
>and the global x is 5.

Yes: this is what I would expect from the test being evaluated - \
nothing to do with the \"extra evaluations\" observed in the first \
section.

>Try this\
\>", "Text"],

Cell["Before trying note that there is now a rule stored for uu", \
"Text"],

Cell[CellGroupData[{

Cell[BoxData[
\(?? uu\)], "Input"],

Cell["Global`uu", "Print",
CellTags->"Info3216631205-4665998"],

Cell[BoxData[
InterpretationBox[GridBox[{
{GridBox[{
{\(uu[
x_?\((\((x = 5; Print["x is ", A[x]];
True)\) &)\)] := x\)}
},
GridBaseline->{Baseline, {1, 1}},
ColumnWidths->0.999,
ColumnAlignments->{Left}]}
},
GridBaseline->{Baseline, {1, 1}},
ColumnAlignments->{Left}],
Definition[ "uu"],
Editable->False]], "Print",
CellTags->"Info3216631205-4665998"]
}, Open ]],

Cell["\<\
I also reset x to 100 and change your 5 to 6 , resmake a point about \
assignment to global variables; and add an extra line, x to test \
this..\
\>", "Text"],

Cell[CellGroupData[{

Cell[BoxData[{
\(\(x = 100;\)\), "\[IndentingNewLine]",
\(Module[{x}, \[IndentingNewLine]uu[
x_?\((\((x = 6; Print["\<x is \>", B[x]]; True)\) &)\)] :=
x; \[IndentingNewLine]Print["\<in Module, x is \>",
x]\[IndentingNewLine]]\), "\[IndentingNewLine]",
\(x\)}], "Input"],

Cell[BoxData[
InterpretationBox[\("x is "\[InvisibleSpace]A[5]\),
SequenceForm[ "x is ",
A[ 5]],
Editable->False]], "Print"],

Cell[BoxData[
InterpretationBox[\("x is "\[InvisibleSpace]B[6]\),
SequenceForm[ "x is ",
B[ 6]],
Editable->False]], "Print"],

Cell[BoxData[
InterpretationBox[\("in Module, x is "\[InvisibleSpace]6\),
SequenceForm[ "in Module, x is ", 6],
Editable->False]], "Print"],

Cell[BoxData[
\(5\)], "Output"]
}, Open ]],

Cell[TextData[{
"Module renames x in {x} and the free x in its body to x$nn; the \
rule defined inside Module is made then the \"extra evaluations\" \
kick in: the left side of the new rule attempts to use the \
pre-existing rule, which results in x being set to 5 and the printout \
",
StyleBox["x is A[5]",
FontFamily->"Courier"],
"; then trhe left side ot the pre-existing rule attempts to use \
the new rule, which results in x$nn being set to 6 and the printout \
x=6 (not x$nn since we have the string \"x is \"). A consequence is \
that without the pre-existing rule, x would not be assigned a new \
value.\nWe now have two rules for uu. Notice that in the one made \
inside Module, x in x_ and on the right side are bound and so are \
not renamed."
}], "Text"],

Cell[CellGroupData[{

Cell[BoxData[
\(\(?uu\)\)], "Input"],

Cell["Global`uu", "Print",
CellTags->"Info3216631214-9056274"],

Cell[BoxData[
InterpretationBox[GridBox[{
{GridBox[{
{\(uu[
x_?\((\((x = 5; Print["x is ", A[x]];
True)\) &)\)] := x\)},
{" "},
{\(uu[
x_?\((\((x$19 = 6; Print["x is ", B[x$19]];
True)\) &)\)] := x\)}
},
GridBaseline->{Baseline, {1, 1}},
ColumnWidths->0.999,
ColumnAlignments->{Left}]}
},
GridBaseline->{Baseline, {1, 1}},
ColumnAlignments->{Left}],
Definition[ "uu"],
Editable->False]], "Print",
CellTags->"Info3216631214-9056274"]
}, Open ]],

Cell["\<\
As we expect from the first section, printouts pile up even if we \
just repeat the evaluation of the module\
\>", "Text"],

Cell[CellGroupData[{

Cell[BoxData[
\(Module[{x}, \[IndentingNewLine]uu[
x_?\((\((x = 6; Print["\<x is \>", C[x]]; True)\) &)\)] :=
x; \[IndentingNewLine]Print["\<in Module, x is \>",
x]\[IndentingNewLine]]\)], "Input"],

Cell[BoxData[
InterpretationBox[\("x is "\[InvisibleSpace]A[5]\),
SequenceForm[ "x is ",
A[ 5]],
Editable->False]], "Print"],

Cell[BoxData[
InterpretationBox[\("x is "\[InvisibleSpace]6\),
SequenceForm[ "x is ", 6],
Editable->False]], "Print"],

Cell[BoxData[
InterpretationBox[\("x is "\[InvisibleSpace]B[6]\),
SequenceForm[ "x is ",
B[ 6]],
Editable->False]], "Print"],

Cell[BoxData[
InterpretationBox[\("x is "\[InvisibleSpace]6\),
SequenceForm[ "x is ", 6],
Editable->False]], "Print"],

Cell[BoxData[
InterpretationBox[\("in Module, x is "\[InvisibleSpace]6\),
SequenceForm[ "in Module, x is ", 6],
Editable->False]], "Print"]
}, Open ]],

Cell[CellGroupData[{

Cell[BoxData[
\(\(?uu\)\)], "Input"],

Cell["Global`uu", "Print",
CellTags->"Info3216631221-7238232"],

Cell[BoxData[
InterpretationBox[GridBox[{
{GridBox[{
{\(uu[
x_?\((\((x = 5; Print["x is ", A[x]];
True)\) &)\)] := x\)},
{" "},
{\(uu[
x_?\((\((x$19 = 6; Print["x is ", B[x$19]];
True)\) &)\)] := x\)},
{" "},
{\(uu[
x_?\((\((x$23 = 6; Print["x is ", x$23];
True)\) &)\)] := x\)}
},
GridBaseline->{Baseline, {1, 1}},
ColumnWidths->0.999,
ColumnAlignments->{Left}]}
},
GridBaseline->{Baseline, {1, 1}},
ColumnAlignments->{Left}],
Definition[ "uu"],
Editable->False]], "Print",
CellTags->"Info3216631221-7238232"]
}, Open ]],

Cell["\<\

>The expectation in a system supporting lexical scope
>with Module
>is that no use of x inside the module would escape.
>But it does. The global x is set to 5.

The change in x is because of the pre-existing rule, as noted above.
But with no such rule another feature emerges:
Check:\
\>", "Text"],

Cell[CellGroupData[{

Cell[BoxData[{
\(Clear[uu]\), "\[IndentingNewLine]",
\(\(x = 100;\)\), "\[IndentingNewLine]",
\(Module[{x}, \[IndentingNewLine]uu[
x_?\((\((x = 6; Print["\<x is \>", x]; True)\) &)\)] :=
x; \[IndentingNewLine]Print["\<in Module, x is \>",
x]\[IndentingNewLine]]\), "\[IndentingNewLine]",
\(x\)}], "Input"],

Cell[BoxData[
InterpretationBox[\("in Module, x is "\[InvisibleSpace]x$27\),
SequenceForm[ "in Module, x is ", x$27],
Editable->False]], "Print"],

Cell[BoxData[
\(100\)], "Output"]
}, Open ]],

Cell["\<\
There have been no extra evaluations, because there are no \
pre-existing rules:\
\>", "Text"],

Cell[CellGroupData[{

Cell[BoxData[
\(x$67\)], "Input"],

Cell[BoxData[
\(x$67\)], "Output"]
}, Open ]],

Cell["The rule defined in Module is", "Text"],

Cell[CellGroupData[{

Cell[BoxData[
\(\(?uu\)\)], "Input"],

Cell["Global`uu", "Print",
CellTags->"Info3216631226-7466759"],

Cell[BoxData[
InterpretationBox[GridBox[{
{GridBox[{
{\(uu[
x_?\((\((x$27 = 6; Print["x is ", x$27];
True)\) &)\)] := x\)}
},
GridBaseline->{Baseline, {1, 1}},
ColumnWidths->0.999,
ColumnAlignments->{Left}]}
},
GridBaseline->{Baseline, {1, 1}},
ColumnAlignments->{Left}],
Definition[ "uu"],
Editable->False]], "Print",
CellTags->"Info3216631226-7466759"]
}, Open ]],

Cell["\<\
Now from earlier we would expect a new rule to be stored if we repeat \
the evaluation of the module; but it seems to have been deleted early \
on in the evaluation\
\>", "Text"],

Cell[CellGroupData[{

Cell[BoxData[{
\(Clear[uu]\), "\[IndentingNewLine]",
\(\(x = 100;\)\), "\[IndentingNewLine]",
\(Module[{x}, \[IndentingNewLine]uu[
x_?\((\((x = 6; Print["\<x is \>", x]; True)\) &)\)] :=
x; \[IndentingNewLine]Print["\<in Module, x is \>",
x]\[IndentingNewLine]]\), "\[IndentingNewLine]",
\(x\)}], "Input"],

Cell[BoxData[
InterpretationBox[\("in Module, x is "\[InvisibleSpace]x$31\),
SequenceForm[ "in Module, x is ", x$31],
Editable->False]], "Print"],

Cell[BoxData[
\(100\)], "Output"]
}, Open ]],

Cell[CellGroupData[{

Cell[BoxData[
\(\(?uu\)\)], "Input"],

Cell["Global`uu", "Print",
CellTags->"Info3216631234-9152500"],

Cell[BoxData[
InterpretationBox[GridBox[{
{GridBox[{
{\(uu[
x_?\((\((x$31 = 6; Print["x is ", x$31];
True)\) &)\)] := x\)}
},
GridBaseline->{Baseline, {1, 1}},
ColumnWidths->0.999,
ColumnAlignments->{Left}]}
},
GridBaseline->{Baseline, {1, 1}},
ColumnAlignments->{Left}],
Definition[ "uu"],
Editable->False]], "Print",
CellTags->"Info3216631234-9152500"]
}, Open ]],

Cell[CellGroupData[{

Cell[BoxData[
\(x$67\)], "Input"],

Cell[BoxData[
\(x$67\)], "Output"]
}, Open ]]
}, Closed]]
},
FrontEndVersion->"4.1 for Microsoft Windows",
ScreenRectangle->{{0, 1024}, {0, 695}},
WindowSize->{498, 598},
WindowMargins->{{-52, Automatic}, {Automatic, 11}},
ShowSelection->True
]

(*******************************************************************
Cached data follows. If you edit this Notebook file directly, not
using Mathematica, you must remove the line containing CacheID at
the top of the file. The cache data will then be recreated when
you save this file from within Mathematica.
*******************************************************************)

(*CellTagsOutline
CellTagsIndex->{
"Info3216631205-4665998"->{
Cell[8877, 346, 64, 1, 25, "Print",
CellTags->"Info3216631205-4665998"],
Cell[8944, 349, 532, 15, 25, "Print",
CellTags->"Info3216631205-4665998"]},
"Info3216631214-9056274"->{
Cell[11361, 426, 64, 1, 25, "Print",
CellTags->"Info3216631214-9056274"],
Cell[11428, 429, 698, 19, 58, "Print",
CellTags->"Info3216631214-9056274"]},
"Info3216631221-7238232"->{
Cell[13341, 497, 64, 1, 25, "Print",
CellTags->"Info3216631221-7238232"],
Cell[13408, 500, 861, 23, 91, "Print",
CellTags->"Info3216631221-7238232"]},
"Info3216631226-7466759"->{
Cell[15523, 579, 64, 1, 25, "Print",
CellTags->"Info3216631226-7466759"],
Cell[15590, 582, 535, 15, 25, "Print",
CellTags->"Info3216631226-7466759"]},
"Info3216631234-9152500"->{
Cell[16989, 631, 64, 1, 25, "Print",
CellTags->"Info3216631234-9152500"],
Cell[17056, 634, 535, 15, 25, "Print",
CellTags->"Info3216631234-9152500"]}
}
*)

(*CellTagsIndex
CellTagsIndex->{
{"Info3216631205-4665998", 18364, 678},
{"Info3216631214-9056274", 18563, 683},
{"Info3216631221-7238232", 18764, 688},
{"Info3216631226-7466759", 18965, 693},
{"Info3216631234-9152500", 19166, 698}
}
*)

(*NotebookFileOutline
Notebook[{
Cell[1705, 50, 1236, 21, 318, "Text"],

Cell[CellGroupData[{
Cell[2966, 75, 36, 0, 59, "Section"],
Cell[3005, 77, 48, 1, 30, "Input"],
Cell[3056, 80, 51, 0, 33, "Text"],
Cell[3110, 82, 155, 3, 30, "Input"],
Cell[3268, 87, 45, 0, 33, "Text"],

Cell[CellGroupData[{
Cell[3338, 91, 34, 1, 30, "Input"],
Cell[3375, 94, 36, 1, 29, "Output"]
}, Open ]],
Cell[3426, 98, 46, 0, 33, "Text"],

Cell[CellGroupData[{
Cell[3497, 102, 60, 1, 30, "Input"],
Cell[3560, 105, 69, 0, 43, "Output"]
}, Open ]],
Cell[3644, 108, 120, 4, 33, "Text"],

Cell[CellGroupData[{
Cell[3789, 116, 143, 3, 30, "Input"],
Cell[3935, 121, 83, 1, 25, "Print"],
Cell[4021, 124, 103, 2, 25, "Print"]
}, Open ]],
Cell[4139, 129, 249, 9, 52, "Text"],

Cell[CellGroupData[{
Cell[4413, 142, 39, 1, 30, "Input"],
Cell[4455, 145, 40, 1, 29, "Output"]
}, Open ]],
Cell[4510, 149, 115, 3, 33, "Text"],

Cell[CellGroupData[{
Cell[4650, 156, 60, 1, 30, "Input"],
Cell[4713, 159, 129, 4, 77, "Output"]
}, Open ]],
Cell[4857, 166, 189, 5, 52, "Text"],

Cell[CellGroupData[{
Cell[5071, 175, 90, 2, 30, "Input"],
Cell[5164, 179, 41, 1, 25, "Print"],
Cell[5208, 182, 41, 1, 25, "Print"]
}, Open ]]
}, Closed]],

Cell[CellGroupData[{
Cell[5298, 189, 42, 0, 39, "Section"],
Cell[5343, 191, 155, 3, 52, "Text"],
Cell[5501, 196, 48, 1, 30, "Input"],
Cell[5552, 199, 53, 0, 33, "Text"],
Cell[5608, 201, 83, 1, 30, "Input"],

Cell[CellGroupData[{
Cell[5716, 206, 38, 1, 30, "Input"],
Cell[5757, 209, 184, 3, 60, "Message"],
Cell[5944, 214, 70, 1, 29, "Output"]
}, Open ]],
Cell[6029, 218, 187, 4, 52, "Text"],
Cell[6219, 224, 62, 1, 30, "Input"],

Cell[CellGroupData[{
Cell[6306, 229, 37, 1, 30, "Input"],
Cell[6346, 232, 196, 3, 60, "Message"],
Cell[6545, 237, 52, 1, 29, "Output"]
}, Open ]],
Cell[6612, 241, 62, 1, 30, "Input"],

Cell[CellGroupData[{
Cell[6699, 246, 37, 1, 30, "Input"],
Cell[6739, 249, 54, 1, 29, "Output"]
}, Open ]],
Cell[6808, 253, 70, 0, 33, "Text"],
Cell[6881, 255, 41, 0, 33, "Text"],
Cell[6925, 257, 25, 0, 33, "Text"],

Cell[CellGroupData[{
Cell[6975, 261, 96, 2, 30, "Input"],
Cell[7074, 265, 133, 3, 25, "Print"]
}, Open ]],
Cell[7222, 271, 217, 4, 71, "Text"],
Cell[7442, 277, 378, 11, 185, "Text"],
Cell[7823, 290, 103, 2, 30, "Input"],
Cell[7929, 294, 150, 8, 147, "Text"],
Cell[8082, 304, 31, 0, 33, "Text"],

Cell[CellGroupData[{
Cell[8138, 308, 105, 3, 70, "Input"],
Cell[8246, 313, 149, 4, 25, "Print"],
Cell[8398, 319, 36, 1, 29, "Output"],
Cell[8437, 322, 35, 1, 29, "Output"]
}, Open ]],
Cell[8487, 326, 246, 10, 166, "Text"],
Cell[8736, 338, 75, 1, 33, "Text"],

Cell[CellGroupData[{
Cell[8836, 343, 38, 1, 30, "Input"],
Cell[8877, 346, 64, 1, 25, "Print",
CellTags->"Info3216631205-4665998"],
Cell[8944, 349, 532, 15, 25, "Print",
CellTags->"Info3216631205-4665998"]
}, Open ]],
Cell[9491, 367, 168, 4, 52, "Text"],

Cell[CellGroupData[{
Cell[9684, 375, 312, 6, 130, "Input"],
Cell[9999, 383, 149, 4, 25, "Print"],
Cell[10151, 389, 149, 4, 25, "Print"],
Cell[10303, 395, 155, 3, 25, "Print"],
Cell[10461, 400, 35, 1, 29, "Output"]
}, Open ]],
Cell[10511, 404, 782, 15, 166, "Text"],

Cell[CellGroupData[{
Cell[11318, 423, 40, 1, 30, "Input"],
Cell[11361, 426, 64, 1, 25, "Print",
CellTags->"Info3216631214-9056274"],
Cell[11428, 429, 698, 19, 58, "Print",
CellTags->"Info3216631214-9056274"]
}, Open ]],
Cell[12141, 451, 132, 3, 52, "Text"],

Cell[CellGroupData[{
Cell[12298, 458, 229, 4, 90, "Input"],
Cell[12530, 464, 149, 4, 25, "Print"],
Cell[12682, 470, 133, 3, 25, "Print"],
Cell[12818, 475, 149, 4, 25, "Print"],
Cell[12970, 481, 133, 3, 25, "Print"],
Cell[13106, 486, 155, 3, 25, "Print"]
}, Open ]],

Cell[CellGroupData[{
Cell[13298, 494, 40, 1, 30, "Input"],
Cell[13341, 497, 64, 1, 25, "Print",
CellTags->"Info3216631221-7238232"],
Cell[13408, 500, 861, 23, 91, "Print",
CellTags->"Info3216631221-7238232"]
}, Open ]],
Cell[14284, 526, 308, 10, 185, "Text"],

Cell[CellGroupData[{
Cell[14617, 540, 352, 7, 150, "Input"],
Cell[14972, 549, 161, 3, 25, "Print"],
Cell[15136, 554, 37, 1, 29, "Output"]
}, Open ]],
Cell[15188, 558, 104, 3, 33, "Text"],

Cell[CellGroupData[{
Cell[15317, 565, 37, 1, 30, "Input"],
Cell[15357, 568, 38, 1, 29, "Output"]
}, Open ]],
Cell[15410, 572, 45, 0, 33, "Text"],

Cell[CellGroupData[{
Cell[15480, 576, 40, 1, 30, "Input"],
Cell[15523, 579, 64, 1, 25, "Print",
CellTags->"Info3216631226-7466759"],
Cell[15590, 582, 535, 15, 25, "Print",
CellTags->"Info3216631226-7466759"]
}, Open ]],
Cell[16140, 600, 188, 4, 52, "Text"],

Cell[CellGroupData[{
Cell[16353, 608, 352, 7, 150, "Input"],
Cell[16708, 617, 161, 3, 25, "Print"],
Cell[16872, 622, 37, 1, 29, "Output"]
}, Open ]],

Cell[CellGroupData[{
Cell[16946, 628, 40, 1, 30, "Input"],
Cell[16989, 631, 64, 1, 25, "Print",
CellTags->"Info3216631234-9152500"],
Cell[17056, 634, 535, 15, 25, "Print",
CellTags->"Info3216631234-9152500"]
}, Open ]],

Cell[CellGroupData[{
Cell[17628, 654, 37, 1, 30, "Input"],
Cell[17668, 657, 38, 1, 29, "Output"]
}, Open ]]
}, Closed]]
}
]
*)

(*******************************************************************
End of Mathematica Notebook file.
*******************************************************************)


"Richard Fateman" <fat...@cs.berkeley.edu> wrote in message
news:9ul2ft$6m3$1...@smc.vnet.net...

Richard Fateman

unread,
Dec 7, 2001, 6:32:11 AM12/7/01
to

Andrzej Kozlowski wrote:

> This sort of arguments seem to be a regular feature on this list. I do
> not feel like going into detail because I remember all this having been
> done before more than once. There are however three general points that
> I would make.
>
> 1) All the "unexpected" outputs are exactly as would be expected by
> anyone who has a fair grasp of the Mathematica language and can be
> supported by the documentation. Therefore they can't be called bug, at
> least not in the sense that I understand the term.


Documenting a bug as a feature does not remove it, in my opinion.
My guess is that your formal training is not in computer science,
and that you have not taken a course in (say) design of programming
languages.

In mathematics it is possible to construct formal systems based on
any set of non-contradictory axioms, and there is only a momentary
pause in the stream of publications when someone points out that
the defined system is useless, or perhaps vacuous. A set with no
elements has many properties, and if you didn't realize it was empty,
you could have something quite interesting!

In programming, there is not so much that is arbitrary. We don't
want people to be surprised by the consequences. Sometimes there are
legitimate choices in design, based on different perspectives of
(say) scope: which is most useful/efficient. Sometimes there are
just "bad" designs. I think of these as really bad bugs, especially
when they are defended. (Maple, for a long time, had some such
bugs. To their credit, they eventually fixed them. Probably because
one of the designers left the company.)

(This is not to say
> that there are no bugs in mathematica, it certainly has its fair share.
> Just that none of these are.)


Certainly we can agree to disagree here.


> In fact the first two cases are Mathematica "standard errors", discussed
> in this group a countless number of times . If a Mathematica beginner
> came up with them I would refer him to the Mathematica Book. The other
> examples are more subtle but highly contrived. In the unlikely event
> that that a beginner would be troubled by them my reaction would be to
> say "why on earth do you want to do that?".

Certainly you are familiar with the importance of counterexamples in
mathematics.
If someone proposed a new axiom system for geometry, and you showed that
it lead -- in certain singular instances -- to contradictions, then
you would have a valid objection to that system. You would probably
not have much confidence in anything proved in that system.

If someone proposed a new programming language and I showed that it
lead -- in certain singular instances -- to nonsense, then I would
have a valid object to that language. I would not have much confidence
in anything programmed in that system.

>
> 2) One can certainly argue about the good and bad points of the design
> of a programming languages. However, to a large extent this is a matter
> of what one is used to, how and how often one uses a language and of
> personal taste.


To some extent this is true. Just as in mathematics one can use
a notation f'(x) or d/dx(f(x)).

For example, you have written on the subject of Block
> and Module before, and I have found that some of the things that you
> criticize are in my opinion among their strongest points, allowing many
> constructions that are difficult to achieve in other programming languages.

I don't know what other programming languages you are referring to here.
You mention Common Lisp, which allows a far more complete and consistent
programming perspective. If you are saying Mathematica as a programming
language is better than Common Lisp, I think you are being blinded by
application programs, and superficial syntax. These can of course be
added to Common Lisp, and it does not require breaking the semantics
to do so.


>
> 3) I can imagine that there may be good reasons for being interested in
> translating between different programming languages. I do not know much
> about that.


Often this is appealing because people say "mathematica is too slow,
can it be translated into C" or "I would like to run my Maple program
along with someone else's Mathematica program".

> However, as a matter of practice I find "translating" a bad
> idea. I use two languages, Mathematica and Common Lisp, the first very
> often and the second when really needed, and I make an effort to
> consciously avoid trying to translate between them since this is the
> surest route to inefficient programming. Both languages have their
> unique strengths and are ideally suited for different purposes. The
> Mathematica language is certainly unlike any other but I really do not
> see why this is a bad thing. And after all, as you yourself have
> written, one is always always free not to use it. Since you have already
> made this point what is the point you are trying to make now?


I am continually surprised at how bad the design is in respect
to certain programming language issues. As you know, I wrote a
parser / partial evaluator for Mathematica (MockMMA) in Lisp.
I have not run these examples in it, but I expect that it will
either (a) operate in the same way as a consequence of my having
programmed the order of evaluation and binding in the same way
as Mathematica, or (b) operate in a different way, reflecting
my (mis)understanding at the time of how the simulation of parameter
binding by pattern matching is supposed to work. My expectation
is that at time time I wrote MockMMA, my understanding of
(a) the syntax
(b) the pattern matcher
(c) the evaluation
was as thorough as any but a handful of people.
That is generally what happens when one implements a system:
all the details must be tied down.

As programming language designers, we are not constrained
to physical reality (as is the case with some physicists).
we are not constrained to study actual biological animals
and plants (as is the case with some biologists).
We can construct our own systems. Somewhat like mathematicians
but with a different esthetic sense.

The language design of mathematica, presumably done by
Wolfram, has many interesting features. It is possible
that these same features could be assembled in a system
that does NOT botch scope. MockMMA allows one to experiment
with such changes, though frankly no one (including myself)
has pursued "a new Mathematica evaluation mechanism" using
this tool.


I do not know how the system would have come out if Wolfram
had (for example) really understood lambda calculus or
lexical scope. If he had read the Abelson-Sussman book
Structure and Interpretation of Computer Programs,
I think Mathematica's language would make more sense.
As it is, Wolfram picked up some of these ideas but did not, I
think, understand them.

Andrzej Kozlowski

unread,
Dec 7, 2001, 6:40:33 AM12/7/01
to
Of course you are right that I am a mathematician by training and not a
computer scientist. Clearly our perspectives on programming languages
are different: I tend to look at them as tools, to be used in doing
mathematics, not as formal systems to be studied. In judge a
programming language by its usefulness and not not by such matters as
consistency and so on. What can be "proved about it", is usually less
interesting to me, at least in my capacity as a user of a programming
language. Of course there are situations when it is no so. It so happens
that I first learned Lisp from reading Greg Chaitin's "Algorithmic
Information Theory". Before that I had only only had used Algol and
Pascal which I learned as an undergraduate, and when I read Chaitin's
book I was amazed there could be a programming language that was so
perfectly consistent and well defined that one could prove theorems
about it. That is indeed very beautiful, but hardly useful for doing the
sort of mathematics I am really interested in. The whole situation
reminds me of the traditional division in mathematics between these
mathematicians who consider foundations of mathematics as an important
and central subject and those who think of it as something totally
unimportant. Suppose an unresolvable flaw was discovered in the
foundations of Mathematics, say a basic inconsistency in all known
axioms of set theory. What would be the reaction of people studying
partial differential equations? Most would just shrug their shoulders
and go on doing what they were doing, and in my opinion would be quite
right to do so. These subject do not rest on the "foundations", it's
only the people who who work on foundations who flatter themselves that
it is so. You talk of mathematics in terms of "axioms". Of course there
are many mathematicians who think in this way. But there are many more,
including myself (and I mean pure mathematicians dealing with abstract
objects like manifolds or complexes) who hardly ever mention this word
in their work.

So my reaction to your examples and to most of your comments is that
them may well be true but are hardly relevant to me or the vast majority
of people who use Mathematica. You say that the fact that something is
documented and called a "feature" does not stop it being a bug. But that
is only true if that "bug" prevents you from doing something you might
want to do. When the manual says "don't do it this way, do it that way",
the argument that other programs do it the first way and so not being
able to do it that way must be a bug, does not seem to carry much weight
to me.

I find Mathematica more useful than Common Lisp because I can, for
example, combine Groebner basis computations, with graphics and
evaluation of integrals, all in the same program. Of course these things
could be added to Lisp, but they are not. Moreover, the rule based
programming style of Mathematica is very much more efficient for the
kind of things I do, most of the time. Let me make this concrete. At
this time I doing research which involves computing invariants of
actions fo finite groups on certain polynomial rings. I have written a
"package", or rather just a collection of functions, defining the
Steenrod operations, Dickson invariants and so on. I use this together
with the built in GroebnerBasis and other polynomial algebra package.
All of this just in about two printed pages. I also happen to have a
Lisp program which does basically the same thing. It's more than 10
pages long and is most of the time slower. There are countless other
examples of this kind. In fact I only use Lisp when I need to do
something that will require huge amounts of memory, because in such
cases Lisp's recursive programming seems sometime the only way to go.
But this has nothing to do with the consistency of Lisp and Mathematica
and nothing to do with scoping.

So to sum up: I consider the examples that you sent to be of some
theoretical interest and 0. practical importance. TO justify this view
I looked at some of my hundreds of Matheamtica notebooks to check how
often I used Block and Module. It was I as expected, almost exclusively
when writing something for the mathgroup. I am now not even sure how I
came be indoctrinated with the idea that one should do that! The
programs I write for myself consist of lots of short, often one line
function definitions and function calls. In fact I often use global
variables and Clear them afterwards. It seems to me that this is the
natural way to use Mathematica and I expect that most users do the same.
Given that, is it surprising that I consider yor message of little
importance. Maybe Mathematica scoping is "all wrong" but if so then
"scope" is hardly an important aspect of Mathematica. Suppose it could
be "fixed", would it make Matheamtica a more useful tool? I doubt it.
Moreover, any human and other resources devoted to this task would have
to be diverted form other things, like mathematical applications. If one
has to choose between improving Mathematica scope and its ability to
solve differential equations, how many users would choose the former?
Very few I believe. I think in the end this is the central issue. Of
course I would like Mathematica to be perfect in all respects, but
fixing the "foundations" is less important to me than expanding its
frontiers. Like mathematics, Mathematica is not a vertical structure
that can be brought down by some weakness of its foundations ( or at
least not this particular weakness).


Andrzej Kozlowski
Toyama International University
JAPAN
http://platon.c.u-tokyo.ac.jp/andrzej/

Richard Fateman

unread,
Dec 7, 2001, 6:42:52 AM12/7/01
to

Andrzej Kozlowski wrote:

> Of course you are right that I am a mathematician by training and not a
> computer scientist. Clearly our perspectives on programming languages
> are different: I tend to look at them as tools, to be used in doing
> mathematics, not as formal systems to be studied.


I agree with you entirely on programming languages being tools.
I do not study programming languages, I use them. I prefer
my tools to be correct, however.


In judge a
> programming language by its usefulness and not not by such matters as
> consistency and so on.


In that case you are missing the point. The usefulness should be
in the specifications of the language --- that many people can use
the same tools. If all you are saying is "I used this language
to write this program and it worked for me, even though it might
not work for you if you happen to use it for a case where the
answer is not known in advance and can't be checked" then I
say this language should be judged "not very" useful.


What can be "proved about it", is usually less
> interesting to me, at least in my capacity as a user of a programming
> language. Of course there are situations when it is no so. It so happens
> that I first learned Lisp from reading Greg Chaitin's "Algorithmic
> Information Theory". Before that I had only only had used Algol and
> Pascal which I learned as an undergraduate, and when I read Chaitin's
> book I was amazed there could be a programming language that was so
> perfectly consistent and well defined that one could prove theorems
> about it. That is indeed very beautiful, but hardly useful for doing the
> sort of mathematics I am really interested in.


The fact is that several computer algebra systems were written in
lisp (a more advanced version than Chaitin;s of course). These
include Reduce, Axiom, Macsyma, (and probably 12 research programs of
the past).

The whole situation
> reminds me of the traditional division in mathematics between these
> mathematicians who consider foundations of mathematics as an important
> and central subject and those who think of it as something totally
> unimportant. Suppose an unresolvable flaw was discovered in the
> foundations of Mathematics, say a basic inconsistency in all known
> axioms of set theory. What would be the reaction of people studying
> partial differential equations? Most would just shrug their shoulders
> and go on doing what they were doing, and in my opinion would be quite
> right to do so. These subject do not rest on the "foundations", it's
> only the people who who work on foundations who flatter themselves that
> it is so. You talk of mathematics in terms of "axioms". Of course there
> are many mathematicians who think in this way. But there are many more,
> including myself (and I mean pure mathematicians dealing with abstract
> objects like manifolds or complexes) who hardly ever mention this word
> in their work.


But you are using as a tool, a program in which transitivity of equality
fails. That is, a==b and b==c does not imply a==c.
This matters even in partial differential equations.

You are using a tool in which the identity function Function[x,x] is not
a function, but a kind of pattern in which the basic notions of free
and bound variables -- essential for referential transparency -- the
substitution of equals for equals -- fails.

Now of course if all your programs are not really programs, but
commands like
if you see f(x,x) change it to g(x).
or commands like "compute the totally understood result of
the polynomial resultant of two polynomials with exact integer
coefficients" then you are OK.

If you try to build a robust system of substantial complexity,
the tools must not have hidden flaws.


>
> So my reaction to your examples and to most of your comments is that
> them may well be true but are hardly relevant to me or the vast majority
> of people who use Mathematica.


The vast majority of people who use Mathematica are still learning
integral calculus. The vast majority of people who use computers
today are probably surfing the net looking for pornography. Not a
good argument for excellence!

You say that the fact that something is
> documented and called a "feature" does not stop it being a bug. But that
> is only true if that "bug" prevents you from doing something you might
> want to do. When the manual says "don't do it this way, do it that way",
> the argument that other programs do it the first way and so not being
> able to do it that way must be a bug, does not seem to carry much weight
> to me.
>
> I find Mathematica more useful than Common Lisp because I can, for
> example, combine Groebner basis computations, with graphics and
> evaluation of integrals, all in the same program.


I can do this in Lisp, since Macsyma has those pieces, though these
parts of Mathematica are probably OK. Well actually, the evaluation
of integrals has problems...

Of course these things
> could be added to Lisp, but they are not. Moreover, the rule based
> programming style of Mathematica is very much more efficient for the
> kind of things I do, most of the time. Let me make this concrete. At
> this time I doing research which involves computing invariants of
> actions fo finite groups on certain polynomial rings. I have written a
> "package", or rather just a collection of functions, defining the
> Steenrod operations, Dickson invariants and so on. I use this together
> with the built in GroebnerBasis and other polynomial algebra package.
> All of this just in about two printed pages. I also happen to have a
> Lisp program which does basically the same thing. It's more than 10
> pages long and is most of the time slower. There are countless other
> examples of this kind. In fact I only use Lisp when I need to do
> something that will require huge amounts of memory, because in such
> cases Lisp's recursive programming seems sometime the only way to go.
> But this has nothing to do with the consistency of Lisp and Mathematica
> and nothing to do with scoping.
>
> So to sum up: I consider the examples that you sent to be of some
> theoretical interest and 0. practical importance.


I think we can agree to disagree. But doing these "theoretical" things
correctly would not be expensive. It would just have required Wolfram
to know a few things when he dictated how the system should work.

I think the idea that Wolfram was pursuing, that the language
he designed was important, the application "Mathematica" just
an example, is deeply flawed. I think that people who teach
Mathematica as a computer science "programming language" are doing
a grave disservice to the science of computer science.

Just as those people (who still work in physics labs) who think
that Fortran is the best language, even though it is the only
one they ever used. And that their opinion, because they
are physicists, is therefore valuable.


TO justify this view
> I looked at some of my hundreds of Matheamtica notebooks to check how
> often I used Block and Module. It was I as expected, almost exclusively
> when writing something for the mathgroup. I am now not even sure how I
> came be indoctrinated with the idea that one should do that! The
> programs I write for myself consist of lots of short, often one line
> function definitions and function calls. In fact I often use global
> variables and Clear them afterwards. It seems to me that this is the
> natural way to use Mathematica and I expect that most users do the same.
> Given that, is it surprising that I consider yor message of little
> importance. Maybe Mathematica scoping is "all wrong" but if so then
> "scope" is hardly an important aspect of Mathematica. Suppose it could
> be "fixed", would it make Matheamtica a more useful tool? I doubt it.
> Moreover, any human and other resources devoted to this task would have
> to be diverted form other things, like mathematical applications. If one
> has to choose between improving Mathematica scope and its ability to
> solve differential equations, how many users would choose the former?
> Very few I believe. I think in the end this is the central issue. Of
> course I would like Mathematica to be perfect in all respects, but
> fixing the "foundations" is less important to me than expanding its
> frontiers. Like mathematics, Mathematica is not a vertical structure
> that can be brought down by some weakness of its foundations ( or at
> least not this particular weakness).


I actually disagree. Look at the disclaimer at the front of the book
that says not to use Mathematica for computations involving life, or
property.

Regards
RJF

Andrzej Kozlowski

unread,
Dec 7, 2001, 6:43:56 AM12/7/01
to
Well, to me at least, these remarks show that you are engaging in
rhetoric designed to discredit Mathemaitca or Wolfram rather than an
objective argument. You know perfectly well that non-transitive notions
of "equality" are quite common in mathematics dealing with approximate
and uncertain quantities, indeed there are a whole subjects (for example
something called "fuzzy geometry") based on such notions. In fact you
yourself have pointed out that comparisons of this kind between
approximate quantities ought to be avoided. In fact Mathematica has a
strict notion of equality (SameQ) and this worn argument is just a red
herring. As for the other point, well Mathematica is clearly a pattern
matching language with a functional syntax, which makes it easier to
use, but may be misleading to those who have not studied it carefully.
But one can no more blame it for not being like Lisp as for not being
like C or Java.

>
> I can do this in Lisp, since Macsyma has those pieces, though these
> parts of Mathematica are probably OK. Well actually, the evaluation
> of integrals has problems...

Presumably you would argue that the reason why Macsyma never really
managed to gain any popularity outside a few departments of mathematics
or computer science (it was there when I was beginning to teach in the
US, before Mathematica, yet today it seems to be even less well known
than in those days) is somehow the result of failure of people to
realize its superior excellence. But claims like this are common,
particularly by the authors of the less successful products.

>
>
> I actually disagree. Look at the disclaimer at the front of the book
> that says not to use Mathematica for computations involving life, or
> property.
>
> Regards
> RJF
>
>

Hm, are you saying that you would be willing to accept personal
liability for any damage to life or property that could result from a
bug in Macsyma? If so I find it very admirable since I am not aware of
any other software developer who has the courage to take this attitude.

Alan Mason

unread,
Dec 7, 2001, 6:45:06 AM12/7/01
to
In general, Mathematica has complicated rules for when and how its functions
hold their arguments, which can lead to semantic surprises. Users can
change these attributes at their own risk. In particular, the right-hand
side of a SetDelayed such as uu[...] := x is normally not evaluated, and the
left-hand side is normally wrapped in HoldPattern. Just how these rules
work in conjunction with the pattern matcher is a mystery, but
they definitely are not working correctly in Fateman's first example ---
rr[x_] := Module[{x}, x = 5; Print["x is ", x]].
The system needs to unwrap the various Holds in the right order and process
first the
first argument {...}of Module giving the locals and preempt the pattern
matcher if there is a clash. Presumably this should be done before
Mathematica's uniqueifying rules (appending $n to local variable names to
make
them unique) are performed. Could be a timing problem. The handling of
Hold
and ReleaseHold is tricky and this may explain some other bugs, e.g. why in
version 4.1
Collect[e_, patt_, func] incorrectly releases any Holds present in e.

In view of the above, I think the Fateman's second example, uu[x_?((x = 5;
Print["x is ", x]; True) &)] := x,
actually shows Mathematica doing something correctly :=). The x_ should
correspond to the x on the right-hand side,
whereas the x in the PatternTest, being on the LHS, should define and/or
update a new variable x separate from
whatever x_ matches. Also, on a fresh startup of Mathematica v4.1 I get no
extraneous printout.

Fateman's third example, Module[{x}, uu[x_?((x = 5; Print["x is ", x]; True)
&)] := x; Print["in Module, x is " , x]],
illustrates some interesting behavior when
run repeatedly, as in the following notebook. I do not find that x is
changed to 5. However, the printed statements
become more numerous with each subsequent run. Examination shows that
Mathematica is
defining a new version of uu with each run, parameterized by the current
local name x$9, x$10, etc. for the local x, and is running all the versions.
This is as it should be.
Surprisingly, however, these variables are not
allocated on the stack but seem to be stored on the heap -- one has
access to them and can change them. I have not been able to
change the global x from 400 to 5, but x$9 is also in essence global (it
didn't disappear from any stack) and if I reassign x$9 to 44, say, and run
the Module[...] again, x$9 *is* changed back to 5. This is not happening to
x, though -- x remains 400. In a way this is good, since one doesn't expect
the global x to be changed, but it also seems inconsistent since x$9 is just
as global as x . It would appear that local variables in Mathematica are not
treated as such if they parameterize global objects defined inside a
module; instead, the system keeps track of them even after their scope
disappears.
This enables Mathematica to distinguish dynamically between different
instances of, e.g., programmatically generated rules
parameterized by some argument(s), but seems to muddy the distinction
between local and global variables. Why does Mathematica behave this way,
rather than just plugging the value of x$n directly into the rule and then
letting
x$n go out of scope? Maybe because in principle it allows the user to
change x$n and
therefore also the rule (this is the essence of RuleDelayed, I suppose); but
users will typically not
know what alias to use for the local variable x in order to change it (the
only way to find this alias is to do a ?uu). So I wonder
if this hypothetical advantage warrants the apparent inconsistency that I
noted above.


In[1]:=
x = 400
Out[1]=
400
In[2]:=


Module[{x}, uu[x_?((x = 5; Print["x is ", x]; True) &)] := x;
Print["in Module, x is " , x]]

in Module, x is \[InvisibleSpace]x$9
In[3]:=Module[{x}, uu[x_?((x = 5; Print["x is ", x]; True) &)] := x;


Print["in Module, x is " , x]]

x is \[InvisibleSpace]5
x is \[InvisibleSpace]5
in Module, x is \[InvisibleSpace]5
In[4]:=


Module[{x}, uu[x_?((x = 5; Print["x is ", x]; True) &)] := x;
Print["in Module, x is " , x]]

x is \[InvisibleSpace]5
x is \[InvisibleSpace]5
x is \[InvisibleSpace]5
x is \[InvisibleSpace]5
in Module, x is \[InvisibleSpace]5
In[5]:=


Module[{x}, uu[x_?((x = 5; Print["x is ", x]; True) &)] := x;
Print["in Module, x is " , x]]

x is \[InvisibleSpace]5
x is \[InvisibleSpace]5
x is \[InvisibleSpace]5
x is \[InvisibleSpace]5
x is \[InvisibleSpace]5
x is \[InvisibleSpace]5
in Module, x is \[InvisibleSpace]5
In[6]:=
?uu
Global`uu
\!\(\*
InterpretationBox[GridBox[{
{GridBox[{
{\(uu[x_?\((\((x$9 = 5; Print["x is ", x$9]; True)\) &)\)] :=
x\)},
{" "},
{\(uu[x_?\((\((x$10 = 5; Print["x is ", x$10]; True)\) &)\)]


:=
x\)},
{" "},

{\(uu[x_?\((\((x$11 = 5; Print["x is ", x$11]; True)\) &)\)]


:=
x\)},
{" "},

{\(uu[x_?\((\((x$12 = 5; Print["x is ", x$12]; True)\) &)\)]


:=
x\)}
},
GridBaseline->{Baseline, {1, 1}},
ColumnWidths->0.999,
ColumnAlignments->{Left}]}
},
GridBaseline->{Baseline, {1, 1}},
ColumnAlignments->{Left}],
Definition[ "uu"],

Editable->False]\)
In[7]:=
x$9 = 44
Out[7]=
44
In[8]:=


Module[{x}, uu[x_?((x = 5; Print["x is ", x]; True) &)] := x;
Print["in Module, x is " , x]]

(snip--AGM)
In[9]:=
{x, x$9}
Out[9]=
{400,5}

Alan

"Richard Fateman" <fat...@cs.berkeley.edu> wrote in message
news:9ul2ft$6m3$1...@smc.vnet.net...

Richard Fateman

unread,
Dec 8, 2001, 6:04:52 AM12/8/01
to

Andrzej Kozlowski wrote:

>
>
>> If you try to build a robust system of substantial complexity,
>> the tools must not have hidden flaws.
>>
> Well, to me at least, these remarks show that you are engaging in
> rhetoric designed to discredit Mathemaitca or Wolfram rather than an
> objective argument. You know perfectly well that non-transitive notions
> of "equality" are quite common in mathematics dealing with approximate
> and uncertain quantities, indeed there are a whole subjects (for example
> something called "fuzzy geometry") based on such notions.


I don't know about fuzzy geometry, and I certainly do not encourage
people to compare for equality of floating point numbers except in
a very limited sense. (Typically a convergence criterion that says
"did the last iteration change the result AT ALL" ... but even so
this is generally not a good idea). But that the programming language
itself would have a notion of equality that was not transitive... this
is bizarre, and I think unique to Mathematica.

In fact you
> yourself have pointed out that comparisons of this kind between
> approximate quantities ought to be avoided. In fact Mathematica has a
> strict notion of equality (SameQ) and this worn argument is just a red
> herring. As for the other point, well Mathematica is clearly a pattern
> matching language with a functional syntax, which makes it easier to
> use, but may be misleading to those who have not studied it carefully.
> But one can no more blame it for not being like Lisp as for not being
> like C or Java.


The notation f[x_]:=... is commonly thought of, and used, as
though it were (in Lisp equivalent notation)
(defun f(x) ...)

This is, as you say, potentially misleading. Especially since very
few people DO study it carefully! I certainly think of f[x_]:= as
a function definition, and so I am surprised when it fails to work
that way. Only then do I go back and say, OH, as a pattern, it is
doing something else.


>
>>
>> I can do this in Lisp, since Macsyma has those pieces, though these
>> parts of Mathematica are probably OK. Well actually, the evaluation
>> of integrals has problems...
>
>
> Presumably you would argue that the reason why Macsyma never really
> managed to gain any popularity outside a few departments of mathematics
> or computer science (it was there when I was beginning to teach in the
> US, before Mathematica, yet today it seems to be even less well known
> than in those days) is somehow the result of failure of people to
> realize its superior excellence. But claims like this are common,
> particularly by the authors of the less successful products.


Actually I don't blame users at all. There is a marketplace for scientific
software, and they made choices based on their criteria. I don't believe
the "customer is always right" but certainly "the customer is important".
Macsyma did not succeed because customers (users) did not buy it.

If customers think that Mathematica is better than it really is, then
it is a success in marketing. I think that the choice between Maple and
Mathematica is made --sometimes quite correctly-- on the basis of price.

I think part of the failure of Macsyma to gain great popularity
is political and financial. That is, MIT sold the exclusive commercial
rights to Symbolics Inc. For many years they refused to sell the program
except on their own special hardware. Not on Vaxes or on Suns.

Why did they buy Macsyma from MIT? Apparently so that their rivals in the
Lisp Machine business (LMI) would not buy it and have a competitive
advantage.

Thus part of the blame is (a) MIT and its decision-makers (Mike Dertouzos
and Joel Moses and their lawyers; (b) Arthur D. Little Inc, the "deal-maker"
who chose Symbolics, Inc. and (c) Symbolics Inc. management.

There are differences between systems, and I have written rather critically
of Macsyma (also). The disappointment is that the lessons of Macsyma were
not understood in the construction of Maple and Mathematica. Instead,
the same mistakes were implemented.

It will be interesting to see if the free version of Macsyma will have
an increasing impact, now that commercial Macsyma seems to have disappeared.


>
>>
>>
>> I actually disagree. Look at the disclaimer at the front of the book
>> that says not to use Mathematica for computations involving life, or
>> property.
>>
>> Regards
>> RJF
>>
>>
>
> Hm, are you saying that you would be willing to accept personal
> liability for any damage to life or property that could result from a
> bug in Macsyma? If so I find it very admirable since I am not aware of
> any other software developer who has the courage to take this attitude.


No, I would not accept personal liability for errors.
But there is a difference between disclaiming responsibility for
errors, and what SW says:
"The author, WRI and AW do not recommend the use of the software described
in this book for applications in which errors or omissions could threaten
life, injury or significant loss." (added in the second edition of The
Book).


I wonder how many other software system authors specifically recommend
AGAINST using their software? I can't find any such disclaimers in
the reference manuals for other packages, but maybe I have not looked
enough.

RJF

Alan Mason

unread,
Dec 9, 2001, 6:22:16 AM12/9/01
to
Hello All.
The following notebook has been instrumented to reveal the origin of the
mysterious print statements for Fateman's third example. Looks like Allan
Hayes is right -- it seems that evaluation is being triggered in an attempt
to sort out possible effects of the previous rules on the one currently
being defined. Can WR confirm this and elaborate on just how SetDelayed
works?

In[1]:=
Module[{x},
uu[x_?((Print["Initially, x is ", {x, Hold[x]}];x = 5; Print["x is ", x];


True) &)] := x;
Print["in Module, x is " , x]]


in Module, x is \[InvisibleSpace]x$9

In[2]:=
?uu

Global`uu

\!\(\*
InterpretationBox[GridBox[{
{GridBox[{
{\(uu[

x_?\((\((Print["Initially, x is ", {x$9, Hold[x$9]}];


x$9 = 5; Print["x is ", x$9]; True)\) &)\)] :=
x\)}
},

GridBaseline->{Baseline, {1, 1}},
ColumnWidths->0.999,
ColumnAlignments->{Left}]}
},
GridBaseline->{Baseline, {1, 1}},
ColumnAlignments->{Left}],
Definition[ "uu"],
Editable->False]\)

In[3]:=
x$9 = 9

Out[3]=
9

In[4]:=
Module[{x},

uu[x_?((Print["Initially, x is ", {x, Hold[x]}];x = 5; Print["x is ", x];


True) &)] := x;
Print["in Module, x is " , x]]

Initially, x is \[InvisibleSpace]{9,Hold[x$9]}

x is \[InvisibleSpace]5

Initially, x is \[InvisibleSpace]{x$20,Hold[x$20]}

x is \[InvisibleSpace]5

in Module, x is \[InvisibleSpace]5

In[5]:=
x$9

Out[5]=
5

In[6]:=
?uu

Global`uu

\!\(\*
InterpretationBox[GridBox[{
{GridBox[{
{\(uu[

x_?\((\((Print["Initially, x is ", {x$9, Hold[x$9]}];


x$9 = 5; Print["x is ", x$9]; True)\) &)\)] :=
x\)},
{" "},
{\(uu[

x_?\((\((Print["Initially, x is ", {x$20, Hold[x$20]}];
x$20 = 5; Print["x is ", x$20]; True)\) &)\)] :=


x\)}
},
GridBaseline->{Baseline, {1, 1}},
ColumnWidths->0.999,
ColumnAlignments->{Left}]}
},
GridBaseline->{Baseline, {1, 1}},
ColumnAlignments->{Left}],
Definition[ "uu"],
Editable->False]\)

In[7]:=
x$9 = 9;x$20 = 20;

In[8]:=
Module[{x},

uu[x_?((Print["Initially, x is ", {x, Hold[x]}];x = 5; Print["x is ", x];


True) &)] := x;
Print["in Module, x is " , x]]

Initially, x is \[InvisibleSpace]{9,Hold[x$9]}

x is \[InvisibleSpace]5

Initially, x is \[InvisibleSpace]{x$24,Hold[x$24]}

x is \[InvisibleSpace]5

Initially, x is \[InvisibleSpace]{20,Hold[x$20]}

x is \[InvisibleSpace]5

Initially, x is \[InvisibleSpace]{5,Hold[x$24]}

x is \[InvisibleSpace]5

in Module, x is \[InvisibleSpace]5

In[9]:=
?uu

Global`uu

\!\(\*
InterpretationBox[GridBox[{
{GridBox[{
{\(uu[

x_?\((\((Print["Initially, x is ", {x$9, Hold[x$9]}];


x$9 = 5; Print["x is ", x$9]; True)\) &)\)] :=
x\)},
{" "},
{\(uu[

x_?\((\((Print["Initially, x is ", {x$20, Hold[x$20]}];
x$20 = 5; Print["x is ", x$20]; True)\) &)\)] :=


x\)},
{" "},
{\(uu[

x_?\((\((Print["Initially, x is ", {x$24, Hold[x$24]}];
x$24 = 5; Print["x is ", x$24]; True)\) &)\)] :=


x\)}
},
GridBaseline->{Baseline, {1, 1}},
ColumnWidths->0.999,
ColumnAlignments->{Left}]}
},
GridBaseline->{Baseline, {1, 1}},
ColumnAlignments->{Left}],
Definition[ "uu"],
Editable->False]\)

In[10]:=
x$9 = 9;x$20 = 20;x$24=24;

In[11]:=
Module[{x},
uu[x_?((Print["Initially, x is ", {x, Hold[x]}];x = 5; Print["x is ", x];


True) &)] := x;
Print["in Module, x is " , x]]

Initially, x is \[InvisibleSpace]{9,Hold[x$9]}

x is \[InvisibleSpace]5

Initially, x is \[InvisibleSpace]{x$28,Hold[x$28]}

x is \[InvisibleSpace]5

Initially, x is \[InvisibleSpace]{20,Hold[x$20]}

x is \[InvisibleSpace]5

Initially, x is \[InvisibleSpace]{5,Hold[x$28]}

x is \[InvisibleSpace]5

Initially, x is \[InvisibleSpace]{24,Hold[x$24]}

x is \[InvisibleSpace]5

Initially, x is \[InvisibleSpace]{5,Hold[x$28]}

David Withoff

unread,
Dec 10, 2001, 6:23:51 AM12/10/01
to
> In general, Mathematica has complicated rules for when and how its functions
> hold their arguments, which can lead to semantic surprises. Users can
> change these attributes at their own risk. In particular, the right-hand
> side of a SetDelayed such as uu[...] := x is normally not evaluated, and the
> left-hand side is normally wrapped in HoldPattern. Just how these rules
> work in conjunction with the pattern matcher is a mystery, but
> they definitely are not working correctly in Fateman's first example ---
> rr[x_] := Module[{x}, x = 5; Print["x is ", x]].
> The system needs to unwrap the various Holds in the right order and process
> first the
> first argument {...}of Module giving the locals and preempt the pattern
> matcher if there is a clash. Presumably this should be done before
> Mathematica's uniqueifying rules (appending $n to local variable names to
> make
> them unique) are performed. Could be a timing problem.

I presume from all of those speculations and non-specific concerns
that you suspect there is something wrong but that you aren't quite
sure what it is. Is there some way that you could be more specific?
Do you have any examples of "complicated rules" or "semantic
surprises" that might help to explain your concerns? What exactly
is "definitely ... not working correctly" about that example? Do
you have a specific description of what you think that example
should do, and why? What are the "various Holds" that you are
referring to here?

I can imagine two potential criticisms of Mathematica here, one
of which might be partially valid, and the other of which is not
valid at all.

The potentially sensible criticism lies within the fact that you found
this behavior confusing. In some abstract, ideal world, all of the
things that we use, from VCR's to automobiles to computer software,
would be completely intuitive, and everything would behave as expected.
Any time someone is confused by Mathematica there is at least the
possibility that there is something about the design of Mathematica
that invites that confusion.

In this example, however, I just don't see it. If I translate

rr[x_] := Module[{x}, x = 5; Print["x is ", x]]

into C, for example, I get

int rr(int x) {int x; x = 5; printf("x is %d\n", x);}

which generates a warning message in my C compiler and produces
system-dependent results when I run the program. Most C programmers
would (I hope) immediately see the error of using the same name both
as a function parameter and as a local variable. I suppose it could
be argued that there is also something wrong with C and with the
many other programming languages that behave this way, but other than
that, I don't see what it is about Mathematica that might lead one to
expect behavior other than what is found in other languages. If
anything, the behavior of Mathematica is more straightforward than
other languages. At least it isn't system-dependent, and even
an intermediate understanding of how Mathematica works would
allow one to anticipate what this example will do.

The other potential criticism, which so far doesn't appear to be
valid at all, is that there is something objectively wrong with
the design of this aspect of Mathematica; that the design includes
a violation of some unspecified Sacred Principle that is well known
to people with advanced degrees in computer language design, but
that is probably beyond the understanding of everyone else; but
that everyone should nevertheless be Very Worried that these problems
are lurking around like a bogeyman in the dark, waiting to bite you
in the middle of a large program.

The reality is that there is no bogeyman, that this aspect of
Mathematica is pretty straightforward, and that in all essential
details these design choices have extensive precedent in other
programming languages.

This still leaves the subjective criticism. Is there something
about the design of Mathematica that suggests that it should
behave unlike other common programming languages?

There were a few other examples here, but the analysis was all
so broad and muddled that I hope that anyone who is interested
will follow up with a more specific question.

Dave Withoff
Wolfram Research

David Withoff

unread,
Dec 10, 2001, 6:24:53 AM12/10/01
to
> I have found a feature amongst your examples that came as a surprise: the
> way in which SetDelayed is evaluated. ... the rule is stored is as expected

> from the above, but it seems that after making later rules; some kind of
> evaluation is triggered, as though trying to evaluate the left sides using
> the other rules (the rules themselves are not altered). These evaluations
> may be due to working out the order in which to store or replace existing
> ones.

Yes. I thought that this was already well-known, at least to people
interested in Mathematica trivia, which is about all that this really is.
It has nothing to do with any of the other issues raised in this discussion,
and is certainly not a fundamental feature of the programming language. The
current strategy for ordering rules involves some evaluations of parts of
previous rules. This is essentially just a curiosity which is rarely
encountered and which has no known adverse effects in any practical examples.

> It seems to me that it would be better if these evaluations were done
> in private.

While it might be better to develop some other strategy for ordering
rules, as a practical matter there is no such thing as doing evaluations
in private, since evaluations can have irreversible effects. For example,
one might consider what should happen if one of those evaluations loaded
a package, or updated the random number generator, or evaluated Quit[].

> However, the same kind of evaluations will occur when the rules
> are used, and any unwanted assignments can be avoided in both circumstances
> by suitable localisation of symbols inside tests and conditions, though
> unwanted printing would still occur.

Exactly. In other words, if those evaluations are a problem when
the rules are ordered then they is also a problem when the rules are
used, and the programmer will have to figure out a way to deal with that
regardless of whatever else happens.

Dave Withoff
Wolfram Research

David Withoff

unread,
Dec 10, 2001, 6:26:01 AM12/10/01
to
> > Well, to me at least, these remarks show that you are engaging in
> > rhetoric designed to discredit Mathemaitca or Wolfram rather than an
> > objective argument. You know perfectly well that non-transitive notions
> > of "equality" are quite common in mathematics dealing with approximate
> > and uncertain quantities, indeed there are a whole subjects (for example
> > something called "fuzzy geometry") based on such notions.
>
> I don't know about fuzzy geometry, and I certainly do not encourage
> people to compare for equality of floating point numbers except in
> a very limited sense. (Typically a convergence criterion that says
> "did the last iteration change the result AT ALL" ... but even so
> this is generally not a good idea). But that the programming language
> itself would have a notion of equality that was not transitive... this
> is bizarre, and I think unique to Mathematica.

I don't understand this. What does "the programming language itself"
having "a notion of equality" mean? Mathematica supports several
functions that are typically used as measures of equality, and users
can of course program their own. Some of those operations will be
transitive and some will not. Would the language be better if all
built-in functions for non-transitive measures of equality were removed?
Conversely, what if such functions were added to standard C and Fortran
libraries. Would doing so make those languages worse?

None of this has anything to do with the message "Subject" of course.
I am concerned that the subject may have transmogrified to include
so many things that it is not very meaningful any more.

Dave Withoff
Wolfram Research

David Withoff

unread,
Dec 10, 2001, 6:27:21 AM12/10/01
to
> Hello All.
> The following notebook has been instrumented to reveal the origin of the
> mysterious print statements for Fateman's third example. Looks like Allan
> Hayes is right -- it seems that evaluation is being triggered in an attempt
> to sort out possible effects of the previous rules on the one currently
> being defined. Can WR confirm this and elaborate on just how SetDelayed
> works?

See my message of December 7. I'm afraid that some people are going to
worry about it no matter what, but this is basically just an obscure bit
of Mathematica trivia with no known practical consequences. It is not a
fundamental part of the Mathematica programming language and has nothing
to do with the topic at hand. These evaluations are part of the current
strategy for ordering evaluation rules. This has nothing specifically to
do with SetDelayed, except that SetDelayed is one of many functions that
introduce evaluation rules. If anyone thinks they have a *practical*
example where this might be an issue you could contact tech support, or
just post it here (in a separate thread, please), which would undoubtedly
provide hours of amusement for all concerned.

> In[1]:= Module[{x},
> uu[x_?((Print["Initially, x is ", {x, Hold[x]}];x = 5; Print["x is ", x];
> True) &)] := x;
> Print["in Module, x is " , x]]
>

> in Module, x is x$9


>
> In[3]:= x$9 = 9
>
> Out[3]= 9
>
> In[4]:= Module[{x},
> uu[x_?((Print["Initially, x is ", {x, Hold[x]}];x = 5; Print["x is ", x];
> True) &)] := x;
> Print["in Module, x is " , x]]
>

> Initially, x is {9,Hold[x$9]}
>
> x is 5
>
> Initially, x is {x$20,Hold[x$20]}
>
> x is 5
>
> in Module, x is 5


>
> In[5]:= x$9
>
> Out[5]= 5

etc. etc.

Alan Mason

unread,
Dec 12, 2001, 4:14:25 AM12/12/01
to
Hello.
1) I think that ideal behavior would be to issue a warning "argument of
function is shadowed by local variable, will have no effect" and just use
the local x. To barge right in and replace x in the body of the Module when
this x should refer to the local variable strikes me as too simplistic and
is therefore a surprise. Perversely, badly written code is not always a
waste of time, because it can reveal interesting things about how a system
operates. For example, people are always throwing crap at C compilers;
there are even contests to see who can write the most obfuscated C code.

I tried in my previous post to express what I think would have to be
changed to accommodate "ideal" behavior. In essence, some processing (and
therefore unHolding) of the RHS of := -- to determine the locals and look
for name clashes, and if neccessary preempt the pattern matcher -- would
have to occur before the value that the system has determined for the
pattern x_ on LHS is passed in to the RHS. Currently, this passing is
essentially instantaneous.

I concede that the above "ideal" behavior would have no practical benefits
(that I can think of) and it could burden all functions with undesirable
overhead. I can also see that Mathematica, unlike C, is not really obliged
to behave in ways that have been specified by outside committees.

2) My comment about the local x$9 reemerging as a de facto global (growing
wings as it were and flying the coop) does seem relevant to Fateman's
concern about scope violation and "escaping" variables. Variables like x$9
are normally off-limits to programmers outside of the subroutine in which
they are declared as local. Does Mathematica rely on the uniqueness of x$n
variable names to keep track internally of multiple versions of global rules
generated programmatically inside a Module, by using them in effect as part
of their "signature"? I know that I can change rules after the fact (i.e.,
after the scope of x$n as originally declared in its subroutine has
disappeared) by changing the x$n to which they have been "hard-wired". Of
course, no one who has used Mathematica entertains for a moment the
possibility that local variables are escaping wholesale -- this would make
Mathematica completely unusable, whereas in practice it's eminently usable
(albeit with a steep learning curve). But the observed phenomenon does seem
to be a kind of "back door" and therefore not exactly kosher...

Alan

PS. I think for clarity it would be best to include a code snippet showing
exactly what I mean here.
Here's a greatly abridged example from actual code:

\!\(\(\(setRules[sym_: D, \ delayCircleDotEvaluation_: 0]\ := \
Module[{\ h, \ symL}, \[IndentingNewLine]If[Head[sym]\ =!= \ List, \
symL\ = \ {sym}, \
symL\ = \ sym]; \[IndentingNewLine]SetAttributes[
SmallCircle, {OneIdentity, \
Flat}]; \[IndentingNewLine]a_\ \[SmallCircle]\ b_\ /; \
Head[a] === Plus\ || \ Head[b] === Plus := \
Distribute[h[a, \ b]]\ /.
h -> SmallCircle\ ; \ \[IndentingNewLine]\((a_. \ S_\_u_)\)\ \
\[SmallCircle]\ \((b_\ \ c_)\)\ := \
a\ b\ \ S\_u\ \[SmallCircle]\ c\ + \
a\ S\_u\ \[CircleDot]\ b\ c\ /; \
MemberQ[symL, \
S]\ \ && \((FreeAllQ[b, symL]\ || \
Head[b] ===

CircleDot)\);\[IndentingNewLine]];\)\(\[IndentingNewLine]\
\)
\)\)

If you run setRules and then do DownValues[\[SmallCircle], pick out the
rule involving S, and do a FullForm, you will not find S but rather symL$n
instead (its value is in fact that of S, but it is being held; Cases[rule,
symL$n, {0, Infinity}] returns {}). If you change symL$n interactively,
you will change rule accordingly. (But I thought symL$n was local! So this
really is a back door.)

A side observation possibly of interest: If we change the code in setRules
so that S is not first copied to symL (i.e., not "mediated") but used
directly in the rule, the value of S does appear when the rule is examined
using DownValues. This seems to shed some light on Mathematica's timing --
the value found for S_ is passed to RHS of := very early and is not held but
treated as "raw".

"David Withoff" <wit...@wolfram.com> wrote in message
news:9v2607$ldc$1...@smc.vnet.net...

David Withoff

unread,
Dec 14, 2001, 3:36:06 AM12/14/01
to
> I think that ideal behavior would be to issue a warning "argument of
> function is shadowed by local variable, will have no effect"

I would go along with that. Probably the only objection would be that
adding such a message may not be worth the effort, since essentially
no on ever makes this mistake anyway.

I found the next comment to be fairly interesting:

> To barge right in and replace x in the body of the Module when
> this x should refer to the local variable strikes me as too simplistic and
> is therefore a surprise.

Does this mean that the behavior was surprising because it wasn't
sufficiently complicated? The only times that I have been confused
by Mathematica was when I expected it to be more complicated than
it really was. Mathematica is actually a pretty simple system.

The two different ways of handling this situation can be
illustrated by comparing:

In[1]:= f[x_]:=Module[{x},x=5;Print["x is ", x]]

In[2]:= f[99]

Module::lvsym: Local variable specification {99} contains 99 which


is not a symbol or an assignment to a symbol.

Out[2]= Module[{99},99=5;Print[x is ,99]]

where, as you noted, the value associated with x in f[x_] just
goes barging right in to the right side of the rule, and

In[3]:= f = Function[{x},Module[{x},x=5;Print["x is ",x]]];

In[4]:= f[99]

x is 5

where the value associated with the x in Function[{x}, ...] respects
the local variable of same name in the Module. So there really are
two qualitatively different ways of handling this situation. The
decision on how to handle this in Mathematica was not made lightly.
Among the many considerations was the observation that most people
think of applying a rule as a qualitatively different operation
than evaluation of nested scoping constructs, and in particular
expect things like With[{x = 99}, Module[{x}, ...]] to be handled
differently than things like f[99] /. f[x_] :> Module[{x}, ...].

People who expect rule application to be handled like another
scoping construct may very well be disappointed by this design
choice. I'm not sure it is possible to design a programming
language that matches everyone's expectations. I would claim,
however, that there is ample precedent in other programming
languages for this aspect of the design of Mathematica, that
there is no absolute principle for choosing one design or the
other, and that in some sense it comes down to choosing what
will be most useful to most users most of the time.

> I tried in my previous post to express what I think would have to be
> changed to accommodate "ideal" behavior. In essence, some processing (and
> therefore unHolding) of the RHS of := -- to determine the locals and look
> for name clashes, and if neccessary preempt the pattern matcher -- would
> have to occur before the value that the system has determined for the
> pattern x_ on LHS is passed in to the RHS. Currently, this passing is
> essentially instantaneous.

Yes, that is the other possibility (e.g. the behavior of the second
example above). Things could certainly be done that. It is obviously
debatable, of course, that this alternative is "ideal".

> 2) My comment about the local x$9 reemerging as a de facto global (growing
> wings as it were and flying the coop) does seem relevant to Fateman's
> concern about scope violation and "escaping" variables. Variables like x$9
> are normally off-limits to programmers outside of the subroutine in which
> they are declared as local. Does Mathematica rely on the uniqueness of x$n
> variable names to keep track internally of multiple versions of global rules
> generated programmatically inside a Module, by using them in effect as part
> of their "signature"? I know that I can change rules after the fact (i.e.,
> after the scope of x$n as originally declared in its subroutine has
> disappeared) by changing the x$n to which they have been "hard-wired". Of
> course, no one who has used Mathematica entertains for a moment the
> possibility that local variables are escaping wholesale -- this would make
> Mathematica completely unusable, whereas in practice it's eminently usable
> (albeit with a steep learning curve). But the observed phenomenon does seem
> to be a kind of "back door" and therefore not exactly kosher...

This is an observation about an implementational detail, rather than
anything fundamental about the language. Values of local variables
are essentially always accessible in any programming system. In typical
C or Fortran implementations, for example, you can inspect or modify
values of arbitrary local variables by using system-dependent commands
to determine the corresponding memory locations. The only difference
is that, in Mathematica, those variables are more accessible. In
Mathematica you can do it by finding the right sym$nnn variable
(analogous to finding the right memory location in other systems)
and then using ordinary evaluation or assignment (analogous to using
memory "peek" and "poke" functions in other systems). So that "back
door" exists in any system.

A lot of people rather like the accessibility of these private
variables, especially for debugging purposes. It would be possible
to make them more well hidden in Mathematica by removing them from
the symbol table, but I hope that that doesn't happen.

There is a fairly clear statement in the documentation not to
mess with these variables unless you know what these variables
are doing and you have a good reason to mess with them.

Since I don't know what "run setRules" means (evaluate SetRules[] perhaps?)
or what "do DownValues[\[SmallCircle]" means (DownValues[\[SmallCircle]] is
a syntax error), and I don't know what this function is supposed to do, I
can't comment on this example exactly, but I am guessing that the problem
is with arguments that are held unevaluated and has nothing to do with
variable localization. I am guessing, for example, that Module could be
dropped from this example and it still wouldn't do what was intended.
That problem can be corrected too, but it is separate issue.

> A side observation possibly of interest: If we change the code in setRules
> so that S is not first copied to symL (i.e., not "mediated") but used
> directly in the rule, the value of S does appear when the rule is examined
> using DownValues. This seems to shed some light on Mathematica's timing --
> the value found for S_ is passed to RHS of := very early and is not held but
> treated as "raw".

I don't understand exactly what this example is either (did you perhaps
mean sym used directly, rather than S?), but if that guess is correct
then yes, rule application is a way of getting values into held expressions
and into scoping contructs like SetDelayed, both of which appear to
be needed here.

Dave Withoff
Wolfram Research

0 new messages