Wolfram Language Warts
this is a collection of weirdness or usual behavior in WolframLang.
Equality Problem
Equal
does not return True
or False
even for obvious cases.
This is probably because, equal needs to represent equations, e.g.
x^2+ 3 == y
{} == 2 (* return expression as is. Version 13 *) (* using Reduce makes it true *) Reduce[ {} == 2 ] === True {{1}} == {2} (* return expression as is. Version 13 *) {{1.0}} == {2.0} (* return expression as is *)
Table, Leaked Variable
leaked variable when using Table
, due to dynamic scope.
(same happens with
Do
,
Sum
etc
)
(* leaked x *) y = x; Table[ x+y, {x, 1, 4}] (* output {2, 4, 6, 8} expect {1 + x, 2 + x, 3 + x, 4 + x} this is due to dynamic scope used in Table. *)
Dynamic Scope of Block
(* dynamic scope of Block *) (* any symbol, in the body of Block, including any expression's value or value of value etc, if it has the same name as the local variable in Block, the Block's local value overrides it. *) Clear[x,y]; y = x; Block[ {x=3}, y ] (* 3 *) Clear[x,y,z]; y = z; z = x; Block[ {x=3}, y ] (* 3 *) (* when using Block, make sure that its body, any possible value encountered when evaluating it, does not encounter a name that is the same as your local variable. *)
Module and With, Later Variable Do Not See Previous Local Variable's Value
(* Module, later variable do not see previous local variable's value *) Module[ {x=3, y=x+1}, y ] (* 1 + x *) (* expect 4 *) (* work around is to always assign values in the body. *) Module[ {x, y}, x=3; y=x+1; y] (* 4 *)
(* With, later variable do not see previous local variable's value *) With[ {x=3, y=x}, y ] (* return x *)
Block
do not have this problem
(* with Block, later variables do see previous local variable's value *) Block[ {x=3, y=x}, y ] (* return 3 *)
Module, Slow and Creating Temp Symbols
Module
is lexical scope.
However, it creates intermediate symbols
(temp variables) for each of your local variable, and increment a module variable counter in doing so, and these symbols are exposed to the user.
And because of this, is slow.
practically, this means:
- do not use
Module
in a loop (slow) - sometimes you may see names such as x$1218 that you never declared, in the result.
(* scoping construct complexity *) Print[ $ModuleNumber ] (* 1218 *) Module[ {x}, Print[ x ] ] (* x$1218 *) Print[ $ModuleNumber ] (* 1219 *)
note, With
, do not have this creating new symbols problem.
however, later variable do not see previous variable value.
this makes With
much less useful.
Block
also do not have this creating new symbols problem.
however, its dynamic scoping creates unexpected shadowing of variable.
Clear[x,y]; y = x; With[ {x=3}, y ] (* x *)
Function is Not a Black Box
This is some weird effect, due to the nature of term rewriting system.
A function (here, the Function
), is not a black box unit.
It is merely a sequence of symbols (terms), that is ready to interact, be replaced, by rewriting rules.
xx = Module[{aa = Expand[(1 + x)^2]}, Function[x, aa]] (* Function[x$, aa$1218] *) xx[y] (* 1 + 2*x + x^2 *)
(* correct behavior *) Clear[x,y]; y = x; Function[{x}, x+y][4] (* 4 + x *)
this is some sort of referencial transparency issue, or non-functional semantics.
(* example of non-functional semantics in WolframLang. or, violate referencial transparency principle. or, something. *) Clear[ f ]; (* defining a function with optional named parameters *) Options[ f ] = {xyz -> 4}; f[OptionsPattern[]] := OptionValue[ xyz ] ;
Credit: many of these are are documented in Wolfram language.