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,我有以下代码: let rec combinations acc listC = match listC with | [] -> acc | h::t -> let next = [h]::List.map (fun t -> h::t) acc @ acc combinations next t 它看起来是尾部递归的,但我不断地得到堆栈溢出。关于如何让它工作,有

我有以下代码:

    let rec combinations acc listC = 
        match listC with
        | [] -> acc 
        | h::t ->
            let next = [h]::List.map (fun t ->  h::t) acc @ acc
            combinations next t 

它看起来是尾部递归的,但我不断地得到堆栈溢出。关于如何让它工作,有什么想法吗?

组合是尾部递归的。您的问题在于
@
操作员。附加一个列表将迭代整个列表,因此当您的
acc
变大时,您将得到一个so

您可以看到,
@
运算符不是尾部递归的。非优化版本如下所示:
let rec(@)xy=match x with[]->y |(h::t)->h::(t@y)

要解决此问题,有两种选择:

  • 如果您不关心顺序,可以编写一个尾部递归方法来预先处理结果,如下所示:

    让rec在lst1和lst2之前=
    将lst1与
    |[]->lst2
    |head::tail->prepend tail(head::lst2)

  • 如果您关心顺序,您可以编写一个方法,首先反转列表,然后将其前置。当然,这样做的缺点是需要两倍的内存,因为您正在分配一个额外的列表来保存原始列表的反转版本。您可以重用前面的函数编写如下内容:

    let prepend2 lst1 lst2=
    前置(前置lst1[])lst2


  • 组合是尾部递归的。您的问题在于
    @
    操作员。附加一个列表将迭代整个列表,因此当您的
    acc
    变大时,您将得到一个so

    您可以看到,
    @
    运算符不是尾部递归的。非优化版本如下所示:
    let rec(@)xy=match x with[]->y |(h::t)->h::(t@y)

    要解决此问题,有两种选择:

  • 如果您不关心顺序,可以编写一个尾部递归方法来预先处理结果,如下所示:

    让rec在lst1和lst2之前=
    将lst1与
    |[]->lst2
    |head::tail->prepend tail(head::lst2)

  • 如果您关心顺序,您可以编写一个方法,首先反转列表,然后将其前置。当然,这样做的缺点是需要两倍的内存,因为您正在分配一个额外的列表来保存原始列表的反转版本。您可以重用前面的函数编写如下内容:

    let prepend2 lst1 lst2=
    前置(前置lst1[])lst2


  • 你在哪里得到堆栈溢出?单声道您启用了TCO?您可以显示从该代码生成的IL吗?这应该是尾部递归的-很可能您没有启用TCO,或者问题出在其他地方-顺便问一下:您开始的列表有多大?也许你应该考虑切换到SEQSI在两个地方使用它,一个是用ExelDeDNA作为一个.xLL,另一个是WebSaple(Debug)中的服务器端函数,你会在哪里得到堆栈溢出?单声道您启用了TCO?您可以显示从该代码生成的IL吗?这应该是尾部递归的-很可能您没有启用TCO,或者问题出在其他地方-顺便问一下:您开始的列表有多大?也许你应该考虑切换到SEQSI在两个地方使用它,一个是AxelDNA的.xLL,另一个是WebSaple(调试)中的服务器端函数,这是有意义的。有趣的是,我会测试一下。谢谢你的帮助谢谢,这很有道理。很有趣,我来测试一下。谢谢你的帮助
    > prepend [1;2;3;4] [5;6;7;8];; 
    val it : int list = [4; 3; 2; 1; 5; 6; 7; 8]
    
    > prepend2 [1;2;3;4] [5;6;7;8];; 
    val it : int list = [1; 2; 3; 4; 5; 6; 7; 8]