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キーワードが不要

変数キャプチャの指定もないですが、僅か数文字の違いであるので挙げませんでした。


スポンサード リンク

この記事のカテゴリ

  • ⇒ 久々にOvenを触ってみたくなった
  • ⇒ 久々にOvenを触ってみたくなった