値を返すブロック

半分以上ギャグです。

# 値を返すブロック

ある値が生成後変化しないなら、`const`にしたいのが人の性です。
リテラル値を即代入できる場合や、単純な計算、関数呼び出しの場合はこれはすぐさまできて、

```cpp
constexpr std::int32_t answer = 42;
constexpr double pi = boost::math::constants::pi<double>();
constexpr double one_div_pi = 1.0 / pi;
```

となります。
しかし、現実は常にこのような単純な場合だけではなく、値が条件によって変化する場合があるでしょう。同じようにしたくても、C++の`if`文は値を返さないので以下のようには書けません。

```cpp
const double factor = if (ptr) {*ptr} else {1.0}; // 無理
```

とはいえ、単なる条件分岐なら三項演算子が使えて、

```cpp
const double factor = ptr ? *ptr : 1.0;
```

とできます。

三項演算子に関しては慣れていないと読みにくいとの意見もありますが、個人的には状況次第で`const`になっていないよりは三項演算子の方がマシだと考えています。と言うか三項演算子にはC++11で`constexpr`関数を書いていたら嫌でも慣れるのでコンパイル時計算をしましょう。

さて、ではもう少し面倒な場合はどうでしょう。例えば`{0, 3, 6, 9, 12, ..., 300}`のような値で配列を初期化したいとします。

例えばこれは不可能なコードです。

```cpp
const std::vector<std::uint32_t> nums = {0, 3, 6, 9, /* ... 頑張る ... */, 300};
```

マクロに手を染めることによって`/* ... 頑張る ... */`を生成することが可能でしょうが、マクロに頼りたくはありません。`csv`を`#include`するのは忘れてください。

やはり初期化時に直接作るのが一番です。となると、自分で`iterator`を作成する……のは面倒なのでBoost.Iteratorを使うと、以下のように書けます。

```cpp
const auto f = [](std::uint32_t i){return i*3;};
const std::vector<std::uint32_t> nums(
    boost::make_transform_iterator(
        boost::make_counting_iterator<std::uint32_t>(0), f),
    boost::make_transform_iterator(
        boost::make_counting_iterator<std::uint32_t>(101), f)
    );
```

※ 上で`f`としているラムダを個々の`make_transform_iterator`で直接作るとコンパイルに失敗します。おそらく一つ目のラムダと二つ目のラムダが別の型として生成されてしまい、二つのイテレータが別の型になるので`vector`のコンストラクタにマッチしなくなることが原因でしょう。

これは目的に沿ったコードですが、長くそして奇妙です。いやここまでの文脈を共有している皆さんにとっては特に奇妙ではないでしょうが、突然これが出て来ると多くのプログラマは一瞬面食らうでしょう。面食らわれました。

生成するだけなら、標準ライブラリだけを使って以下のようにしてできます。

```cpp
std::vector<std::uint32_t> nums(101);
std::iota(std::begin(nums), std::end(nums), 0u);
std::transform(std::begin(nums), std::end(nums), std::begin(nums),
               [](const std::uint32_t v) -> std::uint32_t {return v * 3;});
```

しかし今回は`const`にしたいのでした。上のコードは書き換えるのが前提なので`const`にはできません。
例えば上のようにして作ったものをそのまま、

```cpp
const auto nums = {
    std::vector<std::uint32_t> nums_(101);
    std::iota(std::begin(nums_), std::end(nums_), 0u);
    std::transform(std::begin(nums_), std::end(nums_), std::begin(nums_),
                   [](const std::uint32_t v) -> std::uint32_t {return v * 3;});
    nums_
}; // 無理
```

のように代入してしまえれば、どんなに楽なことでしょう。ブロックが値を返せたらいいのですが！

と言うわけで値を返せるブロックをご紹介します。ブロックの前に`[]`を、最後に`()`をつけてください。それだけでブロックが値を返せるようになります。

```cpp
const auto nums = []{
    std::vector<std::uint32_t> nums_(101);
    std::iota(std::begin(nums_), std::end(nums_), 0u);
    std::transform(std::begin(nums_), std::end(nums_), std::begin(nums_),
                   [](const std::uint32_t v) -> std::uint32_t {return v * 3;});
    return nums_;
}();
```

これで、`transform_iterator`や他のfancy iteratorを駆使しても作るのが難しい値でも、素直に`for`ループやなんやかんやでゴリっと作成したものを返すだけで`const`な値として初期化できます。

よかったですね。

### 補遺

これが問題のコードですが、

```cpp
const auto nums = []{
    // なんか色々
    return nums_;
}();
```

これはラムダ関数をその場で構築して即呼び出したものです。ラムダ抽象構文`[](){}`のうち、引数や属性、戻り値型を全て省略するなら、そもそもパラメータリスト`()`を省略できます。`[]{/*色々*/ return nums_;}`の部分までがそれです。
今回は関数オブジェクトが欲しいのではなく、その戻り値が欲しいわけなので、作って即呼び出しています。呼び出すとき、そもそもパラメータリストを省略しているので渡す引数はなく、最後にある呼び出しの`()`は空です。
キャプチャもしないので`[]`も空で構いません。外にある変数を使うためにはキャプチャしなければならないのですが、最初の`[]`に色々入ってしまってラムダ感丸出しになるので上の例では避けました。

自然な発想の流れとしては、

1. 関数の戻り値ならそのまま代入できるのに……
2. でもこの場で使うだけの関数をわざわざ定義するのも面倒だ
3. そういえばこの場で即関数オブジェクトを作れる機能があるぞ？

と言う流れになります。

ちなみにRustならブロックは値を返すしそれ以前に一度`mut`で束縛したものに書き込んだ後immutableでシャドーイングしつつ再束縛できます。ほかの部分で`boost::variant`と`boost::optional`を使いまくってそれをラップして`expected`を自作し、リソース管理は全て`unique/shared_ptr`を使うようにして、SFINAEと`static_assert`でコンセプトのような何かをゴリゴリ頑張っていることを考えると、何でRustで書かなかったの？　みたいな感じですね！　それでは皆さんよいRustライフを！