Wolfram Language Warts

By Xah Lee. Date: . Last updated: .

this is a collection of weirdness or usual behavior in Wolfram language.

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 *)

Dynamic Scope (Block, Table, Do, Sum)

leaked variable when using Table, due to dynamic scope. (same happens with • BlockDoSum )

Solution: Avoid defining global variables with common short names, or, use uncommon names in Table or Block etc.

Example. Table

(* leaked x. *)

y = x;
Table[ x+y, {x, 1, 4}]

(*
output
{2, 4, 6, 8}

expect
{1 + x, 2 + x, 3 + x, 4 + x}
*)

Example. Block

(* dynamic scope of Block *)

Clear[x,y];
y = x;
Block[ {x=3}, y ]
(* 3 *)

Module and With, No Variable Chain

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. but is slow.

Module works by creating temp symbols for each of your local variable, and also internally increment a module variable counter in doing so.

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 leaking values from outside.

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 = (1 + x)}, Function[x, aa]]
(* Function[x$, aa$1539] *)

xx[y]
(* 1 + x *)
(* 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 ] ;

Syntax Shortcut Exception, Breaking Systematic Grammar?

not sure how to describe this, but it seems to break some minor syntactic consistency.

Optional

WolframLang syntax wart 2024-09-22 VQhKy
WolframLang syntax wart 2024-09-22 VQhKy

is this a bug

(* why is this, bug ? *)

ReplaceAll[
{1, 2, 9, 3, 8, 2},
{x__, s:OrderlessPatternSequence[ 3,8,9 ], y__} -> {x, y, g[s]}
]

(* {1, 2, 9, 3, 8, 2} *)

Credit: most of these are are documented in Wolfram language documentation.