函数就是f(x,y,...),f(x,y,...)就是函数。学过高中数学的都知道。
函数的基本结构:
Julia里面的函数定义语法:
function f(x,y)
#逻辑运算部分
end
比如我们定义一个计算两数乘积的函数:
function multiplier1(x,y)
return x*y
end
我们看函数调用返回:
julia> multiplier1(3,7)
21
简化的函数定义:
multiplier2(x,y) = x*y
调用这个函数,看到返回和multiplier1一样。
julia> multiplier2(3,7)
21
函数的调用:
上面的函数multiplier1()和multiplier2(),我们已经给出直接使用f()的语法,历史上还有apply()函数调用其他函数,比如上面的multiplier1()的调用可以写成:
julia> apply(multiplier1,3,7)
但是到了Julia1.0版本后,已经取消了apply()这个函数。
函数的返回:
多数时候我们需要函数完成个运算后返回一个或者多个具体的值。
比如我们定义一个已知三角形两边和夹角求第三边的函数:
function thirdSide(x,y,c)
z = sqrt(x^2+y^2-2*x*y*cosd(c))
return z
end
我们拿勾股定理试一下:
julia> thirdSide(3,4,90)
5.0
心里装个正三角形:
julia> thirdSide(3,3,60)
3.0
匿名函数
顾名思义,就是不起名字的函数,例如:
x -> x^2 - 2x + 1
和
function (x)
x^2 - 2x + 1
end
是一样的,但是第一种写法没有函数名,所以调用起来有自己的语法。
我们使用map()函数演示一下匿名函数的调用方法:
julia> map( x -> x^2 - 2x + 1,[1,3,5,7,9])
5-element Array{Int64,1}:
0
4
16
36
64
上面这段可以看到函数的嵌套使用,编程中会经常遇到,例如:
map(round, [1.2,99.5,-10.135])
3-element Array{Float64,1}:
1.0
100.0
-10.0
多返回值函数:
定义:
function add1(a,b)
return a+1, b+1
end
调用:
julia> add1(5,6)
(6, 7)
函数返回值对变量的赋值:
julia> x, y = foo(7,9)
(8,10)
julia> x
8
julia> y
10
跨结构参数
先定义函数minmax(),输出小数在前大数在后:
minmax(x, y) = (y < x) ? (y, x) : (x, y)
再定义range(),输出大数减小数的差((min, max),作为一个Tuples的固定形式存在,是一个整体。):
range((min, max)) = max - min
跨函数体传递参数:
print(range(minmax(100, 2)))
98
很明显,与前面的map(),不同,这是另一种形式的函数嵌套使用。
变参函数
所谓变参,是指函数中参数的个数不定,在使用时根据实际情况变化,定义函数时,最后一个参数后紧跟省略号 ... 来定义变参函数:
julia> vf(a,b,c...) = (a,b,c)
bar (generic function with 1 method)
julia> vf(1,2)
(1, 2, ()))
julia> vf(1,2,3,4,5,6)
(1, 2, (3, 4, 5, 6))
julia> x = (3,4)
(3, 4)
julia> vf(1,2,x...)
(1, 2, (3, 4))
julia> x = (2,3,4)
(2, 3, 4)
julia> vf(1,x...)
(1, 2, (3, 4))
julia> x = [7,8,9]
3-element Array{Int64,1}:
7
8
9
julia> vf(1,x...)
(1, 7, (8, 9))
julia> vf(x...)
(7, 8, (9,))
原函数可以不是可变参数,一样可以对元组或者阵列引用,定义非可变函数ff():
julia> ff(a, b) = a + b
ff (generic function .with 1 method)
julia> x = (5,6)
(5, 6)
julia> ff(x...)
11
julia> x = [7,8]
2-element Array{Int64,1}:
7
8
julia> ff(x...)
15
如果带入参数个数有问题,函数调用会失败。
julia>x = [7,8,9]
7
8
9
julia> ff(x...)
ERROR: MethodError: no method matching ff(::Int64, ::Int64, ::Int64)
Closest candidates are:
ff(::Any, ::Any) at none:1
Stacktrace:
[1] top-level scope at none:0
x = 1
1
julia> ff(x...)
ERROR: MethodError: no method matching ff(::Int64)
Closest candidates are:
ff(::Any, ::Any) at none:1
Stacktrace:
[1] top-level scope at none:0
可选参数
函数入参中,个别参数为可选项,可以不传入,因为在函数定义时设定了默认值,比如我们定义函数oa():
function oa(x, y, z = 100)
return x+y+z
end
julia> oa(1,2)
103
julia> oa(1,2,3)
6
常见的日期函数Date(),就属于可选参数函数:
julia> using Dates
julia> Date(2000, 12, 12)
2000-12-12
julia> Date(2000, 12)
2000-12-01
julia> Date(2000)
2000-01-01
Do-Block语法
前面我们讲了map()函数的用法,当map()引用的函数为多行时,代码的可读性降低。Julia提供了do保留字,优化了代码风格,将遍历的入参提到和map()在同一行:
julia> map([-1,100,0,0.001,1234567890,-999999]) do x
if x < 0
return 0
elseif x == 0
return 1
else return x
end
end
6-element Array{Real,1}:
0
100.0
1
0.001
1.23456789e9
0
点语法在函数应用中的场景
科学严谨地描述是:给定函数f(x)应用于数组的每个元素A以产生新的数组f(A)。
说人话就是:一个函数f(x),一个数组A,要把数组A中每个数都代入f(x)计算,计算结果生成新的数组。
通常而又朴素的编程技巧告诉我们,我们需要实现得到数组A长度,并声明一个数组B和数组A等长,再建立一个循环体,把f(x)置于循环体内,依次代入数组A的每个数值,并把计算结果放入数组B。
本来简单的事情,用代码写起来竟然变得这么复杂。
好在Julia提供了点语法,没多就是英文半角的这个“.”。
下面以cosd()函数的使用举例:
julia> a = [0,60,90,120,180]
5-element Array{Int64,1}:
0
60
90
120
180
julia> cosd.(a)
5-element Array{Float64,1}:
1.0
0.5
0.0
-0.5
-1.0
再以梯形面积公式举例:
julia> a = [10,30,60]
3-element Array{Int64,1}:
10
30
60
julia> b = [20,50,100]
3-element Array{Int64,1}:
20
50
100
julia> h = [100,50,20]
3-element Array{Int64,1}:
100
50
20
julia> f(x,y,h) = (x + y) * h /2
f (generic function with 2 methods)
julia> f.(a,b,h)
3-element Array{Float64,1}:
1500.0
2000.0
1600.0
我们再看一下函数嵌套使用中,“@.”的语法,以sin()和asin为例:
julia> y = [0.0,30.0,60.0,90.0,120.0,150.0,180.0]
7-element Array{Float64,1}:
0.0
30.0
60.0
90.0
120.0
150.0
180.0
julia> x = similar(y) # pre-allocate output array
7-element Array{Float64,1}:
1.0609978956e-313
1.9097962122e-313
2.33419537056e-313
2.970794108e-313
3.18299368704e-313
3.60739284563e-313
2.1219957915e-314
julia> @.x = asind(sind(y))
7-element Array{Float64,1}:
0.0
30.000000000000004
59.99999999999999
90.0
59.99999999999999
30.000000000000004
0.0
上面的x = similar(y),是为了开辟一个新数组接收下面的函数输出。
网友评论