gpt4 book ai didi

f# - 执行时会是尾调用吗?

转载 作者:行者123 更新时间:2023-12-01 13:59:52 24 4
gpt4 key购买 nike

一旦编译并运行,这会像尾调用一样吗?

let rec f accu = function
| [] -> accu
| h::t -> (h + accu) |> f <| t

也许有一种简单的方法可以测试我不知道的行为,但这可能是另一个问题。

最佳答案

我认为如果您不使用流水线运算符,这会更容易理解。实际上,这两个流水线运算符被定义为inline。 , 所以编译器会将代码简化为如下(而且我认为这个版本也更易读和更容易理解,所以我会这样写):

let rec f accu = function
| [] -> accu
| h::t -> f (h + accu) t

现在,您可以阅读 tail-call on Wikipedia 的定义,它说:

A tail call is a subroutine call that happens inside another procedure as its final action; it may produce a return value which is then immediately returned by the calling procedure.

所以是的,调用 f最后一行是尾调用。

如果你想分析原始表达式 (h + accu) |> f <| t (不知道流水线运算符是内联的),那么这实际上变成了 ((h + accu) |> f) <| t .这意味着表达式调用 <|带有两个参数的运算符并返回结果 - 所以调用 <|是尾调用。

<|运算符定义如下:

let (<|) f a = f a

现在,调用 f流水线运算符内部也是一个尾调用(对于其他流水线运算符也是如此)。

总而言之,如果编译器没有进行内联,您将有一个包含三个尾调用的序列(使用 .NET .tail 指令编译以确保 .NET 执行尾调用)。但是,由于编译器执行内联,它会看到您有一个递归尾调用( f 调用 f ),这可以更有效地编译成一个循环。 (但是跨多个函数或运算符的调用不能轻易使用循环。)

关于f# - 执行时会是尾调用吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16549827/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com