Repository navigation
Variables
Logo variables are not bindings but mutable places stored in dynamic frames and object environments; Common Lisp provides the host machinery, but the semantics must be implemented explicitly.
Bindings are promises that a value will exist where the binding name is used. They will be implemented in line-based lexical environments introduced by
with.
Logo
- variables = places
- procedures = transformations
- objects = environments
Common Lisp implementation
- frames = alists
- objects = structs
- lookup = explicit algorithm
This preserves:
- Logo’s thinking model
- Lisp’s implementation strength
- pedagogical transparency
Logo variables live in three distinct layers:
Introduced by:
- procedure inputs (
:foo) -
local/localmake
Properties:
- dynamically scoped
- shadow outer variables
- lifetime = procedure activation
Introduced by:
make-
havemake(in objects)
Properties:
- stored in the current object
- persist beyond procedure calls
- inherited via BLOS parent chain
Global variables are the object variables of logo.
-> "Global" just means "owned by logo".
cLogos variable lookup is environment chaining plus dynamic frames*:
- check procedure-local dynamic environment
- check current object variables
- check parent objects
- ultimately check
logo.
When evaluating ❌
- walk logo-dynamic-frames (top → bottom)
- if found → return value
- else check (current-object.variables)
- else walk parent objects (left to right)
- else error
Logo variables are data, not Lisp bindings, so Logo variable lookup must be implemented manually.
(defvar *logo-dynamic-frames* '())Each frame is:
((name . value) ...)On procedure entry:
- push frame On exit:
- pop frame
Each object including logo has:
variables : hash-table (name -> value)
inherited via BLOS parent chain.
local "x
make "x 10
Meaning:
- introduce a new dynamic slot
- shadow outer
x - lifetime = current procedure
Implementation:
(push-frame (list (cons 'x *unassigned*)))make then mutates that slot.
Logo is a medium for thinking. Variables are places where that thinking can settle, change, and be observed.
Major Principle Variables in Logo are not conveniences for the machine. They are cognitive anchors for the learner. Any implementation choice that weakens this role is invalid.
- A Logo variable denotes a mutable place associated with a name.
- Variables are not lexical bindings and not immutable values.
- Assignment (
make,localmake,havemake) changes the content of a place, not the structure of an expression.
Invariant: No variable operation may rely on lexical binding semantics.
- Variable names are Logo words.
- Variable lookup is performed by symbolic name, not by host-language identifiers.
- Variable existence is discoverable and inspectable.
Invariant: Variables must not be compiled into or hidden behind host-language bindings.
- Variable resolution is dynamic, not lexical.
- The active variable environment is determined by the runtime call context.
- Later calls may affect earlier variable meanings.
Invariant:
Any form of lexical scoping must be introduced explicitly and locally
(e.g. with) and must not replace dynamic scope.
Logo variables exist in exactly three conceptual strata:
-
Procedure-local variables
- Introduced by procedure inputs, local, localmake
- Lifetime: procedure activation
- Highest lookup priority
-
Object variables
- Introduced by make, havemake
- Owned by the current object
- Persist beyond procedure calls
-
Global variables
- Object variables of the root object logo
- No special global mechanism exists
Invariant: No variable may bypass these strata or collapse them.
Variable lookup proceeds strictly in this order:
- Procedure-local dynamic frames (most recent first)
- Current object variables
- Parent object variables (left-to-right, depth-first)
- Root object (logo)
Invariant: This order is not configurable and must be preserved exactly.
-
makemodifies the nearest accessible variable place. -
localmakealways creates or modifies a procedure-local place. -
havemakealways creates or modifies an object-local place.
Invariant: Assignment must never silently create variables in unintended strata.
- Inner variables may shadow outer ones.
- Shadowing is temporary and context-bound.
- The system must support querying ownership (whosename).
Invariant: Shadowing must be transparent and introspectable.
- Every variable place has an owner:
- a procedure frame, or
- an object
- Ownership determines lifetime, visibility, and mutation rights.
Invariant: Variable ownership must be representable and queryable at runtime.
- Variable semantics are identical in:
- primitive procedures
- user procedures
- object methods
- turtle commands
- No evaluation context may introduce special variable rules.
Invariant: Variables behave the same across all execution contexts.
- Referencing an inaccessible variable is an error.
- Silent fallbacks or implicit defaults are not permitted.
- Errors must report which name and why it failed.
Invariant: Variable errors must be pedagogically informative.
- All Berkeley Logo variable behaviour must be reproducible.
- Any deviation must be:
- explicitly documented
- pedagogically justified
Invariant: If Berkeley Logo accepts a variable program, cLogos must accept it with identical meaning.
- The host language (Common Lisp) must not leak:
- bindings
- scoping rules
- mutation semantics
- The host language is an implementation detail.
Invariant: Logo variables must remain Logo variables, conceptually and observably.
🄯 2026 cLogos Initiative represented by Lispl-Wicht -- The textual content of this work is licensed under the Creative Commons Attribution 4.0 International License (CC BY 4.0).