474c4facf0 2010-11-25 kinaba: ######################################## 474c4facf0 2010-11-25 kinaba: print("----------"); 474c4facf0 2010-11-25 kinaba: 474c4facf0 2010-11-25 kinaba: @macro twice = fun(x) { x; x }; # Hello Hello 474c4facf0 2010-11-25 kinaba: twice( print("Hello") ); 474c4facf0 2010-11-25 kinaba: 474c4facf0 2010-11-25 kinaba: ######################################## 474c4facf0 2010-11-25 kinaba: print("----------"); 474c4facf0 2010-11-25 kinaba: 060f267779 2010-11-20 kinaba: @macro maxBad(x,y) { 474c4facf0 2010-11-25 kinaba: if x<y then y else x 474c4facf0 2010-11-25 kinaba: }; 474c4facf0 2010-11-25 kinaba: @macro maxGood(x,y) { 474c4facf0 2010-11-25 kinaba: var _x = x; # NOTE: no hygenic macro 474c4facf0 2010-11-25 kinaba: var _y = y; 474c4facf0 2010-11-25 kinaba: if _x < _y then _y else _x 060f267779 2010-11-20 kinaba: }; 474c4facf0 2010-11-25 kinaba: def maxFun(x,y) { 474c4facf0 2010-11-25 kinaba: if x<y then y else x 060f267779 2010-11-20 kinaba: }; 474c4facf0 2010-11-25 kinaba: @macro maxGreat(x,y){@value( 474c4facf0 2010-11-25 kinaba: var nx = gensym(); # generate fresh symbol 474c4facf0 2010-11-25 kinaba: var ny = gensym(); 474c4facf0 2010-11-25 kinaba: @macro _x = @macro(nx) {name: nx}; # cheating to create {is:"Var" .. } 474c4facf0 2010-11-25 kinaba: @macro _y = @macro(ny) {name: ny}; # at macro layer 474c4facf0 2010-11-25 kinaba: {is: "Let", name: nx, layer: "", init: @macro(x), expr: 474c4facf0 2010-11-25 kinaba: {is: "Let", name: ny, layer: "", init: @macro(y), expr: 474c4facf0 2010-11-25 kinaba: @macro(if _x < _y then _y else _x)}} # the expression 474c4facf0 2010-11-25 kinaba: )}; 3ae09b8cbf 2010-11-24 kinaba: 474c4facf0 2010-11-25 kinaba: print( maxGood(print(1), print(2)) ); # 1 2 2 474c4facf0 2010-11-25 kinaba: print( maxBad(print(1), print(2)) ); # 1 2 2 2 474c4facf0 2010-11-25 kinaba: print( maxFun(print(1), print(2)) ); # 1 2 2 474c4facf0 2010-11-25 kinaba: print( maxGreat(print(1), print(2)) ); # 1 2 2 474c4facf0 2010-11-25 kinaba: print( maxGreat(print(2), print(1)) ); # 2 1 2 474c4facf0 2010-11-25 kinaba: 474c4facf0 2010-11-25 kinaba: ######################################## 474c4facf0 2010-11-25 kinaba: print("----------"); 474c4facf0 2010-11-25 kinaba: 474c4facf0 2010-11-25 kinaba: # the variable "it" is inserted to the scope 474c4facf0 2010-11-25 kinaba: @macro LetItBe(x, y) { let it = x in y }; 474c4facf0 2010-11-25 kinaba: print( LetItBe("myself", "when I find " ~ it ~ " in times of trouble") ); 474c4facf0 2010-11-25 kinaba: 474c4facf0 2010-11-25 kinaba: ######################################## 474c4facf0 2010-11-25 kinaba: print("----------"); 474c4facf0 2010-11-25 kinaba: 474c4facf0 2010-11-25 kinaba: # layerd parameter can also be used for @macro 474c4facf0 2010-11-25 kinaba: # you can mix @macro and normal parameters!! 474c4facf0 2010-11-25 kinaba: def 3way(n, c1 @macro, c2 @macro, c3 @macro) 474c4facf0 2010-11-25 kinaba: { 474c4facf0 2010-11-25 kinaba: case n*n 474c4facf0 2010-11-25 kinaba: when 0: c1 474c4facf0 2010-11-25 kinaba: when 1: c2 474c4facf0 2010-11-25 kinaba: when 4: c3 060f267779 2010-11-20 kinaba: }; 060f267779 2010-11-20 kinaba: 474c4facf0 2010-11-25 kinaba: 3way( rand(3), print("One"), print("Two"), print("Three") ); 474c4facf0 2010-11-25 kinaba: 3way( rand(3), print("One"), print("Two"), print("Three") ); 474c4facf0 2010-11-25 kinaba: 3way( rand(3), print("One"), print("Two"), print("Three") ); 474c4facf0 2010-11-25 kinaba: 474c4facf0 2010-11-25 kinaba: ######################################## 474c4facf0 2010-11-25 kinaba: print("----------"); 474c4facf0 2010-11-25 kinaba: 474c4facf0 2010-11-25 kinaba: # Conversely, we can mix @value parameter in the macro definition 474c4facf0 2010-11-25 kinaba: @macro times(n @value, e) { @value( 474c4facf0 2010-11-25 kinaba: if n == 1 then 474c4facf0 2010-11-25 kinaba: @macro(e) 474c4facf0 2010-11-25 kinaba: else 474c4facf0 2010-11-25 kinaba: @macro(e; times(n-1,e)) 474c4facf0 2010-11-25 kinaba: )}; 474c4facf0 2010-11-25 kinaba: times(7, print("Ichimen no Nanohana")); 474c4facf0 2010-11-25 kinaba: 474c4facf0 2010-11-25 kinaba: # Here, n is bound to the integer 7, not the AST of it. 474c4facf0 2010-11-25 kinaba: 474c4facf0 2010-11-25 kinaba: ######################################## 474c4facf0 2010-11-25 kinaba: print("----------"); 474c4facf0 2010-11-25 kinaba: 474c4facf0 2010-11-25 kinaba: # Explicit manipulation of AST. 474c4facf0 2010-11-25 kinaba: # Reverse the order of arguments of the function call expression 474c4facf0 2010-11-25 kinaba: @macro reverseArgs(e) {@value( 474c4facf0 2010-11-25 kinaba: def rev(xs, acc) { 474c4facf0 2010-11-25 kinaba: case xs when {car:x, cdr:xs}: rev(xs, {car:x, cdr:acc}) when {}: acc 474c4facf0 2010-11-25 kinaba: }; 474c4facf0 2010-11-25 kinaba: case @macro(e) 474c4facf0 2010-11-25 kinaba: when {is:"App", fun:f, args:as}: {is:"App", fun:f, args:rev(as,{})} 474c4facf0 2010-11-25 kinaba: when e : e 474c4facf0 2010-11-25 kinaba: )}; 474c4facf0 2010-11-25 kinaba: print( reverseArgs(1+2) ); # 2+1 == 3 474c4facf0 2010-11-25 kinaba: print( reverseArgs(1-2) ); # 2-1 == 1 474c4facf0 2010-11-25 kinaba: 474c4facf0 2010-11-25 kinaba: ######################################## 474c4facf0 2010-11-25 kinaba: print("----------"); 474c4facf0 2010-11-25 kinaba: 474c4facf0 2010-11-25 kinaba: # Both prints "original". Macro respects the neutral layer's "let y=" 474c4facf0 2010-11-25 kinaba: # and "fun(y)". It does not alter the inner scope y 474c4facf0 2010-11-25 kinaba: @macro test1(y) { fun(y){y}("original") }; 474c4facf0 2010-11-25 kinaba: @macro test2(y) { let y = "original" in y }; 474c4facf0 2010-11-25 kinaba: print( test1("replaced?") ); 474c4facf0 2010-11-25 kinaba: print( test2("replaced?") ); 474c4facf0 2010-11-25 kinaba: 474c4facf0 2010-11-25 kinaba: ######################################## 474c4facf0 2010-11-25 kinaba: print("----------"); 474c4facf0 2010-11-25 kinaba: 474c4facf0 2010-11-25 kinaba: # Macro expansion is done only at the first call. 474c4facf0 2010-11-25 kinaba: # So by using @macro parameter, it can remember the argument 474c4facf0 2010-11-25 kinaba: # of the first call. 474c4facf0 2010-11-25 kinaba: def remember1( x @macro, y ) { if x == y then "yes" else "no" }; 474c4facf0 2010-11-25 kinaba: print( remember1(1, 1) ); # yes 1 == 1 474c4facf0 2010-11-25 kinaba: print( remember1(2,1) ); # yes "1" == 1 474c4facf0 2010-11-25 kinaba: print( remember1(2,2) ); # no "1" != 2 474c4facf0 2010-11-25 kinaba: 474c4facf0 2010-11-25 kinaba: # exactly the same function, but called in different order 474c4facf0 2010-11-25 kinaba: def remember2( x @macro, y ) { if x == y then "yes" else "no" }; 474c4facf0 2010-11-25 kinaba: print( remember2(2, 2) ); # yes "2" == 2 474c4facf0 2010-11-25 kinaba: print( remember2(2, 1) ); # no "2" != 1 474c4facf0 2010-11-25 kinaba: print( remember2(1, 1) ); # no "2" != 1 474c4facf0 2010-11-25 kinaba: 474c4facf0 2010-11-25 kinaba: # Is this a good thing or a bad thing?? ba11f1d551 2010-11-23 kinaba: 474c4facf0 2010-11-25 kinaba: ######################################## 474c4facf0 2010-11-25 kinaba: print("----------"); ba11f1d551 2010-11-23 kinaba: 474c4facf0 2010-11-25 kinaba: # Trick to extract the AST of a function 474c4facf0 2010-11-25 kinaba: def foo(x) { x + x }; 474c4facf0 2010-11-25 kinaba: print( @macro(@value(foo)(arg1)) ); # prints AST for "arg1 + arg1" ba11f1d551 2010-11-23 kinaba: 474c4facf0 2010-11-25 kinaba: # If we wrote @macro(foo(arg1)), it is the AST of "foo(arg1)" 474c4facf0 2010-11-25 kinaba: # Here, by @value(foo) we obtain the "usual" behavior of foo, 474c4facf0 2010-11-25 kinaba: # not the macro-like bahavior to construct AST "foo(??)". 474c4facf0 2010-11-25 kinaba: # But still, by @macro( ... ) layer, the "usual" function is run in 474c4facf0 2010-11-25 kinaba: # macro mode.