为什么 C++20 范围不只提供管道语法?
Why do C++20 ranges not provide only pipe syntax?
我知道这个问题听起来很奇怪,所以这里有一些上下文。
最近我很失望地得知 C++20 范围内的 map reduce 并不像人们预期的那样工作,即
const double val = data | transform(...) | accumulate (...);
不行,你必须这样写不自然:
const double val = accumulate(data | transform(...));
可以找到详细信息here and ,但归结为 accumulate 不能消除 2 个不同用例之间的歧义。
所以这让我想到:
如果 C++20 要求您必须使用管道来使用范围,也就是您可以不写
vector<int> v;
sort(v);
但是你必须写
vector<int> v
v|sort();
这会解决歧义问题吗?
如果是的话,虽然对于使用 std::sort
和其他 STL 算法的人来说不自然,但我想知道在较长的 运行 中,这是否是一个更好的设计选择。
注意:
如果这个问题太模糊,请随意投票关闭,但我觉得这是一个合理的设计问题,可以以相对公正的方式回答,特别是如果我对问题的理解是错误的。
would that would solve problem of ambiguity?
是的。
如果只有一种写作方式,那么这种方式一定是唯一可能的解释。如果算法 "call" 只能是对算法的部分调用,该算法必须通过左侧范围的 |
操作完成,那么您甚至永远不会有这样的问题算法调用是部分或全部。只是总是片面的。
在这个意义上没有歧义。
但是如果你走那条路,你最终会得到这样的结果:
auto sum = accumulate("hello"s);
实际上并没有对该字符串中的 char
求和,实际上是占位符,它正在等待一个范围以初始值 "hello"s
.
累加
您需要区分范围算法和范围适配器。算法是对一系列值执行通用操作的函数。适配器是创建范围视图的函数,这些视图修改范围的表示。适配器由 |
运算符链接;算法只是常规函数。
有时候,同一个概念上的东西可以有算法和适配器形式。 transform
作为算法和适配器存在。前者将转换存储到输出范围中;后者创建输入的视图范围,根据请求延迟计算转换。
这些是针对不同需求和用途的不同任务。
此外,请注意 C++20 中没有 sort
适配器 。排序适配器必须创建一个视图范围,以某种方式混合源范围中的元素。它必须为新的值序列分配存储空间(即使它只是对值进行 iterators/pointers/indices 排序)。而且排序必须在构建时完成,所以不会发生惰性操作。
这也是为什么 accumulate
不能那样工作的原因。不是"ambiguity"的问题;这是操作的基本性质的问题。累加从一个范围计算一个值;它不会根据现有范围计算新范围。那是算法的工作,而不是适配器。
有些任务在算法形式上很有用。一些任务在适配器形式中很有用(你发现很少有 zip
-like 算法)。有些任务对两者都有用。但是因为这是两个用于不同目的的独立概念,所以它们有不同的调用方式。
我知道这个问题听起来很奇怪,所以这里有一些上下文。
最近我很失望地得知 C++20 范围内的 map reduce 并不像人们预期的那样工作,即
const double val = data | transform(...) | accumulate (...);
不行,你必须这样写不自然:
const double val = accumulate(data | transform(...));
可以找到详细信息here and
所以这让我想到:
如果 C++20 要求您必须使用管道来使用范围,也就是您可以不写
vector<int> v;
sort(v);
但是你必须写
vector<int> v
v|sort();
这会解决歧义问题吗?
如果是的话,虽然对于使用 std::sort
和其他 STL 算法的人来说不自然,但我想知道在较长的 运行 中,这是否是一个更好的设计选择。
注意: 如果这个问题太模糊,请随意投票关闭,但我觉得这是一个合理的设计问题,可以以相对公正的方式回答,特别是如果我对问题的理解是错误的。
would that would solve problem of ambiguity?
是的。
如果只有一种写作方式,那么这种方式一定是唯一可能的解释。如果算法 "call" 只能是对算法的部分调用,该算法必须通过左侧范围的 |
操作完成,那么您甚至永远不会有这样的问题算法调用是部分或全部。只是总是片面的。
在这个意义上没有歧义。
但是如果你走那条路,你最终会得到这样的结果:
auto sum = accumulate("hello"s);
实际上并没有对该字符串中的 char
求和,实际上是占位符,它正在等待一个范围以初始值 "hello"s
.
您需要区分范围算法和范围适配器。算法是对一系列值执行通用操作的函数。适配器是创建范围视图的函数,这些视图修改范围的表示。适配器由 |
运算符链接;算法只是常规函数。
有时候,同一个概念上的东西可以有算法和适配器形式。 transform
作为算法和适配器存在。前者将转换存储到输出范围中;后者创建输入的视图范围,根据请求延迟计算转换。
这些是针对不同需求和用途的不同任务。
此外,请注意 C++20 中没有 sort
适配器 。排序适配器必须创建一个视图范围,以某种方式混合源范围中的元素。它必须为新的值序列分配存储空间(即使它只是对值进行 iterators/pointers/indices 排序)。而且排序必须在构建时完成,所以不会发生惰性操作。
这也是为什么 accumulate
不能那样工作的原因。不是"ambiguity"的问题;这是操作的基本性质的问题。累加从一个范围计算一个值;它不会根据现有范围计算新范围。那是算法的工作,而不是适配器。
有些任务在算法形式上很有用。一些任务在适配器形式中很有用(你发现很少有 zip
-like 算法)。有些任务对两者都有用。但是因为这是两个用于不同目的的独立概念,所以它们有不同的调用方式。