Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
F# 尾部递归与布尔算子_F#_Tail Recursion - Fatal编程技术网

F# 尾部递归与布尔算子

F# 尾部递归与布尔算子,f#,tail-recursion,F#,Tail Recursion,我目前正在自学F#(通过try F#网站)。 我有以下(imho)尾部递归函数,用于一元谓词(int->bool)的存在量化 但是,第二个实现不是尾部递归的。问题是编译器是否会将其优化为尾部递归 更简单(好吧,这有点傻)的例子情况如何 let rec hasNoRoot f = if (f x = 0) then false else hasNoRoot (fun x -> f (x+1)) 对 let rec hasNoRoot f = (f 0 <> 0

我目前正在自学F#(通过try F#网站)。 我有以下(imho)尾部递归函数,用于一元谓词(int->bool)的存在量化

但是,第二个实现不是尾部递归的。问题是编译器是否会将其优化为尾部递归

更简单(好吧,这有点傻)的例子情况如何

let rec hasNoRoot f = 
    if (f x = 0) then false
    else hasNoRoot (fun x -> f (x+1))

let rec hasNoRoot f = (f 0 <> 0) && (hasNoRoot (fun x-> f(x+1)))
let rec hasNoRoot f=(f0)和&(hasNoRoot(funx->f(x+1)))
在第二个示例中,为了将函数(其实际描述)识别为尾部递归函数,编译器只需要“知道”为了计算一个连接,不一定要同时计算两个连接


感谢您的建议

我使用VS2012(F#3.0)编译了“exists”和“hasNoRoot”函数的第二个版本,并进行了优化,然后使用.NET Reflector检查了编译器生成的IL。编译器确实优化了“hasNoRoot”函数,但不幸的是,没有优化“exists”函数。不过,这似乎是一个合理的优化,因此可能会添加到下一版本的编译器中

对于子孙后代,以下是编译器生成的内容:

.method public static bool exists(int32 bound, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<int32, bool> predicate) cil managed
{
    .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = { new int32[int32(0x2)] { int32(0x1), int32(0x1) } }
    .maxstack 8
    L_0000: nop 
    L_0001: ldarg.0 
    L_0002: ldc.i4.1 
    L_0003: add 
    L_0004: ldc.i4.0 
    L_0005: ble.s L_001c
    L_0007: ldarg.1 
    L_0008: ldarg.0 
    L_0009: callvirt instance !1 [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<int32, bool>::Invoke(!0)
    L_000e: brfalse.s L_0012
    L_0010: ldc.i4.1 
    L_0011: ret 
    L_0012: ldarg.0 
    L_0013: ldc.i4.1 
    L_0014: sub 
    L_0015: ldarg.1 
    L_0016: starg.s predicate
    L_0018: starg.s bound
    L_001a: br.s L_0001
    L_001c: ldc.i4.0 
    L_001d: ret 
}
.method公共静态bool存在(int32绑定,类[FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2谓词)cil托管
{
.custom实例void[FSharp.Core]Microsoft.FSharp.Core.compileationArgumentCountsAttribute::.ctor(int32[])={new int32[int32(0x2)]{int32(0x1),int32(0x1)}
.maxstack 8
L_0000:没有
L_0001:ldarg.0
L_0002:ldc.i4.1
L_0003:添加
L_0004:ldc.i4.0
L_0005:ble.s L_001c
L_0007:ldarg.1
L_0008:ldarg.0
L_0009:callvirt实例!1[FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0)
L_000e:brfalse.s L_0012
L_0010:ldc.i4.1
L_0011:ret
L_0012:ldarg.0
L_0013:ldc.i4.1
L_0014:分接头
L_0015:ldarg.1
L_0016:标准谓词
L_0018:标准界
L_001a:br.s L_0001
L_001c:ldc.i4.0
L_001d:ret
}

我使用VS2012(F#3.0)编译了“exists”和“hasNoRoot”函数的第二个版本,并进行了优化,然后使用.NET Reflector检查了编译器生成的IL。编译器确实优化了“hasNoRoot”函数,但不幸的是,没有优化“exists”函数。不过,这似乎是一个合理的优化,因此可能会添加到下一版本的编译器中

对于子孙后代,以下是编译器生成的内容:

.method public static bool exists(int32 bound, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<int32, bool> predicate) cil managed
{
    .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = { new int32[int32(0x2)] { int32(0x1), int32(0x1) } }
    .maxstack 8
    L_0000: nop 
    L_0001: ldarg.0 
    L_0002: ldc.i4.1 
    L_0003: add 
    L_0004: ldc.i4.0 
    L_0005: ble.s L_001c
    L_0007: ldarg.1 
    L_0008: ldarg.0 
    L_0009: callvirt instance !1 [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<int32, bool>::Invoke(!0)
    L_000e: brfalse.s L_0012
    L_0010: ldc.i4.1 
    L_0011: ret 
    L_0012: ldarg.0 
    L_0013: ldc.i4.1 
    L_0014: sub 
    L_0015: ldarg.1 
    L_0016: starg.s predicate
    L_0018: starg.s bound
    L_001a: br.s L_0001
    L_001c: ldc.i4.0 
    L_001d: ret 
}
.method公共静态bool存在(int32绑定,类[FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2谓词)cil托管
{
.custom实例void[FSharp.Core]Microsoft.FSharp.Core.compileationArgumentCountsAttribute::.ctor(int32[])={new int32[int32(0x2)]{int32(0x1),int32(0x1)}
.maxstack 8
L_0000:没有
L_0001:ldarg.0
L_0002:ldc.i4.1
L_0003:添加
L_0004:ldc.i4.0
L_0005:ble.s L_001c
L_0007:ldarg.1
L_0008:ldarg.0
L_0009:callvirt实例!1[FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0)
L_000e:brfalse.s L_0012
L_0010:ldc.i4.1
L_0011:ret
L_0012:ldarg.0
L_0013:ldc.i4.1
L_0014:分接头
L_0015:ldarg.1
L_0016:标准谓词
L_0018:标准界
L_001a:br.s L_0001
L_001c:ldc.i4.0
L_001d:ret
}

可能重复的@Joce虽然这个问题与你的问题有一些相似之处,但它的不同足以证明它是公开的。可能重复的@Joce虽然这个问题与你的问题有一些相似之处,但它的不同足以证明它是公开的。
.method public static bool exists(int32 bound, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<int32, bool> predicate) cil managed
{
    .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = { new int32[int32(0x2)] { int32(0x1), int32(0x1) } }
    .maxstack 8
    L_0000: nop 
    L_0001: ldarg.0 
    L_0002: ldc.i4.1 
    L_0003: add 
    L_0004: ldc.i4.0 
    L_0005: ble.s L_001c
    L_0007: ldarg.1 
    L_0008: ldarg.0 
    L_0009: callvirt instance !1 [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<int32, bool>::Invoke(!0)
    L_000e: brfalse.s L_0012
    L_0010: ldc.i4.1 
    L_0011: ret 
    L_0012: ldarg.0 
    L_0013: ldc.i4.1 
    L_0014: sub 
    L_0015: ldarg.1 
    L_0016: starg.s predicate
    L_0018: starg.s bound
    L_001a: br.s L_0001
    L_001c: ldc.i4.0 
    L_001d: ret 
}