Recursion F#用实际值替换变量会导致无限循环(递归函数)
我最近从F#开始,实现了一个非常基本的递归函数,它代表了Eratosthenes筛。我提出了以下工作代码:Recursion F#用实际值替换变量会导致无限循环(递归函数),recursion,f#,infinite-loop,Recursion,F#,Infinite Loop,我最近从F#开始,实现了一个非常基本的递归函数,它代表了Eratosthenes筛。我提出了以下工作代码: static member internal SieveOfEratosthenesRecursive sequence accumulator = match sequence with | [] -> accumulator | head::tail -> let rest = tail |> List.filter(fun number -&
static member internal SieveOfEratosthenesRecursive sequence accumulator =
match sequence with
| [] -> accumulator
| head::tail -> let rest = tail |> List.filter(fun number -> number % head <> 0L)
let newAccumulator = head::accumulator
Prime.SieveOfEratosthenesRecursive rest newAccumulator
静态成员内部SieveFeratosines递归序列累加器=
匹配序列
|[]->累加器
|head::tail->let rest=tail |>List.filter(有趣的数字->数字%head 0L)
让newacculator=head::acculator
Prime.sieveoferatostenes递归剩余新累加器
这个函数并没有真正的内存效率,所以我试图消除变量“rest”和“newacculator”。我想出了以下代码
static member internal SieveOfEratosthenesRecursive sequence accumulator =
match sequence with
| [] -> accumulator
| head::tail -> tail |> List.filter(fun number -> number % head <> 0L)
|> Prime.SieveOfEratosthenesRecursive (head::accumulator)
静态成员内部SieveFeratosines递归序列累加器=
匹配序列
|[]->累加器
|head::tail->tail |>List.filter(有趣的数字->数字%head 0L)
|>Prime.sieveoferatostenesrecursive(头::累加器)
据我所知,我读过的教程Prime.sieveoferatosonesrecursive将被调用,过滤后的tail作为第一个参数,由head::acculator组成的列表作为第二个参数。然而,当我试图以较少的变量使用量运行代码时,程序会陷入无限循环。为什么会发生这种情况?我做错了什么
据我所知,我读过的教程Prime.siveoferatosNesRecursive将被调用,第一个参数是过滤后的tail
,第二个参数是由head::acculator
组成的列表
你把这个倒过来
在第一个版本中,您要传递rest
然后newacculator
;在第二个版本中,您实际上是在传递newacculator
然后rest
。也就是说,你已经转换了论点
Prime.sieveoferatosonesrecursive(head::accumulator)
是一个部分函数应用程序,其中应用(head::accumulator)
作为第一个参数(序列
)。此分部函数应用程序将生成一个一元函数(应为累加器
),您将(通过|>
)传递到该函数,在代码的第一个版本中称之为rest
改变<代码> sieEfErrastOth.Stutials//Cord>的参数顺序是最简单的解决方案,但我也会考虑如下类似的习惯用法:
static member internal SieveOfEratosthenesRecursive sequence accumulator =
match sequence with
| [] -> accumulator
| head::tail ->
tail
|> List.filter(fun number -> number % head <> 0L)
|> Prime.SieveOfEratosthenesRecursive <| (head::accumulator)
静态成员内部SieveFeratosines递归序列累加器=
匹配序列
|[]->累加器
|头:尾->
尾
|>列表.过滤器(乐趣编号->编号%head 0L)
|>Prime.sieveoferatostenes递归累加器
|头:尾->
尾
|>列表.过滤器(乐趣编号->编号%head 0L)
|>flipzip(头部:累加器)
||>Prime.sieveoferatos递归
FWIW,将
rest
和newacculator
作为命名变量删除,不会对内存使用产生丝毫影响。第二个函数中的最后一个调用相当于:
Prime.SieveOfEratosthenesRecursive newAccumulator rest
在这里,您可以切换两个参数的位置。由于newacculator
在每次递归调用后都会变大,因此您永远不会达到空列表的基本情况
经验法则是最后放置最常更改的参数:
let rec sieve acc xs =
match xs with
| [] -> acc
| x::xs' -> xs' |> List.filter (fun y -> y % x <> 0L)
|> sieve (x::acc)
使用pipe(
|>
)操作符只会使函数更具可读性,根本不会影响内存使用。你说得对。谢谢你指出这一点。管道参数将作为最后一个参数传入
let rec sieve acc xs =
match xs with
| [] -> acc
| x::xs' -> xs' |> List.filter (fun y -> y % x <> 0L)
|> sieve (x::acc)
let rec sieve acc = function
| [] -> acc
| x::xs' -> xs' |> List.filter (fun y -> y % x <> 0L)
|> sieve (x::acc)