要介绍的内容:
- 如何定义函数
- julia中的鸭子类型
- Mutating vs. non-mutating functions
- 广播
如何定义函数
Julia中有多种定义函数的方式。第一种定义函数的方法是使用function
和end
关键词
function sayhi(name)
println("Hi $name, it's great to see you!")
end
sayhi (generic function with 1 method)
function f(x)
x^2
end
f (generic function with 1 method)
我们可以使用如下方式调用这两个函数
sayhi("Lu")
Hi Lu, it’s great to see you!
f(42)
1764
或者,我们也可以只用一行就可以定义上面两个函数
sayhi2(name) = println("Hi $name, it's great to see you!")
sayhi2 (generic function with 1 method)
f2(x) = x^2
f2 (generic function with 1 method)
sayhi2("Ra")
Hi Ra, it’s great to see you!
f2(2)
4
julia也支持匿名函数,上面两个函数可以用匿名函数定义
sayhi3 = name -> println("Hi $name, it's great to see you!")
#3 (generic function with 1 method)
f3 = x -> x^2
#5 (generic function with 1 method)
sayhi3("Peng")
Hi Peng, it’s great to see you!
f3(42)
1764
Julia中的Duck-typing
任何合理的输入,带入Julia函数都可以运行。例如,sayhi
可以输入整数参数
sayhi(12345)
Hi 12345, it’s great to see you!
f
可以输入矩阵参数
A = rand(3, 3)
3×3 Array{Float64,2}:
0.696815 0.78963 0.0178001
0.0770015 0.0322625 0.664665
0.981264 0.130805 0.679957
f(A)
3×3 Array{Float64,2}:
0.56382 0.57803 0.549346
0.708352 0.148785 0.474758
1.36105 0.867998 0.566749
f
不能输入向量,因为向量v
的平方v^2
运算存在歧义。不像矩阵的平方定义明确。
f(rand(3))
MethodError: no method matching ^(::Array{Float64,1}, ::Int64)
Closest candidates are:
^(!Matched::Irrational{:ℯ}, ::Integer) at mathconstants.jl:91
^(!Matched::Irrational{:ℯ}, ::Number) at mathconstants.jl:91
^(!Matched::Missing, ::Integer) at missing.jl:155
…Stacktrace:
[1] macro expansion at ./none:0 [inlined]
[2] literal_pow at ./none:0 [inlined]
[3] f(::Array{Float64,1}) at ./In[5]:2
[4] top-level scope at In[19]:1
[5] include_string(::Function, ::Module, ::String, ::String) at ./loading.jl:1091
[6] execute_code(::String, ::String) at /home/lupeng/.julia/packages/IJulia/a1SNk/src/execute_request.jl:27
[7] execute_request(::ZMQ.Socket, ::IJulia.Msg) at /home/lupeng/.julia/packages/IJulia/a1SNk/src/execute_request.jl:86
[8] #invokelatest#1 at ./essentials.jl:710 [inlined]
[9] invokelatest at ./essentials.jl:709 [inlined]
[10] eventloop(::ZMQ.Socket) at /home/lupeng/.julia/packages/IJulia/a1SNk/src/eventloop.jl:8
[11] (::IJulia.var"#15#18")() at ./task.jl:356
Mutating vs. non-mutating functions
按照惯例,函数后面跟!
会改变方程内容,后面不带!
的方程不会改变方程内容。例如,我们看看sort
和sort!
的区别
v = [3, 5, 2]
3-element Array{Int64,1}:
3
5
2
sort(v)
v
3-element Array{Int64,1}:
3
5
2
sort(v)
语句返回把v
中元素排序好的数组,但是v
本身没有发生变化
当我们运行sort!(v)
时,数组v
中的元素也被排好序了
sort!(v)
3-element Array{Int64,1}:
2
3
5
v
3-element Array{Int64,1}:
2
3
5
广播
在任意一个函数名和它参数列表之间加一个.
,就在告诉那个函数广播输入对象的元素。
让我们看看f()
和f.()
的不同
A = [i + 3*j for j in 0:2, i in 1:3]
3×3 Array{Int64,2}:
1 2 3
4 5 6
7 8 9
f(A)
3×3 Array{Int64,2}:
30 36 42
66 81 96
102 126 150
跟之前我们看到的那样,对于矩阵A
,f(a) = A^2 = A * A
f.(A)
将返回一个每个元素都是矩阵A
对应位置元素平方的矩阵
B = f.(A)
3×3 Array{Int64,2}:
1 4 9
16 25 36
49 64 81
A[2, 2]
5
A[2, 2]^2
25
B[2, 2]
25
对于向量v
,虽然f(v)
不能运行,但是f.(v)
有意义
v = [1, 2, 3]
3-element Array{Int64,1}:
1
2
3
f.(v)
3-element Array{Int64,1}:
1
4
9