Functional programming 除“以外的所有尾部递归函数;rev";需要遍历列表两次吗?

Functional programming 除“以外的所有尾部递归函数;rev";需要遍历列表两次吗?,functional-programming,Functional Programming,根据我收集的信息,在实现尾部递归调用时,存储在acc(accumulator)变量中的结果列表元素实际上会向后显示,因此一般趋势似乎是在从当前函数返回之前将其向后反转 这意味着,如果我没有弄错的话,函数式编程语言中的所有高阶函数(除了rev)调用都会有系统开销,至少它们的命令式调用是如此 我是不是遗漏了什么?这不是很糟糕吗?这只是意味着尾部调用递归并不是函数式编程优化的全部。首先,列表本身就是隐藏的链表,在所有语言中,链表上的算法都有点低效。因此,函数式语言通常提供更接近命令式数组的结构,以满足

根据我收集的信息,在实现尾部递归调用时,存储在
acc
(accumulator)变量中的结果列表元素实际上会向后显示,因此一般趋势似乎是在从当前函数返回之前将其向后反转

这意味着,如果我没有弄错的话,函数式编程语言中的所有高阶函数(除了
rev
)调用都会有系统开销,至少它们的命令式调用是如此


我是不是遗漏了什么?这不是很糟糕吗?

这只是意味着尾部调用递归并不是函数式编程优化的全部。首先,列表本身就是隐藏的链表,在所有语言中,链表上的算法都有点低效。因此,函数式语言通常提供更接近命令式数组的结构,以满足程序员需要高效处理大型线性集合的情况。此外,除了在介绍性练习中,通过显式递归逐个元素建立列表的场景相对较少。相反,像
map
filter
这样的高阶函数更常用于生产代码中。对于编译器或标准库编写者来说,如何实现这些功能成为一个问题

我曾经非常好奇,以至于我在SML/NJ的标准库中找到了SML/NJ如何实现
map
。我希望看到它以您描述的方式通过使用
rev
的尾部调用递归实现。相反,他们这样做:

fun map f = let
      fun m [] = []
    | m [a] = [f a]
    | m [a, b] = [f a, f b]
    | m [a, b, c] = [f a, f b, f c]
    | m (a :: b :: c :: d :: r) = f a :: f b :: f c :: f d :: m r
      in
    m
      end
一个非尾部调用递归版本,将天真递归方法中隐含的函数调用开销减少了4倍。他们可能考虑过使用尾部调用递归方法的想法,但后来拒绝了,因为他们不希望两次传递的性能受到影响


最后一句话,除了C语言之外的每种语言都有一些特性,从效率的角度来看,这些特性让人不禁要问:“这真的很糟糕吗?”。Python——每个对象都有一个给出其类型和大小的头——这不是很糟糕吗?语言需要权衡。总的来说,函数式语言是以牺牲执行时间为代价来优化开发人员时间的语言。现代计算机的速度快得令人眼花缭乱——为什么不利用这种速度来实现一些语言,让您能够在更高的抽象级别上更简洁地编写代码呢?对于核心的数值分析可能不是最好的权衡,但对于许多问题领域来说,这是一个好主意

这只是意味着尾部调用递归不是函数式编程中的全部优化。首先,列表本身就是隐藏的链表,在所有语言中,链表上的算法都有点低效。因此,函数式语言通常提供更接近命令式数组的结构,以满足程序员需要高效处理大型线性集合的情况。此外,除了在介绍性练习中,通过显式递归逐个元素建立列表的场景相对较少。相反,像
map
filter
这样的高阶函数更常用于生产代码中。对于编译器或标准库编写者来说,如何实现这些功能成为一个问题

我曾经非常好奇,以至于我在SML/NJ的标准库中找到了SML/NJ如何实现
map
。我希望看到它以您描述的方式通过使用
rev
的尾部调用递归实现。相反,他们这样做:

fun map f = let
      fun m [] = []
    | m [a] = [f a]
    | m [a, b] = [f a, f b]
    | m [a, b, c] = [f a, f b, f c]
    | m (a :: b :: c :: d :: r) = f a :: f b :: f c :: f d :: m r
      in
    m
      end
一个非尾部调用递归版本,将天真递归方法中隐含的函数调用开销减少了4倍。他们可能考虑过使用尾部调用递归方法的想法,但后来拒绝了,因为他们不希望两次传递的性能受到影响


最后一句话,除了C语言之外的每种语言都有一些特性,从效率的角度来看,这些特性让人不禁要问:“这真的很糟糕吗?”。Python——每个对象都有一个给出其类型和大小的头——这不是很糟糕吗?语言需要权衡。总的来说,函数式语言是以牺牲执行时间为代价来优化开发人员时间的语言。现代计算机的速度快得令人眼花缭乱——为什么不利用这种速度来实现一些语言,让您能够在更高的抽象级别上更简洁地编写代码呢?对于核心的数值分析可能不是最好的权衡,但对于许多问题领域来说,这是一个好主意

这只是意味着尾部调用递归不是函数式编程中的全部优化。首先,列表本身就是隐藏的链表,在所有语言中,链表上的算法都有点低效。因此,函数式语言通常提供更接近命令式数组的结构,以满足程序员需要高效处理大型线性集合的情况。此外,除了在介绍性练习中,通过显式递归逐个元素建立列表的场景相对较少。相反,像
map
filter
这样的高阶函数更常用于生产代码中。对于编译器或标准库编写者来说,如何实现这些功能成为一个问题

我曾经非常好奇,以至于我在SML/NJ的标准库中找到了SML/NJ如何实现
map
。我希望看到它以您描述的方式通过使用
rev
的尾部调用递归实现。相反,他们这样做:

fun map f = let
      fun m [] = []
    | m [a] = [f a]
    | m [a, b] = [f a, f b]
    | m [a, b, c] = [f a, f b, f c]
    | m (a :: b :: c :: d :: r) = f a :: f b :: f c :: f d :: m r
      in
    m
      end
一种非尾部调用递归版本,它将函数-c减少了4倍