Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/xamarin/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
Recursion F#树构建函数导致Xamarin Studio中的堆栈溢出_Recursion_Xamarin_F#_Functional Programming_Stack Overflow - Fatal编程技术网

Recursion F#树构建函数导致Xamarin Studio中的堆栈溢出

Recursion F#树构建函数导致Xamarin Studio中的堆栈溢出,recursion,xamarin,f#,functional-programming,stack-overflow,Recursion,Xamarin,F#,Functional Programming,Stack Overflow,我试图在树状结构中建立一些规则,逻辑门,即and,not,or以及条件,例如属性x等于值y。我首先编写了最明显的递归函数,这很有效。然后,我尝试编写一个版本,以延续传递的方式从和中获取线索,不会导致堆栈溢出 它适用于小树(深度约为1000),但不幸的是,当使用大树时,当我使用Xamarin Studio在Mac上运行它时,它会导致堆栈溢出。有谁能告诉我,我是否误解了F#如何对待尾部递归代码,或者这段代码是否不是尾部递归代码 代码是尾部递归的,你说对了。但问题在于单核细胞增多症。看,Mono并不

我试图在树状结构中建立一些规则,逻辑门,即and,not,or以及条件,例如属性x等于值y。我首先编写了最明显的递归函数,这很有效。然后,我尝试编写一个版本,以延续传递的方式从和中获取线索,不会导致堆栈溢出

它适用于小树(深度约为1000),但不幸的是,当使用大树时,当我使用Xamarin Studio在Mac上运行它时,它会导致堆栈溢出。有谁能告诉我,我是否误解了F#如何对待尾部递归代码,或者这段代码是否不是尾部递归代码


代码是尾部递归的,你说对了。但问题在于单核细胞增多症。看,Mono并不像官方产品那样是.NET的高质量实现。特别是,它不进行尾部调用消除。一点也不

对于最简单(也是最普遍)的自递归,这并不重要,因为编译器会更早地捕获它。F#编译器足够聪明,可以发现函数正在调用自己,找出在什么条件下,并将其转换为整洁的
while
循环,这样编译后的代码就不会进行任何调用

但是,当尾部调用是作为参数传递的函数时,编译器不能这样做,因为实际调用的函数直到运行时才知道。事实上,即使两个函数的相互递归也不能可靠地转换为循环

可能的解决办法:

  • 切换到.NET核心
  • 不要使用递归延续,而是使用累加器(可能不可能)
  • 使用自递归并传递手动维护的连续堆栈
  • 如果所有其他操作都失败,请使用可变堆栈

  • 那太令人失望了。花了相当长的时间思考问题的关键是我的实现。找到了这个,它看起来和这个匹配,最后的评论让它看起来好像不会很快解决。Mono正在消失。切换到.NET内核。@FyodorSoikin我认为Xamarin的Mono不会很快消失。
    let FoldTree andF orF notF leafV t data = 
        let rec Loop t cont = 
            match t with
            | AndGate (left, right)->
                Loop left  (fun lacc ->  
                Loop right (fun racc -> 
                cont (andF lacc racc))) 
            | OrGate (left, right)->
                Loop left  (fun lacc ->  
                Loop right (fun racc -> 
                cont (orF lacc racc))) 
            | NotGate exp ->
                Loop exp (fun acc -> cont (notF acc))
            | EqualsExpression(property,value) -> cont (leafV (property,value))
        Loop t id
    
    let evaluateContinuationPassingStyle tree data = 
        FoldTree (&&) (||) (not) (fun (prop,value) -> data |> Map.find prop |> ((=) value)) tree data