Wolfram Language Warts

By Xah Lee. Date: . Last updated: .

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:

(* 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.