Julia语言具有强大的元编程机制,本文用Julia实现《SICP》中文第二版中第 99 页中的实例:符号求导,体验一下Julia元编程。
运行结果如下:
julia> include("deriv.jl") # 加载代码
multiplicand (generic function with 1 method)
julia> deriv(:(x + 3), :x) # 求表达式 x + 3 关于 x 的导数
1
julia> deriv(:(x * y), :x) #对表达式 x * y进行求导
:y
julia> deriv(:((x * y) * (x + 3)), :x) #对表达式 (x * y) * (x + 3)进行求导
:(x * y + y * (x + 3))
代码如下(deriv.jl):
1 function deriv(expr, var) 2 if isa(expr, Number) 3 return 0 4 elseif isa(expr, Symbol) 5 if is_same_variable(expr, var) 6 return 1
7 else
8 return 0 9 end 10 elseif is_sum(expr) 11 make_sum(deriv(addend(expr), var), 12 deriv(augend(expr), var)) 13 elseif is_product(expr) 14 make_sum(make_product(multiplier(expr), 15 deriv(multiplicand(expr), var)), 16 make_product(deriv(multiplier(expr), var), 17 multiplicand(expr))) 18 else
19 println("unknown expression type -- DERIV", expr) 20 end 21 end 22
23
24 function is_variable(n) 25 return typeof(n) == Symbol 26 end 27
28 function is_same_variable(v1, v2) 29 return isa(v1, Symbol) && isa(v2, Symbol) && (v1 == v2) 30 end 31
32
33 # function make_sum(a1, a2)
34 # return Expr(:call, :+, a1, a2)
35 # end
36
37 # function make_product(m1, m2)
38 # return Expr(:call, :*, m1, m2)
39 # end
40
41 function make_sum(a1, a2) 42 if is_eq_number(a1, 0) 43 return a2 44 elseif is_eq_number(a2, 0) 45 return a1 46 elseif isa(a1, Number) && isa(a2, Number) 47 return a1 + a2 48 else
49 return Expr(:call, :+, a1, a2) 50 end 51 end 52
53 function make_product(m1, m2) 54 if is_eq_number(m1, 0) || is_eq_number(m2, 0) 55 return 0 56 elseif is_eq_number(m1, 1) 57 return m2 58 elseif is_eq_number(m2, 1) 59 return m1 60 elseif isa(m1, Number) && isa(m2, Number) 61 return m1 * m2 62 else
63 return Expr(:call, :*, m1, m2) 64 end 65 end 66
67 function is_eq_number(expr, num) 68 return isa(expr, Number) && (expr == num) 69 end 70
71 function is_sum(x) 72 return isa(x, Expr) && x.args[1] == :+
73 end 74
75 function addend(s) 76 return s.args[2] 77 end 78
79 function augend(s) 80 return s.args[3] 81 end 82
83 function is_product(x) 84 return isa(x, Expr) && x.args[1] == :*
85 end 86
87 function multiplier(p) 88 return p.args[2] 89 end 90
91 function multiplicand(p) 92 return p.args[3] 93 end