需要帮助了解延续功能
Need assistance understanding continuation function
这是一个说明CPS和尾递归的教学示例:
fun sum [] k = k 0
| sum (x::xs) k = sum xs (fn y=>k(x+y));
我无法理解匿名函数 fn y=>k(x+y)
如何正确地汇总输入列表的元素。
据我了解,匿名函数意味着一个带有一个参数 y 的新函数,其中函数体调用带有参数 y+x
的原始函数 k
。
如果我调用 sum [1,2,3,4,5] (fn x=>x);
,我得到 15。如果我有 sum [1,2,3,4,5] (fn x=>3x);
,答案是 45。因此,sum
函数的用户必须首先了解确切的细节sum
因为只有适当版本的 k
才会产生给定列表的总和。以这种方式让用户提供功能的实际目的是什么?
如果我是 sum
函数的编写者,我无法控制用户为 k
传递的内容。换句话说,我什至如何指定函数将做什么?
The user of the sum function hence would have to first understand the exact gory details of sum
as only an appropriate version of k
will produce the sum of the given list.
没有。一如既往,阅读文档就足够了,无需查看实现细节。您的 k
是 给定的 列表的确切总和 - 这才是最重要的。您应该将 k
理解为 output parameter (though without mutation); it is basically a callback
If I am the writer of the sum function, I cannot control what the user will pass in for k
. In other words, how do I even specify what the function would do precisely?
你不需要关心用户传递了什么。您只需记录该函数的作用:它使用提供的 xs
列表的总和调用提供的 k
。 return 的值并不重要。
What is the real-world purpose of having a user supplied function in such a manner?
如果走极端,您不需要 return continuation-passing style 中的任何值 - 您只需将其传递给回调即可。这使得调用堆栈变得多余。从另一个角度来看,每个函数确实以尾调用结束,可以优化掉而不是 returning.
I have problems understanding how [...] would sum up the elements of the input list correctly.
尝试手动评估您的函数:
sum [1,2,3] id
sum [2,3] (fn y1=>id(1+y1))
sum [3] (fn y2=>(fn y1=>id(1+y1))(2+y2))
sum [] (fn y3=>(fn y2=>(fn y1=>id(1+y1))(2+y2))(3+y3))
(fn y3=>(fn y2=>(fn y1=>id(1+y1))(2+y2))(3+y3)) 0
(fn y2=>(fn y1=>id(1+y1))(2+y2))(3+0)
(fn y2=>(fn y1=>id(1+y1))(2+y2)) 3
(fn y1=>id(1+y1))(2+3)
(fn y1=>id(1+y1)) 5
id(1+5)
id(6)
6
因此,正如您所见,此函数在堆内存中构建了一系列最终相互调用的匿名函数。一个普通的递归函数会使用 stack space 作为等价物。
The user of the sum function hence would have to first understand the exact gory details of sum as only an appropriate version of k will produce the sum of the given list. What is the real-world purpose of having a user supplied function in such a manner?
正如 Bergi 所写,用户不需要了解 sum 函数的工作原理,只需要了解它以延续作为参数并在其基本情况下对其进行解析即可。正如 Bergi 还写道,它不必在其基本情况下评估 k。此函数的替代方法是:
fun sum [] k = k
| sum (x::xs) k = sum xs (fn y=>k(x+y));
此处的一个应用程序以及导出带有回调作为参数和 return 值的 sum 函数的理由是,您可以通过这种方式将函数延迟链接在一起。例如,使用上述函数,您可以对列表的列表求和;
fun sumMany [] k = k
| sumMany (xs::xss) k = sumMany xss (sum xs k)
你可能会这样评价它
val result = sumMany [[1,2,3],[4,5,6],[7,8,9]] (fn x=>x) 0
这是一个说明CPS和尾递归的教学示例:
fun sum [] k = k 0
| sum (x::xs) k = sum xs (fn y=>k(x+y));
我无法理解匿名函数 fn y=>k(x+y)
如何正确地汇总输入列表的元素。
据我了解,匿名函数意味着一个带有一个参数 y 的新函数,其中函数体调用带有参数 y+x
的原始函数 k
。
如果我调用 sum [1,2,3,4,5] (fn x=>x);
,我得到 15。如果我有 sum [1,2,3,4,5] (fn x=>3x);
,答案是 45。因此,sum
函数的用户必须首先了解确切的细节sum
因为只有适当版本的 k
才会产生给定列表的总和。以这种方式让用户提供功能的实际目的是什么?
如果我是 sum
函数的编写者,我无法控制用户为 k
传递的内容。换句话说,我什至如何指定函数将做什么?
The user of the sum function hence would have to first understand the exact gory details of
sum
as only an appropriate version ofk
will produce the sum of the given list.
没有。一如既往,阅读文档就足够了,无需查看实现细节。您的 k
是 给定的 列表的确切总和 - 这才是最重要的。您应该将 k
理解为 output parameter (though without mutation); it is basically a callback
If I am the writer of the sum function, I cannot control what the user will pass in for
k
. In other words, how do I even specify what the function would do precisely?
你不需要关心用户传递了什么。您只需记录该函数的作用:它使用提供的 xs
列表的总和调用提供的 k
。 return 的值并不重要。
What is the real-world purpose of having a user supplied function in such a manner?
如果走极端,您不需要 return continuation-passing style 中的任何值 - 您只需将其传递给回调即可。这使得调用堆栈变得多余。从另一个角度来看,每个函数确实以尾调用结束,可以优化掉而不是 returning.
I have problems understanding how [...] would sum up the elements of the input list correctly.
尝试手动评估您的函数:
sum [1,2,3] id
sum [2,3] (fn y1=>id(1+y1))
sum [3] (fn y2=>(fn y1=>id(1+y1))(2+y2))
sum [] (fn y3=>(fn y2=>(fn y1=>id(1+y1))(2+y2))(3+y3))
(fn y3=>(fn y2=>(fn y1=>id(1+y1))(2+y2))(3+y3)) 0
(fn y2=>(fn y1=>id(1+y1))(2+y2))(3+0)
(fn y2=>(fn y1=>id(1+y1))(2+y2)) 3
(fn y1=>id(1+y1))(2+3)
(fn y1=>id(1+y1)) 5
id(1+5)
id(6)
6
因此,正如您所见,此函数在堆内存中构建了一系列最终相互调用的匿名函数。一个普通的递归函数会使用 stack space 作为等价物。
The user of the sum function hence would have to first understand the exact gory details of sum as only an appropriate version of k will produce the sum of the given list. What is the real-world purpose of having a user supplied function in such a manner?
正如 Bergi 所写,用户不需要了解 sum 函数的工作原理,只需要了解它以延续作为参数并在其基本情况下对其进行解析即可。正如 Bergi 还写道,它不必在其基本情况下评估 k。此函数的替代方法是:
fun sum [] k = k
| sum (x::xs) k = sum xs (fn y=>k(x+y));
此处的一个应用程序以及导出带有回调作为参数和 return 值的 sum 函数的理由是,您可以通过这种方式将函数延迟链接在一起。例如,使用上述函数,您可以对列表的列表求和;
fun sumMany [] k = k
| sumMany (xs::xss) k = sumMany xss (sum xs k)
你可能会这样评价它
val result = sumMany [[1,2,3],[4,5,6],[7,8,9]] (fn x=>x) 0