Julia 中的递归函数
Recursive function in Julia
Julia 有没有办法顺利定义递归函数?
function f(x_0, y_0)
x_1 = g1(x_0,y_0)
y_1 = g2(x_0,y_0)
x_2 = g1(x_1,y_1)
y_2 = g2(x_1,y_1)
x_3 = g1(x_2,y_2)
y_3 = g2(x_2,y_2)
x_4 = g1(x_3,y_3)
y_4 = g2(x_3,y_3)
return x_2,y_2
end
特别是,我希望能够调用函数并提供指定递归循环的参数。像这样:
f(x_0, y_0, circle = 2)
>> x_2, y_2
f(x_0, y_0, circle = 3)
>> x_3, y_3
如果你定义
function apply_n(f, x_0, cycle_len)
for _ in 1:cycle_len
x_0 = f(x_0)
end
return x0
end
并调用 apply_n((x,y)->(g1(x,y),g2(x,y)), (x_0,y_0), 3)
它会起作用。
IterTools.jl 提供了一个 iterate
方法可以做到这一点。
help?> iterated
…
iterated(f, x)
Iterate over successive applications of f, as in x, f(x), f(f(x)), f(f(f(x))), ...
…
julia> x_0, y_0 = 5, 10;
g1 = +;
g2 = -;
julia> using IterTools: iterated, nth
julia> nth(iterated(((x, y),) -> (g1(x, y), g2(x, y)), (x_0, y_0)), 3)
(10, 20)
正如文档所说,结果是(迭代器)(x, f(x), f(f(x)), …)
,这意味着问题中的 (x_2, y_2)
将是 f(f(x))
,这是第三个元素 - 这就是为什么上面对 nth
的调用将 3
作为第二个参数传递。
此方法的一个优点是它 returns 一个迭代器,您可以像对待任何其他迭代器一样对待它。因此,如果您想要该过程所有前 5 个阶段的结果:
julia> using Base.Iterators: take
julia> take(iterated(((x, y),) -> (g1(x, y), g2(x, y)), (x_0, y_0)), 5) |> collect
10-element Vector{Tuple{Int64, Int64}}:
(5, 10)
(15, -5)
(10, 20)
(30, -10)
(20, 40)
或者只希望递归在条件为真时继续:
julia> using Iterators: takewhile
julia> takewhile(((x, y),) -> x + y < 50,
iterated(((x, y),) -> (g1(x, y), g2(x, y)), (x_0, y_0))) |> collect
4-element Vector{Tuple{Int64, Int64}}:
(5, 10)
(15, -5)
(10, 20)
(30, -10)
Julia 有没有办法顺利定义递归函数?
function f(x_0, y_0)
x_1 = g1(x_0,y_0)
y_1 = g2(x_0,y_0)
x_2 = g1(x_1,y_1)
y_2 = g2(x_1,y_1)
x_3 = g1(x_2,y_2)
y_3 = g2(x_2,y_2)
x_4 = g1(x_3,y_3)
y_4 = g2(x_3,y_3)
return x_2,y_2
end
特别是,我希望能够调用函数并提供指定递归循环的参数。像这样:
f(x_0, y_0, circle = 2)
>> x_2, y_2
f(x_0, y_0, circle = 3)
>> x_3, y_3
如果你定义
function apply_n(f, x_0, cycle_len)
for _ in 1:cycle_len
x_0 = f(x_0)
end
return x0
end
并调用 apply_n((x,y)->(g1(x,y),g2(x,y)), (x_0,y_0), 3)
它会起作用。
IterTools.jl 提供了一个 iterate
方法可以做到这一点。
help?> iterated
…
iterated(f, x)
Iterate over successive applications of f, as in x, f(x), f(f(x)), f(f(f(x))), ...
…
julia> x_0, y_0 = 5, 10;
g1 = +;
g2 = -;
julia> using IterTools: iterated, nth
julia> nth(iterated(((x, y),) -> (g1(x, y), g2(x, y)), (x_0, y_0)), 3)
(10, 20)
正如文档所说,结果是(迭代器)(x, f(x), f(f(x)), …)
,这意味着问题中的 (x_2, y_2)
将是 f(f(x))
,这是第三个元素 - 这就是为什么上面对 nth
的调用将 3
作为第二个参数传递。
此方法的一个优点是它 returns 一个迭代器,您可以像对待任何其他迭代器一样对待它。因此,如果您想要该过程所有前 5 个阶段的结果:
julia> using Base.Iterators: take
julia> take(iterated(((x, y),) -> (g1(x, y), g2(x, y)), (x_0, y_0)), 5) |> collect
10-element Vector{Tuple{Int64, Int64}}:
(5, 10)
(15, -5)
(10, 20)
(30, -10)
(20, 40)
或者只希望递归在条件为真时继续:
julia> using Iterators: takewhile
julia> takewhile(((x, y),) -> x + y < 50,
iterated(((x, y),) -> (g1(x, y), g2(x, y)), (x_0, y_0))) |> collect
4-element Vector{Tuple{Int64, Int64}}:
(5, 10)
(15, -5)
(10, 20)
(30, -10)