[misc] Functional C++ Programming
Functional C++ Programming
Introduction
模板真是个强大的东西,能够在编译期完成很多计算,这里整了一套list编程,有点像Racket和Ocaml里面的stylish
List
这个并不难实现,我们可以通过简单的折叠表达式来实现
template <int... Values>
struct IntegerList {};
List Append
采用immutable的方式,我们可以通过递归的方式来实现append
template <typename IntegerList1, typename IntegerList2>
struct ConcatLists;
template <int... Values1, int... Values2>
struct ConcatLists<IntegerList<Values1...>, IntegerList<Values2...>> {
using type = IntegerList<Values1..., Values2...>;
};
List Length
这个很好实现,这个其实和函数式编程差不多
首先我们去定义一个base case,当只有一个元素或者没有一个元素的时候,我们返回0和1,剩下只需要通过递归就可以完美实现了
template <int Head, int... Tail>
constexpr auto length(IntegerList<Head, Tail...>) {
return 1 + length(IntegerList<Tail...>{});
}
template <int Head>
constexpr auto length(IntegerList<Head>) {
return 1;
}
constexpr auto length(IntegerList<>) {
return 0;
}
List Filter
这里我们map,filter,fold一般是需要一个lambda来进行实现,我感觉其实C++里如果后续可能的话,应该对容器在智能指针条件下进行一些拓展支持,像Rust一样可以在runtime进行链式调用,现在stl function里的东西更像是C那一套而不是真正的OOP
这个的实现其实要注意一点,msys在新版本如果是空的内容,就不用用template <>了,直接不用template就可以了,否则会报错
template <int Head, int... Tail, typename Predicate>
constexpr auto filter(IntegerList<Head, Tail...>, Predicate pred) {
if constexpr (pred(Head)) {
return typename ConcatLists<IntegerList<Head>, decltype(filter(IntegerList<Tail...>{}, pred))>::type{};
} else {
return filter(IntegerList<Tail...>{}, pred);
}
}
// 基本情况:当整数列表为空时停止递归
template <typename Predicate>
constexpr auto filter(IntegerList<>, Predicate pred) {
return IntegerList<>{};
}
List Fold
template <int... Values, typename Func>
constexpr auto fold(IntegerList<Values...>, Func func) {
return (func(Values), ...);
}
List Map
为了避免命名冲突,我用了filter_map当作名称,但是实际上这不是option,所以不应该叫filter_map,应该叫map
template <int... Values, typename Func>
constexpr auto filter_map(IntegerList<Values...>, Func func) {
return IntegerList<func(Values)...>{};
}
List Reverse
很简单,和concat反着来就好了
template <typename CurrentList>
constexpr auto reverse(CurrentList currentList) {
return currentList;
}
template <int Head, int... Tail>
constexpr auto reverse(IntegerList<Head, Tail...>) {
return typename ConcatLists<decltype(reverse(IntegerList<Tail...>{})), IntegerList<Head>>::type{};
}
sum up
归根结底其实并不难,我们首先定义规则,然后拆包就好了。关键是这套规则还不太熟悉,希望赶紧熟悉一下
天才选手zerol的主页:https://zerol.me/
|
WeepingDemon的个人主页:https://weepingdemon.gitee.io/blog/