久々にOvenを触ってみたくなった
カテゴリ: C#, C++. タグ: Boost.Format, Boost.Range, C++11, Enumerable.Range, Enumerable.Select, Enumerable.SelectMany, irange, LINQ, PStade.Oven, Range-based for, std::make_pair, System.Tuple, Tuple.Create.
コメントなし
P-Stade.Ovenを引っ張り出してコードを書いていました。単純に直積を行う例です。g++ 4.6.1, Boost 1.47, P-Stade リビジョン2579(これ書いていた時点での最新)を使っています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | #define BOOST_RESULT_OF_USE_DECLTYPE #include <iostream> #include <string> #include <utility> // pair #include <boost/format.hpp> #include <boost/range/irange.hpp> #include <pstade/oven/concatenated.hpp> #include <pstade/oven/transformed.hpp> #include <pstade/oven/regular.hpp> // transformedにラムダ式を渡すにはregularで包まないといけない #define transformed_r(...) transformed(regular(__VA_ARGS__)) int main() { using namespace pstade::oven; using boost::irange; auto r = irange(1, 4) | transformed_r([](int x) { return irange(1, 4) | transformed_r([=](int y) {return std::make_pair(x, y);}); }) | concatenated | transformed_r([](std::pair<int, int> x) { return boost::format("(%1%, %2%)") % x.first % x.second; }); for (auto const& t : r) { std::cout << t << std::endl; } } |
P-Stade.OvenやBoost.Range Adaptorとラムダ式を組み合わせるときは|と{}の縦が揃うように書くのが最近の好みです。まだ一般的なスタイルもない世界だと思い、好きにやっています。
こういう出力になります。
(1, 1) (1, 2) (1, 3) (2, 1) (2, 2) (2, 3) (3, 1) (3, 2) (3, 3)
C#に直訳するとこんな感じです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | using System; using System.Collections.Generic; using System.Linq; class Program { static void Main() { var e = Enumerable.Range(1, 3) .Select(x => Enumerable.Range(1, 3) .Select(y => Tuple.Create(x, y))) .SelectMany(t => t) .Select(t => string.Format("({0}, {1})", t.Item1, t.Item2)); foreach (var t in e) { Console.WriteLine(t); } } } |
irangeは[left, right)ですが、Enumerable.Rangeは[left, right]であることに注意してください。
実際には、少なくとも1つ目のSelectとその次のSelectManyはまとめられます。
1 2 3 4 | var e = Enumerable.Range(1, 3) .SelectMany(x => Enumerable.Range(1, 3) .Select(y => Tuple.Create(x, y))) .Select(t => string.Format("({0}, {1})", t.Item1, t.Item2)); |
C++と比べてC#のラムダ式はすっきりかけていいですね、どっちのコードもやっていることは同じなのですが。
- 引数の型を明示する必要がない
- returnキーワードが不要
変数キャプチャの指定もないですが、僅か数文字の違いであるので挙げませんでした。
スポンサード リンク |