Can a Symbol have more than one OwnValue?
Yes, it can, but only the first matching rule gets applied:
ClearAll[x];
OwnValues[x] = {x :> 1, x :> 2};
OwnValues[x]
Definition[x]
x
{HoldPattern[x] :> 1, HoldPattern[x] :> 2}
x : = 1
x : = 2
1
Compare also to
ClearAll[x];
OwnValues[x] = {x -> 1, x -> 2};
OwnValues[x]
Definition[x]
x
{HoldPattern[x] :> 1, HoldPattern[x] :> 2}
x = 1
x = 2
1
In a comment, Leonid brought up conditional rules in order to point out that it is really the first matching rule that applies. Here is an example that shows that you can do "interesting" things with it:
ClearAll[x];
b = False;
OwnValues[x] = {x :> (b = False; 1) /; b, x :> (b = True; -1) /; ! b};
This way, the "value" of x
after evaluation depends on the state of the boolean b
. As the OwnValues
of x
contain rules with side effects that change the state of b
, this implies that the "value" of x
changes every time it is evaluated.
Table[x, {10}]
{-1, 1, -1, 1, -1, 1, -1, 1, -1, 1}
The answer is yes, as Henrik Schumacher's answer pointed out. Leonid Shifrin gave a more natural way to get multiple OwnValues
in the comments to Henrik's answer. However, the situation is more complicated and appears to expose some undefined/inconsistent behavior.
Unconditional Assignments
As Henrik's answer explains, one can write to OwnValues[x]
:
ClearAll[x];
OwnValues[x] = {x -> 1, x :> 2};
OwnValues[x]
{HoldPattern[x] :> 1, HoldPattern[x] :> 2}
Whether or not an OwnValue
is a Set
or SetDelayed
is not reported by OwnValues[x]
but is reported by Definition[x]
:
Definition[x]
x = 1 x := 2
The ordering of OwnValues[x]
matters. The first rule (actually, the first rule that matches, see below) determines what x
evaluates to.
Setting OwnValues[x]
directly should be avoided, as it can lead to inconsistent behavior (see last section) and can circumvent Mathematica's behavior of placing more specific rules before more general rules as described in the documentation:
If a new rule that you give is determined to be more specific than existing rules, it is, however, placed before them. When the rules are used, they are tested in order.
Conditional Assignments
Leonid Shifrin provides another way to obtain multiple OwnValues
, namely conditional assignment. The placement of the condition determines whether the rule is prepended or appended:
ClearAll[x];
(* Appends the rules to OwnValues[x]. *)
x /; TrueQ[y] := 1;
x /; !TrueQ[y] := 2;
(* Prepends the rules to OwnValues[x]. *)
x := 4 /; EvenQ[y];
x := 1 /; OddQ[y];
OwnValues[x]
{HoldPattern[x] :> 4 /; EvenQ[y], HoldPattern[x] :> 1 /; OddQ[y], HoldPattern[x /; TrueQ[y]] :> 1, HoldPattern[x /; ! TrueQ[y]] :> 2}
The first rule that matches is what x
evaluates to. (Note that this example uses SetDelayed
.)
Set
versus SetDelayed
With existing OwnValues
The behavior of Set
is different from SetDelayed
. Multiple OwnValues
of the form x /; TrueQ[y] = 1;
(condition on the lhs) can coexist with each other and with any form of SetDelayed
:
ClearAll[x];
x /; TrueQ[y] = 1;
x /; ! TrueQ[y] = 2;
x := 3;
OwnValues[x]
{HoldPattern[x] :> 3, HoldPattern[x /; TrueQ[y]] :> 1, HoldPattern[x /; ! TrueQ[y]] :> 2}
However, a call of the form x = 1
or x = 2 /; EvenQ[y]
(condition on the rhs) will always clear any existing members of OwnValues[x]
, no matter its contents:
ClearAll[x];
x /; TrueQ[y] := 1;
OwnValues[x]
x = 2 /; EvenQ[y];
OwnValues[x]
{HoldPattern[x /; TrueQ[y]] :> 1} {HoldPattern[x] :> 2 /; EvenQ[y]}
This is not true of (unconditional) SetDelayed
which only replaces the first rule of the form x:>1
or x->1
in OwnValues[x]
, if such a rule exists:
ClearAll[x];
OwnValues[x] = {x -> 1, x -> 2}; (* However, see last section. *)
x /; TrueQ[y] := 3;
OwnValues[x]
x := 4;
OwnValues[x]
{HoldPattern[x] :> 1, HoldPattern[x] :> 2, HoldPattern[x /; TrueQ[y]] :> 3} {HoldPattern[x] :> 4, HoldPattern[x] :> 2, HoldPattern[x /; TrueQ[y]] :> 3}
With subsequent conditional assignments
A similar pattern holds for subsequent conditional assignments (although see last section). First with Set
:
ClearAll[x];
x = 1;
OwnValues[x]
x /; TrueQ[y] := 2;
OwnValues[x]
{HoldPattern[x] :> 1} {HoldPattern[x /; TrueQ[y]] :> 2}
Now with SetDelayed
:
ClearAll[x];
x := 1;
OwnValues[x]
x /; TrueQ[y] := 2;
OwnValues[x]
{HoldPattern[x] :> 1} {HoldPattern[x] :> 1, HoldPattern[x /; TrueQ[y]] :> 2}
Inconsistent/Undefined Behavior
It matters how a Set
rule is placed into OwnValues[x]
: whether by writing directly to OwnValues
, OwnValues[x] = {x->1}
, or "indirectly", x = 1
.
ClearAll[x];
OwnValues[x] = {x -> 1};
x /; TrueQ[y] := 2;
OwnValues[x]
{HoldPattern[x] :> 1, HoldPattern[x /; TrueQ[y]] :> 2}
Compare to
ClearAll[x];
x = 1;
x /; TrueQ[y] := 2;
OwnValues[x]
{HoldPattern[x /; TrueQ[y]] :> 2}
(As previously stated, an unconditional SetDelayed
will overwrite the first x->1
rule.)