function mygcd(m, n)
  local r
  while n  0
    r = m % n 
    m, n = n, r 
  end
    return m 
end
mygcd (generic function with 1 method)
mygcd(210, 24)
6

\[ u_n = u_{n-1} - \frac{f(u_{n-1})}{f'(u_{n-1})} = u_{n-1} - \frac{u_{n-1}^2 - x}{2 u_{n-1}} = \frac12 \left( u_{n-1} + \frac{x}{u_{n-1}} \right) \]

while true
  expr1
  expr2
  ...
  cond && break
end

其中的cond 为退出循环条件,break表示的是退出一重循环。

function mysqrt(x, eps=1E-6)
    u = 1.0
    u1 = 0.0
    while abs(u - u1) >= eps
        u1 = u
        u = 0.5 * (u + x / u)
    end
    return u
end
mysqrt(2)
1.414213562373095
eps = 0.0001
x = 1.0
y = x;
xk = x;
sgn = 1;
k = 1;
while true
    global k, sgn, xk, y, eps
    k += 1
    sgn *= -1
    xk *= x
    item = xk / k
    y += sgn * item
    item < eps && break
end
println("eps = ", eps, " log(1+", x, ") = ", y,
    " Iterations: ", k)
eps = 0.0001 log(1+1.0) = 0.6931971730609582 Iterations: 10001

自定义函数

function funcname(x, y, z)
    ...
end
f(x) = x^2 +3*x +1
f (generic function with 1 method)
f(1)
f(2)
11

返回值,若需要返回多个值,就使用return res1,res2的格式实现

function summ(x)
    xm = sum(x) / length(x)
    xs = sum(x .^ 2) / length(x)
    return xm, xs
end
res1, res2 = summ([1, 2, 3, 4, 5])
println(res1,"\n",res2)
3.0
11.0

一维数组

v1 = [2, 3, 5, 7, 11, 13, 17]
7-element Vector{Int64}:
  2
  3
  5
  7
 11
 13
 17
v2 = [1.5, 3, 4, 9.12]
4-element Vector{Float64}:
 1.5
 3.0
 4.0
 9.12
v3 = ["苹果", "桔子", "香蕉"]
3-element Vector{String}:
 "苹果"
 "桔子"
 "香蕉"
vf = [1.2, 2.5, 3.6]; vf
3-element Vector{Float64}:
 1.2
 2.5
 3.6
x1 = [1,2,3]
x2 = x1
x2[2] = 100
@show x1;
x1 = [1, 100, 3]
x1 == x2
true
x1  x2
true

参数传递模式

Julia的参数传递是“共享传递”(pass by sharing), 这样可以省去复制的开销。 如果参数是标量的数值、字符串、元组(tuple)这样的非可变类型, 参数原来的值不会被修改; 如果参数是数组这样的可变(mutable)数据类型, 则函数内修改了这些参数保存的值,传入的参数也会被修改。

function f(n)
    println("Inside f() before changing, n = ",n)
    n = -1
    println("Inside f() after changing, n = ", n)
  return
end
function test()
    n = 1
    f(n)
    println("Out of f() n = ",n)
end
test()
Inside f() before changing, n = 1
Inside f() after changing, n = -1
Out of f() n = 1
function double!(x)
    for i in eachindex(x)
        x[i] *= 2
    end
end
xx = [1, 2, 3]
double!(xx)
@show xx;
xx = [2, 4, 6]

其中的循环方式是通过eachindex(x)来实现。同时我们可以使用广播的方式来实现xx .*=2

println(xx)
xx .*=2
[1, 2, 3]
3-element Vector{Int64}:
 2
 4
 6

在Julia中,若函数会修改自变量的值,将函数名后面添加一个叹号!,上述的函数中,double!()改变了数组自变量元素的值,若直接对自变量赋值,相当于在函数中重新绑定x。不会对输入的原始数组造成影响。如:

function double_wrong(x)
    x = 2 .* x
    return x
end
xx = [1, 2, 3]
double_wrong(xx)
@show xx;
xx = [1, 2, 3]

可变参数

function f_vara1(x, args...)
    println("x=", x)
    println("其它参数:", args)
end
f_vara1(11, 1, 2, 3)
x=11
其它参数:
(1, 2, 3)

有时需要传递给一个多自变量函数的实参保存在了一个变量中

max(1, 3, 1, 4)
4

递归调用

闭包

可以在函数内定义内嵌函数并以此内嵌函数为函数返回值, 称这样的内嵌函数为闭包(closure)。 闭包的好处是可以保存定义时的局部变量作为一部分, 产生“有状态的函数”, 类似于面向对象语言中的方法, 而Julia并不支持传统的面向对象语言中那样的类。

function counter_old()
    n = 0
    n = n+1
    return n
end
println(counter_old(), ", ", counter_old())
1, 1
function make_counter()
    n = 0
    function counter()
        n += 1
        return n
    end
end
my_counter = make_counter()
typeof(my_counter)
println(my_counter(), ", ", my_counter())
1, 2

函数式编程

在R中的函数编程,通过map函数来实现对多个重复操作的一次调用,同样在Julia中也有类似的功能实现

map(f, x)将函数f作用到容器x的每个元素上, 有时可以用f.(x)代替, 但有些情况下不能使用广播(加点语法)。

map(x -> x^2 + 1, [1,2,3])
3-element Vector{Int64}:
  2
  5
 10

在调用map()函数时, 如果对每个元素执行的操作需要用多行代码完成, 用无名函数就不太方便。 例如,对数组的每个元素, 负数映射到0, 大于100的数映射到100, 其它数值不变,用有名函数可以写成:

function fwins(x)
    if x < 0
        y = 0
    elseif x > 100
        y = 100
    else
        y = x
    end
    return y
end
fwins.([-1, 0, 80, 120]) |> show
[0, 0, 80, 100]
map((x,y) -> 2*x + y, [1, 2, 3], [10, 20, 30]) |> show
[12, 24, 36]
v1 = [2, 3, 5, 7, 11, 13, 17]
P = [5, 1, 3, 4, 2, 6, 7]
@show w1 = v1[P];

使用show或者@show宏的主要区别是否有对变量原名称进行显示