Function ⋆Values and Definition Clearing

DownValues

If OwnValues are standard value bindings, DownValues are your basic function bindings:

f[x_] := x

DownValues@f

(*Out:*)

{HoldPattern[f[x_]] :> x}

This is also why we can define functions as patterns. All that happens is a series of replacement rules are tried, based on the DownValues of the expression. Really, one can imagine that all Mathematica does to execute an expression is apply ReplaceRepeated on the ⋆Values .

Obviously the system is more complex, because of Attributes and the coming discussion of evaluation order and things, and also more optimized, but it’s a good concept to keep in mind.

Just like with OwnValues we can manipulate the DownValues via

One final thing. On the name DownValues : one can imagine that the system is looking “down-stream” in the expression to see if the arguments match the defined replacement pattern.

UpValues

UpValues are a highly useful, if not necessarily intuitive feature of the expression structure. While DownValues look “down-stream”, UpValues look “up-stream”. What this means in practice is they are patterns applied on an expression by the arguments of the expression which are, in a way, looking “up-stream”. This is probably clearest via example, but first we need to know how UpValues are set.

First off, there is a function UpSet ( ^= ) and it’s partner UpSetDelayed ( ^:= ) which will do this

h[b[c___]] ^:= b[h, c]

This has set UpValues on b :

UpValues@b

(*Out:*)

{HoldPattern[h[b[c___]]] :> b[h, c]}

Then let’s test this:

h[b[1, 3, 4, 2, 1]]

(*Out:*)

b[h, 1, 3, 4, 2, 1]

The most useful aspect of this behavior is that it requires only that we give definitions to the down-stream symbol, not the head, so we can use this to “overload” the basic functionality of a built-in function, which is more efficient and also cleaner and safer.

Moreover, this means we can apply definitions to functions which we otherwise couldn’t. We’ll demonstrate this with the MessageName function. Aliased with ::

I’ll also demonstrate the better way to set these definitions, using TagSet ( /: )

AssociationInterface /: HoldPattern[
   MessageName[AssociationInterface[a_Association], key_]
   ] := a[key];

TagSet only sets the definition on the symbol to the left, unlike UpSet which sets the definition on every argument.

The HoldPattern is necessary to make sure the expression doesn’t evaluate while we set the UpValue , which will make more sense when we get to discussions of evaluation order.

Now we can see how our definition works:

AssociationInterface[<|
   "a" -> b,
   "b" -> d,
   "e" -> f
   |>]::a

(*Out:*)

b

MessageName automatically converts its second argument to a String , so the keys of our Association need to be strings, but we can see the definition works.

One thing that should be mentioned before moving on is that the UpValues of the arguments of a symbol are applied before the DownValues of the enclosing head, although the DownValues of the argument itself are applied before its UpValues

SubValues

SubValues are the final type of values we need to deal with here. They provide an extension of DownValues to multiple sets of arguments as follows:

s[arg_][arg2_] := arg + arg2;

SubValues@s

(*Out:*)

{HoldPattern[s[arg_][arg2_]] :> arg + arg2}

Clear and ClearAll

With ⋆Values discussed it’s possible to understand the operations of of the functions Clear and ClearAll . Consider some symbol we’ve set a lot of definitions on:

m[1] = 1;
m[2] = 10;
m[5] = 100;
HoldPattern[m[1][3]] = 20;
m[s_String] := "soup";
HoldPattern[Print[m[x_]]] ^:= x + "Print";
m := 35

OwnValues@m

(*Out:*)

{HoldPattern[m] :> 35}

DownValues@m

(*Out:*)

{HoldPattern[m[1]] :> 1, HoldPattern[m[2]] :> 10, 
 HoldPattern[m[5]] :> 100, HoldPattern[m[s_String]] :> "soup"}

UpValues@m

(*Out:*)

{HoldPattern[HoldPattern[Print[m[x_]]]] :> x + "Print"}

SubValues@m

(*Out:*)

{HoldPattern[HoldPattern[m[1][3]]] :> 20}

All Clear does is remove the ⋆Values :

Clear@m

OwnValues@m

(*Out:*)

{}

DownValues@m

(*Out:*)

{}

UpValues@m

(*Out:*)

{}

SubValues@m

(*Out:*)

{}

ClearAll on the other hand can also remove Options and Attributes

SetAttributes[m, Listable];
Options[m] = {"why" -> "me?"};

Clear@m

Options@m
Attributes@m

(*Out:*)

{"why" -> "me?"}

(*Out:*)

{Listable}

ClearAll@m

Options@m
Attributes@m

(*Out:*)

{}

(*Out:*)

{}

results matching ""

    No results matching ""