map/fold运算符(在c++中)

map/fold operators (in c++)

本文关键字:c++ fold 运算符 map      更新时间:2023-10-16

我正在编写一个库,它可以对范围进行映射/折叠操作。我需要和操作员一起做这些。我对功能编程不是很熟悉,我暂时选择了*作为map,||作为fold。因此,在区间8 < x < 9:中找到cos(x)的最大值(蛮力算法)

double maximum = ro::range(8, 9, 0.01) * std::cos  || std::max;

在上述内容中,ro::range可以替换为任何STL容器。

如果地图/折叠操作符有任何约定,我不想与众不同。我的问题是:有数学符号吗?或者有任何语言使用运算符来表示映射/折叠吗?

**编辑**

对于那些提问的人,下面是RO目前可以做什么的小演示。scc是一个可以评估C++片段的小实用程序。

// Can print ranges, container, tuples, etc directly (vint is vector<int>) :
scc 'vint V{1,2,3};  V'
{1,2,3}
// Classic pipe. Alogorithms are from std::
scc 'vint{3,1,2,3} | sort | unique | reverse'
{3, 2, 1}
// Assign 42 to [2..5)
scc 'vint V=range(0,9);   range(V/2, V/5) = 42;  V'
{0, 1, 42, 42, 42, 5, 6, 7, 8, 9}

// concatenate vector of strings ('add' is shotcut for std::plus<T>()):
scc 'vstr V{"aaa", "bb", "cccc"};  V || add'
aaabbcccc
// Total length of strings in vector of strings
scc 'vstr V{"aaa", "bb", "cccc"};  V * size ||  (_1+_2)'
9
// Assign to c-string, then append `"XYZ"` and then remove `"bc"` substring :
scc 'char s[99];  range(s) = "abc";  (range(s) << "XYZ") - "bc"'
aXYZ

// Remove non alpha-num characters and convert to upper case
scc '(range("abc-123, xyz/") | isalnum) * toupper'
ABC123XYZ

// Hide phone number:
scc "str S="John Q Public  (650)1234567";  S|isdigit='X';  S"
John Q Public  (XXX)XXXXXXX

这实际上更像是一个注释,而不是一个真实的答案,但它太长了,无法放入注释中。

至少如果我对这个术语的记忆正确的话,map本质上是std::transform,fold是std::accumulate。假设这是正确的,我认为尝试自己写最多也是不明智的。

如果你想使用映射/折叠样式的语义,你可以这样做:

std::transform(std::begin(sto), std::end(sto), ::cos);
double maximum = *std::max_element(std::begin(sto), std::end(sto));

虽然std::accumulate更像是一个通用折叠,但std::max_element基本上是一个fold(..., max);。如果您喜欢单个操作,可以执行以下操作:

double maximum = *(std::max_element(std::begin(sto), std::end(sto),
[](double a, double b) { return cos(a) < cos(b); });

为此,我敦促你们重新考虑超载运营商。我上面给出的任何一个例子对任何一个合理的C++程序员来说都应该是清楚的。你所举的例子对大多数人来说是完全不透明的。

在更普遍的层面上,我敦促操作员在超载时格外小心。运算符重载在正确使用时非常好——能够为任意精度整数、矩阵、复数等重载运算符,使使用这些类型的代码比没有重载运算符的代码更可读、更容易理解。

不幸的是,当你以意想不到的方式使用运算符时,恰恰相反——这些用法肯定是非常意想不到的——事实上,完全属于"非常令人惊讶"的范围。如果这些运算符在特定领域得到了很好的理解,但与C++中的其他用途相反,可能会有问题(但至少有一点理由)。然而,在这种情况下,你似乎在发明一种"无中生有"的符号——我不知道有人使用任何运算符C++支持重载来表示折叠或映射(也没有任何视觉上相似或类似的东西)。简而言之,以这种方式使用重载是一个糟糕且不合理的想法。

在我所知道的语言中,没有标准的折叠方法。Scala使用运算符/::以及方法名称,Lisp有reduce,Haskell有foldl

另一方面,在我所知道的所有语言中,map更常见,简称为map

下面是fold在准人类可读中缀C++语法中的实现。请注意,该代码不是很健壮,只是用来证明这一点。它支持更常见的3参数fold运算符(范围、二进制运算和中性元素)。

这很容易成为虐待(你刚才说了"强奸"吗?)超载操作员的最有趣的方式,也是用900磅重的炮弹射中自己脚的最佳方式之一。

enum { fold } fold_t;
template <typename Op>
struct fold_intermediate_1
{
Op op;
fold_intermediate_1 (Op op) : op(op) {}
};
template <typename Cont, typename Op, bool>
struct fold_intermediate_2
{
const Cont& cont;
Op op;
fold_intermediate_2 (const Cont& cont, Op op) : cont(cont), op(op) {}
};
template <typename Op>
fold_intermediate_1<Op> operator/(fold_t, Op op)
{
return fold_intermediate_1<Op>(op);
}
template <typename Cont, typename Op>
fold_intermediate_2<Cont, Op, true> operator<(const Cont& cont, fold_intermediate_1<Op> f)
{
return fold_intermediate_2<Cont, Op, true>(cont, f.op);
}
template <typename Cont, typename Op, typename Init>
Init operator< (fold_intermediate_2<Cont, Op, true> f, Init init)
{
return foldl_func(f.op, init, std::begin(f.cont), std::end(f.cont));
}
template <typename Cont, typename Op>
fold_intermediate_2<Cont, Op, false> operator>(const Cont& cont, fold_intermediate_1<Op> f)
{
return fold_intermediate_2<Cont, Op, false>(cont, f.op);
}
template <typename Cont, typename Op, typename Init>
Init operator> (fold_intermediate_2<Cont, Op, false> f, Init init)
{
return foldr_func(f.op, init, std::begin(f.cont), std::end(f.cont));
}

CCD_ 20和CCD_。

这样使用:

foo myfunc(foo, foo);
container<foo> cont;
foo zero, acc;
acc = cont >fold/myfunc> zero; // right fold
acc = cont <fold/myfunc< zero; // left fold 

fold这个词在这里被用作穷人的一种新保留词。可以定义这种语法的几种变体,包括

<<fold/myfunc<< >>fold/myfunc>>
<foldl/myfunc> <foldr/myfunc>
|fold<myfunc| |fold>myfunc|

内部运算符的优先级必须与外部运算符的优先级相同或更高。这是C++语法的局限性。

对于map,只需要一个中间体,语法可以是例如

mapped = cont |map| myfunc;

实现它是一个简单的练习。

哦,请不要在生产中使用这种语法,除非你非常清楚自己在做什么,甚至可能知道;)