Variables - Lispl-Wicht/c-logo-s GitHub Wiki
Logo 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
The three variable strata in Logo
Logo variables live in three distinct layers:
Procedure-local variables
Introduced by:
- procedure inputs (
:foo) local/localmake
Properties:
- dynamically scoped
- shadow outer variables
- lifetime = procedure activation
Object variables (workspace variables)
Introduced by:
makehavemake(in objects)
Properties:
- stored in the current object
- persist beyond procedure calls
- inherited via BLOS parent chain
Global variables
Global variables are the object variables of logo.
-> "Global" just means "owned by logo".
Dynamic scope: what cLogos actually does
cLogos variable lookup is environment chaining plus dynamic frames*:
- check procedure-local dynamic environment
- check current object variables
- check parent objects
- ultimately check
logo.
Variable lookup algorithm (precise)
When evaluating :x:
- walk logo-dynamic-frames (top → bottom)
- if found → return value
- else check (current-object.variables)
- else walk parent objects (left to right)
- else error
Common Lisp model
Logo variables are data, not Lisp bindings, so Logo variable lookup must be implemented manually.
Dynamic procedure frame stack
(defvar *logo-dynamic-frames* '())
Each frame is:
((name . value) ...)
On procedure entry:
- push frame On exit:
- pop frame
Object variable tables
Each object including logo has:
variables : hash-table (name -> value)
inherited via BLOS parent chain.
local
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.
Invariants
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.
1. Variables are places, not bindings
- 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.
2. Variable names are symbolic data
- 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.
3. Dynamic scope is normative
- 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.
4. Three variable strata exist and are distinct
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.
5. Variable lookup order is fixed
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.
6. Assignment respects existing places
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.
7. Variable shadowing is allowed and visible
- 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.
8. Variable ownership is semantic, not syntactic
- 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.
9. Variables are independent of evaluation regime
- 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.
10. Error behaviour is explicit
- 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.
11. Compatibility with Berkeley Logo is mandatory
- 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.
12. Host-language isolation
- 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.