# Lesson X The name does not move the brush. It keeps the hand from wandering. ## Try ```prolog ?- infer(kernel, [push(quote([dup, mul])), call], Effect). Effect = effect([int|S], [int|S]). ?- run(kernel, [push(int(4)), push(quote([dup, mul])), call], [], Stack). Stack = [int(16)]. ``` ## Lesson We passed an environment but primitives still lived outside that context. Remove the unindexed word rows and `empty_env/1`. The kernel itself becomes the base lookup context. That change is more than naming. `find/4` now copies rows from the selected environment, so the same call shape can later search extended environments without changing runtime or inference again. > [!info]- Change > ```diff > - word(dup, [A|S] -- [A, A|S], true). > - word(drop, [_|S] -- S, true). > - word(swap, [A, B|S] -- [B, A|S], true). > - word(over, [A, B|S] -- [B, A, B|S], true). > - word(add, [A::int, B::int|S] -- [C::int|S], C is B + A). > - word(sub, [A::int, B::int|S] -- [C::int|S], C is B - A). > - word(mul, [A::int, B::int|S] -- [C::int|S], C is B * A). > - > - apply(_Env, Word, Stack0, Stack) :- > - word(Word, InPattern -- OutPattern, Goal), > - bind(InPattern, Stack0), > - call(Goal), > - build(OutPattern, Stack). > - > - infer1(_Env, Word, Stack0, Stack) :- > - word(Word, InPattern -- OutPattern, _Goal), > - types(InPattern, Stack0), > - types(OutPattern, Stack). > - > - empty_env(env([])). > ``` Primitive rows are the single source for fixed words. They describe stack shape and runtime computation for words whose meaning does not depend on a literal argument. The base environment is the atom `kernel`. Primitive words are explicit environment-indexed clauses. The environment argument is what makes the kernel a lookup context instead of a generated list of rows. ```prolog word(kernel, dup, [A|S] -- [A, A|S], true). word(kernel, drop, [_|S] -- S, true). word(kernel, swap, [A, B|S] -- [B, A|S], true). word(kernel, over, [A, B|S] -- [B, A, B|S], true). word(kernel, add, [A::int, B::int|S] -- [C::int|S], C is B + A). word(kernel, sub, [A::int, B::int|S] -- [C::int|S], C is B - A). word(kernel, mul, [A::int, B::int|S] -- [C::int|S], C is B * A). ``` Find searches the current environment for a word clause, then copies the stored row so variables in primitive effects stay fresh for each use. ```prolog find(Env0, Word, InOut, Goal) :- nonvar(Env0), word(Env0, Word, StoredInOut, StoredGoal), copy_term(word(Word, StoredInOut, StoredGoal), word(Word, InOut, Goal)). ``` Fixed words project through primitive rows. ```prolog apply(Env, Word, Stack0, Stack) :- find(Env, Word, InPattern -- OutPattern, Goal), bind(InPattern, Stack0), call(Goal), build(OutPattern, Stack). infer1(Env, Word, Stack0, Stack) :- find(Env, Word, InPattern -- OutPattern, _Goal), types(InPattern, Stack0), types(OutPattern, Stack). ``` [[09_lesson|Prev]] | [[11_lesson|Next]]