%% kernel language examples local X in X = 1 end local X Y T Z in X = 5 Y = 10 T = (X>=Y) if T then Z = X else Z = Y end {Browse Z} end % higher-level language example: local I in fun {I X} X end {Browse {I 5}} end % translates to kernel language: local I in I = proc {$ X Y} Y = X end % function converted to a procedure local T in {I 5 T} % nested procedure call expanded {Browse T} % with temporary variable creation end end % a square routine in extended kernel language % (with multiple variable initialization) local S T in S = proc {$ X Y} Y = X*X end {S 5 T} {Browse T} end % abstracting over statement "if X >= Y then Z = X else Z = Y end" declare Max in proc {Max X Y Z} if X >= Y then Z = X else Z = Y end end {Browse {Max 5 7}} % exercise: translate above call into the kernel language. % abstracting over partial set of free variable identifiers declare LowerBound Y in proc {LowerBound X Z} if X >= Y then Z = X else Z = Y end end {Browse {LowerBound 4}} % blocks because Y is unbound Y = 5 % cannot execute yet because this statement's thread is blocked. Y = 7 % assigns 7 to Y's store variable and resumes the blocked % computation above. % In interactive environment, every statement is executed in a % separate thread. Notice that the newline above the "Y = 7" % statement is therefore significant! % After {LowerBound 4} is displayed, "Y = 5" is executed % producing a failure: "7 = 5" {Browse {LowerBound 6}} {Browse {LowerBound 8}} % exercise: add an empty line before "Y = 5" and execute these % statements in a fresh Oz emulator (one not containing Y in the % global environment). %% lexical scope revisited: %% a variable refers to the closest enclosing declaration local X in % creates a variable in the store X = 1 local X in % creates a variable in the store X = 2 {Browse X} % refers to end {Browse X} % refers to end % Res appears free in following statement: not runnable. local Arg1 Arg2 in Arg1 = 111*111 Arg2 = 999*999 Res = Arg1*Arg2 end % No free variable identifiers: runnable statement. local Res in local Arg1 Arg2 in Arg1 = 111*111 Arg2 = 999*999 Res = Arg1*Arg2 end {Browse Res} end % Creating procedure values: local P Q in Q = proc {$} {Browse hello} end P = proc {$} {Q} end local Q in Q = proc {$} {Browse hi} end {P} end end % what does it display? %% dataflow variables revisited: local X Y Z in X = 5 Y = 6 Z = X+Y {Browse [X Y Z]} end local X Y Z in Z = X+Y % will block forever (X and Y are not bound, "+" suspends) X = 5 Y = 6 {Browse [X Y Z]} end local X Y Z in thread Z = X+Y end % will wait until parent thread assigns X and Y X = 5 Y = 6 {Browse [X Y Z]} end local X Y Z in thread Z = X+Y end % will wait forever for Y X = 5 Z = 6 {Browse [X Y Z]} end local X Y Z in thread Z = X+Y end % after Y is assigned 1, it resumes execution: % compatible assignment "6 = 6" X = 5 Z = 6 {Browse [X Y Z]} Y = 1 end local X Y Z in thread Z = X+Y end % after Y is assigned 2, it resumes execution: % incompatible assignment "6 = 7" displays failure % but store assignments remain X=5 Y=6 Z=2 X = 5 Z = 6 {Browse [X Y Z]} Y = 2 end % failures halt execution of a composite statement, e.g.: local X Y Z in thread Z = X+Y % after Y is assigned 2, it resumes execution: % incompatible assignment "6 = 7" displays failure {Browse Z} % Z is not displayed. end X = 5 Z = 6 {Browse [X Y Z]} Y = 2 end local X Y Z in thread Z = X+Y % after Y is assigned 1, it resumes execution: % compatible assignment "6 = 6" {Browse Z} % Z is displayed. end X = 5 Z = 6 {Browse [X Y Z]} Y = 1 end % %% On recursive computation % %sumlist declare fun {SumList L} case L of nil then 0 [] X|L2 then X+{SumList L2} end end {Browse {SumList [1 2 3 4]}} %map declare fun {Map Xs F} case Xs of nil then nil [] X|Xr then {F X}|{Map Xr F} end end {Browse {Map [1 2 3 4] fun {$ I} I*I end}} %filter declare fun {Filter Xs P} case Xs of nil then nil [] X|Xr andthen {P X} then X|{Filter Xr P} [] X|Xr then {Filter Xr P} end end {Browse {Filter [1 2 3 4] fun {$ A} A<3 end}} %minus declare fun {Minus L X} {Filter L fun {$ V} V \= X end} end %freevars declare fun {FreeVars E} if {IsAtom E} then [E] else case E of [F A] then {Append {FreeVars F} {FreeVars A}} else V = {Arity E}.1 in {Minus {FreeVars E.V} V} end end end %iscombinator declare fun {IsCombinator E} {FreeVars E} == nil end {Browse {IsCombinator lambda(x:x)}} {Browse {IsCombinator x}} {Browse {IsCombinator [lambda(x:x) y]}} {Browse {IsCombinator [lambda(x:x) x]}} {Browse {IsCombinator lambda(x:[x x])}} {Browse {IsCombinator [lambda(x:[x x]) lambda(x:[x x])]}}