C ++ 11支持高阶列表功能


13

大多数函数式编程语言(如Common Lisp的,计划/球拍,Clojure中,Haskell中,斯卡拉,ocaml的,SML)支持列出了一些常见的高阶功能,如mapfiltertakeWhiledropWhilefoldlfoldr(见如Common Lisp的,计划/球拍, Clojure并排参考表HaskellScalaOCamlSML文档。)

C ++ 11是否在列表上具有等效的标准方法或函数?例如,考虑以下Haskell代码段:

let xs = [1, 2, 3, 4, 5]
let ys = map (\x -> x * x) xs

如何在现代标准C ++中表达第二个表达式?

std::list<int> xs = ... // Initialize the list in some way.
std::list<int> ys = ??? // How to translate the Haskell expression?

上面提到的其他高阶函数呢?
它们可以直接用C ++表示吗?


是的,但是它们比双向链表的特定实现更具通用性。就像Python在这方面的操作一样。我更喜欢将其绑定到特定的数据结构。曾经尝试Data.Sequence在Haskell的a上执行这些操作吗?比较难看。

“比较难看。”:与什么相比?
乔治

相较于上的相同操作[a]。您要么必须隐藏前奏功能,改编前奏,要么选择一个不那么直观的名称。

也许您是对的,但是这个问题的主题是如何在C ++中表达公共列表的高阶函数,而不是如何在Haskell中的Data.Sequence上实现类似的函数。
乔治

1
@delnan我认为Haskell的方法更为通用Functor,,FoldableTraversable以我能想到的抽象方式来实现。Data.Sequence是所有这些的实例,因此您可以这样做fmap (\x -> x * x) xsmapfmap专门为初学者。
亚历克2015年

Answers:


16

C ++拥有更多此类功能,请查看算法(或带有C ++ 11的附加功能)标头:

std::transform
std::for_each
std::remove_copy_if

它们可以轻松地与任何容器一起使用。

例如,您的代码可以这样表示(使用C ++ 11 lambdas以便于编码):

std::vector<int> x = {1, 2, 3, 4, 5};
std::vector<int> y;
std::transform(x.begin(), x.end(), std::back_inserter(y), [](int elem){ return elem * elem; });

不太直观,但是您可以轻松地将std::transform调用包装到函数中,该函数将返回新容器(带有move语义的更好的性能)。


谢谢。我想简化几天前编写的代码,这确实可以使它变得更短。只是一个小问题:为什么需要传递x.begin()和x.end()?仅传递向量x还不够吗?
乔治

std::transform需要两个迭代器,因此,您可以获取一个容器切片(请记住,您具有迭代器算法)。
m0nhawk 2012年

因此,您需要执行两项操作:进行切片和应用转换。
乔治

以前,您有两个迭代器,并将变换应用于它们之间的元素。迭代器在函数式编程中并不常见。
m0nhawk 2012年

2
我还没有遇到这样的库,在C ++中,基于迭代器的算法非常有用。您可以自己包装一个包装,std::transform例如:Y<U> map(T<U>, std::function<Y(U)>)
m0nhawk
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.