🐥

C++でmap, filterを使うために方言に馴染もう

2021/02/14に公開

C++20からついにmap, filterが導入されます。
https://en.cppreference.com/w/cpp/ranges

for (int i : ints | std::views::filter(even) | std::views::transform(square)) {
    std::cout << i << ' ';
}

しかし、C++は昔にmapという用語を辞書型に割り振ってしまったために命名がいびつになってしまっているように感じます。
ここではC++の方言をまとめて利用の抵抗感を低減することを目標として記事を書きました。

概要

一般については私の感覚なので個人差があります。

一般 C++ 備考
map transform
flat_map / flatten join
filter_map transform_maybe HaskellはmapMaybe
slide(2) adjacent
fold accumulate foldに名前変更される予定
range iota

filterとC++11時点で対応していたと思われるものはcopy_ifですが引き継がれなかったので気にしなくても良いです。

map

C++ではmapの代わりにtransformという用語を割り当てています。
ただ、私の経験上transformを使っている人をほとんど見たことがありません。
C++11からstd::transformというアルゴリズムが提供されています。

mapを使わないということがプログラミングにおいてあり得ないので命名が悪いと言わざるを得ません。
しかし、今更はるか昔の命名の悪さに文句を言っても始まらないのでC++はmapの代わりにtransformという方言を使うということを広く認識してもらうことが大事なのかなと思っています。

slide

tupleを返すかiterableな物を返すかで名前がまた違う言語もある。好きな方で受け取れる言語もある。
C++はtupleとiterableは受け取り方を明示する必要のある言語なのでtuple版はslide_as_tupleになるかもしれない。

adjacentはslide(2)のtuple版

言語 関数名
Python pairwise
Kotlin windowed, zipWithNext
Scala sliding
D slide
Haskell divvy
Clojure partition
Rust std::slice::Windows

fold / reduce

C++17でreduceが追加され、C++23にてaccumulateがfoldに改名されるとC++にはfoldとreduceの両方が存在することになります。
reduceはfoldの並列実行版として区別すれば良さそうです。

関数名 言語
fold Rust, Haskell
reduce Kotlin, Python, Java, Swift
初期値の有無で使い分け Scala

range

iotaも方言がきつくて使われていない関数の1つ。
C++ではrangeの代わりにiotaを使います。

言語 関数名
Python range
Java range
多数の言語 a..b

参考

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p2214r0.html

Discussion