# Lesson III First see the gesture; then make it. A hand that cannot see before moving writes blindly. ## Try ```prolog % ?- sig(over, In, Out). % In = [_A, _B|_S], % Out = [_B, _A, _B|_S]. % ?- sig(Word, [A, B], [B, A]). % Word = swap. % ?- infer([dup, swap], In, Out). % In = [_A|_S], % Out = [_A, _A|_S]. % ?- infer([swap, over], [A, B], Out). % Out = [A, B, A]. % ?- infer([swap, over], In, [A, B, A]). % In = [A, B]. ``` ## Learn ```prolog % The runtime relation `apply/3` transforms actual stack values. % This stage adds the first static relation: % % sig(Word, InputShape, OutputShape). % % Read the modes broadly: % % sig(?Word, ?InputStack, ?OutputStack). % % The relation can describe a known word, or discover which word has % a known stack shape. % % `sig/3` does not execute a word. It describes the stack shape a % word requires and produces. For the initial stack shufflers, the % static clauses look almost identical to the runtime clauses because % the words only move positions. % % Static signatures describe stack shapes without running the program. sig(dup, [A|S], [A, A|S]). sig(drop, [_|S], S). sig(swap, [A, B|S], [B, A|S]). sig(over, [A, B|S], [B, A, B|S]). % Program inference follows the same sequencing shape as runtime, but % it reads `sig/3` instead of `apply/3`. Similar structure does not % make the two relations aliases. Runtime transforms actual stack % values; inference relates static stack shapes without running the % program. % % Inference follows the same sequencing shape on static effects. infer([], Stack, Stack). infer([Word|Words], Stack0, Stack) :- sig(Word, Stack0, Stack1), infer(Words, Stack1, Stack). ```