再帰ラムダ

某所で挙がっていたことが気になった.ので,適当にググって発見したhttp://pc.2ch.net/tech/kako/996/996131288.htmlの169に書いてあったことを,おおよそそのまんまC++とBLLの形に翻訳してみた結果(と普通の再帰での書き方)が以下.

#include <iostream>
#include <boost/function.hpp>
#include <boost/lambda/lambda.hpp>
#include <boost/lambda/bind.hpp>
#include <boost/lambda/if.hpp>

template<class F>
struct fixer;

template<class F>
fixer<F> fix(F f)
{
  return fixer<F>(f);
}

template<class F>
struct fixer
{
  fixer(F f)
    : f_(f)
  { }

  template<class T>
  T operator()(T n)
  {
    return f_(fix(f_), n);
  }

  F f_;
};

int main()
{
  using namespace std;
  using namespace boost;
  using namespace boost::lambda;

  // 上の記事に従うと以下
  function<int (function<int (int)>, int)> f
    = ret<int>(if_then_else_return(_2 == 1, cref(1), bind(_1, _2 - 1) * _2));
  cout << fix(f)(1) << '\n';
  cout << fix(f)(2) << '\n';
  cout << fix(f)(3) << '\n';
  cout << fix(f)(4) << '\n';
  cout << fix(f)(5) << '\n';
  cout << fix(f)(6) << '\n';


  // 普通の再帰で書くと以下
  function<int (int)> g;
  g = ret<int>(if_then_else_return(_1 == 1, cref(1), bind(var(g), _1 - 1) * _1));
  cout << g(1) << '\n';
  cout << g(2) << '\n';
  cout << g(3) << '\n';
  cout << g(4) << '\n';
  cout << g(5) << '\n';
  cout << g(6) << '\n';
}

うむ.要するに黙っておとなしく関数にしときなさいってことですな.頑張れば汎用かつ分かりやすいものが作れるような気もするけど,そんなの考えてる/作ってるヒマがにゃい・・・.