The pymdl book
7. Values of atoms
4.1. General
There are two kinds of "value" which can be attached to an ATOM. An ATOM
can have either, both, or neither. They interact in no way (except that
alternately referring to one and then the other is inefficient). These two
values are referred to as the local value and the global value of an
ATOM. The terms "local" and "global" are relative to PROCESSes (chapter
22), not functions or programs. The SUBRs which reference the local and
global values of an ATOM, and some of the characteristics of local versus
global values, follow.
Measured, MDL 55, 2026-08-30. "Attached to an
ATOM" is the whole of it: a value cell belongs to an atom, not to a name. Two atoms that share aPNAMEon different oblists are different variables:<SET FOO 1> ⇒ 1 <SET FOO!-INTERRUPTS 2> ⇒ 2 .FOO ⇒ 1 .FOO!-INTERRUPTS ⇒ 2pymdl keyed local values by the bare name until that was measured, so it had one
FOOwhere the era has two. Chapter 18 has the rest of the evidence and what it cost; the same fact is why chapter 28's package system works at all.
4.2. Global Values
4.2.1. SETG
A global value can be assigned to an ATOM by the SUBR SETG ("set
global"), as in
<SETG atom any>
where atom must EVAL to an ATOM, and any can EVAL to anything. EVAL
of the second argument becomes the global value of EVAL of the first
argument. The value returned by the SETG is its second argument, namely the
new global value of atom.
Examples:
<SETG FOO <SETG BAR 500>> ⇒ 500
The above made the global values of both the ATOM FOO and the ATOM BAR
equal to the FIXed-point number 500.
<SETG BAR 500> ⇒ 500
<SETG BAR FOO> ⇒ FOO
That made the global value of the ATOM BAR equal to the ATOM FOO.
4.2.2. GVAL
The SUBR GVAL ("global value") is used to reference the global value of an
ATOM.
<GVAL atom>
returns as a value the global value of atom. If atom does not evaluate to an
ATOM, or if the ATOM to which it evaluates has no global value, an error
occurs.
GVAL applied to an ATOM anywhere, in any PROCESS, in any function, will
return the same value. Any SETG anywhere changes the global value for
everybody. Global values are context-independent.
READ understands the character , (comma) as an abbreviation for an
application of GVAL to whatever follows it. PRINT always translates an
application of GVAL into the comma format. The following are absolutely
equivalent:
,atom <GVAL atom>
Assuming the examples in section 4.2.1 were carried out in the order given, the following will evaluate as indicated:
<SETG FOO <SETG BAR 500>> ⇒ 500
<SETG BAR FOO> ⇒ FOO
,FOO ⇒ 500
<GVAL FOO> ⇒ 500
,BAR ⇒ FOO
,,BAR ⇒ 500
'<GVAL FOO> ⇒ ,FOO
The last line is the printing half of the rule: an application of GVAL,
quoted so that it is not performed, prints in the comma format it would have
been read from.
4.2.3. Note on SUBRs and FSUBRs
The initial GVALs of the ATOMs used to refer to MDL "built-in"
Subroutines are the SUBRs and FSUBRs which actually get applied when those
ATOMs are referenced. If you don't like the way those supplied routines
work, you are perfectly free to SETG the ATOMs to your own versions.
<TYPE ,LENGTH> ⇒ SUBR
<SETG LENGTH <FUNCTION (X) 42>>
<LENGTH '(1 2 3)> ⇒ 42
pymdl's own. Freely, and it is not a trick: the built-in was only ever the atom's initial global value, and replacing it replaces what gets applied. Era programs do this on purpose -- chapter 34's self-hosting had to put the compiler's own
DATEandRTIMEback after a library file redefined them, because the compiler runs on those, and MDL 55 breaks the same way whenDATEis redefined under it. The one place the substitution does not reach is compiled code that has been linked (chapter 33): a linked call has already cached the callee.
4.2.4. GUNASSIGN
<GUNASSIGN atom>
("global unassign") causes atom to have no assigned global value, whether or not it had one previously. The storage used for the global value can become free for other uses.
<SETG A 1> ⇒ 1
<GASSIGNED? A> ⇒ T
<GUNASSIGN A> ⇒ A
<GASSIGNED? A> ⇒ #FALSE ()
4.3. Local Values
4.3.1. SET
The SUBR SET is used to assign a local value to an ATOM. Applications
of SET are of the form
<SET atom any>
SET returns EVAL of any just like SETG.
Examples:
<SET BAR <SET FOO 100>> ⇒ 100
Both BAR and FOO have been given local values equal to the FIXed-point
number 100.
<SET FOO BAR> ⇒ BAR
FOO has been given the local value BAR.
Note that neither of the above did anything to any global values FOO and
BAR might have had.
<SETG FOO 500> ⇒ 500
<SET FOO 100> ⇒ 100
,FOO ⇒ 500
.FOO ⇒ 100
4.3.2. LVAL
The SUBR used to extract the local value of an ATOM is named LVAL. As
with GVAL, READ understands an abbreviation for an application of LVAL:
the character . (period), and PRINT produces it. The following two
representations are equivalent, and when EVAL operates on the corresponding
MDL object, it returns the current local value of atom:
<LVAL atom> .atom
The local value of an ATOM is unique within a PROCESS. SETting an
ATOM in one PROCESS has no effect on its LVAL in another PROCESS,
because each PROCESS has its own "control stack" (chapters 22 and 24).
Assume all of the previous examples in this chapter have been done. Then the following evaluate as indicated:
<SETG FOO <SETG BAR 500>> ⇒ 500
<SETG BAR FOO> ⇒ FOO
<SET BAR <SET FOO 100>> ⇒ 100
<SET FOO BAR> ⇒ BAR
.BAR ⇒ 100
<LVAL BAR> ⇒ 100
.FOO ⇒ BAR
,.FOO ⇒ FOO
'<LVAL BAR> ⇒ .BAR
The last two lines are worth reading slowly. ,.FOO is <GVAL <LVAL FOO>>:
the local value of FOO is the ATOM BAR, and the global value of BAR is
the ATOM FOO. And an application of LVAL, like one of GVAL, prints in
the abbreviation it reads from.
Measured, MDL 55, 2026-08-16 and 2026-08-17. Both
SETandLVALtake an optionalENVIRONMENT(chapter 12), and the era rejects anything else there rather than ignoring it:<PROG ((ZA 1)) <SET ZA 2 0>>isSECOND-ARG-WRONG-TYPE SET, andLVAL,VALUE,UNASSIGNandLLOCanswer the same for their own names. Note thatSET's environment is its third argument and the banner still saysSECOND: the era's banners do not track the position, which is the same per-SUBRirregularity chapter 6 describes. pymdl ignored the extra argument until this was measured.The atom argument is irregular too, in a different direction:
<SETG 5 1>,<LVAL 5>,<GVAL 5>and<VALUE 5>areNON-ATOMIC-ARGUMENT, but<SET 5 1>isFIRST-ARG-WRONG-TYPE SET.
4.3.3. UNASSIGN
<UNASSIGN atom>
causes atom to have no assigned local value, whether or not it had one previously.
<SET A 1> ⇒ 1
<ASSIGNED? A> ⇒ T
<UNASSIGN A> ⇒ A
<ASSIGNED? A> ⇒ #FALSE ()
<BOUND? A> ⇒ T
Measured, MDL 55. The last line is the distinction chapter 12 turns on and this section does not mention:
UNASSIGNleaves the binding in place and takes away only the value, so the atom is bound-but-unassigned andBOUND?still answersT. That is the interpreter's ownUNASIT, confirmed against the era.
4.4. VALUE
VALUE is a SUBR which takes an ATOM as an argument, and then:
- if the
ATOMhas anLVAL, returns theLVAL; - if the
ATOMhas noLVALbut has aGVAL, returns theGVAL; - if the
ATOMhas neither aGVALnor anLVAL, calls theERRORfunction.
This order of seeking a value is the opposite of that used when an ATOM
is the first element of a FORM. The latter will be called the G/LVAL, even
though that name is not used in MDL.
Example:
<UNASSIGN A> ⇒ A
<SETG A 1> ⇒ 1
<VALUE A> ⇒ 1
<SET A 2> ⇒ 2
<VALUE A> ⇒ 2
,A ⇒ 1
Found along the way. The two orders are not a curiosity; both are load-bearing. The G/LVAL order is what lets a program
SETa variable whose name is also a built-in's without breaking the call, and it is what chapter 30's dynamic loader hooks.VALUE's order is what the compiled code of chapter 34 has to preserve, and it is why anATOMwhose value is read at construction time refuses right there if it is unbound -- the era builds a pair list with one call per atom, so an unbound atom complains withVALUEnamed as the complainer, and pymdl deferring that read silently masked it until it was measured.