にほんごのれんしゅう

日本語として伝えるための訓練を兼ねたテクログ

boost::optionalを使ってみて 第2回

前回よりはだいぶまし

val hoge = Some(10).map{(x)=> x +1 };

これをC++に導入する

twitterでコメントいただいて,引数の型を明示的にspecifyするのは行けてない,とのことでした.折を見て修正しようと思います

boost::optionalを使ってみて 第2回

boost::optionalをやってみました.C++でOption型を実現する例のアレ.
OptionがNoneでなかったら,プロシージャを継続するというアレ.
C++でも専用の関数を利用すれば,ある程度フレキシブルに利用できることが確認できた.
つまり,scala入門時によく言われる,Option型でmapして,その中のプロシージャがモナドを部分的に満たすアレをC++で実装する.

scala> val hage = Some(10)
hage: Some[Int] = Some(10)

scala> val result = hage.map{ (x) =>
     |  println(x+1)
     | }
11
result: Option[Unit] = Some(())

使い方

  boost::optional<int> aaa = 10;
  auto result = KOKUU2::Match::eval(
                  aaa, //マップを開始したいoptional変数
                  [](int i){return i*i;}, //マップの中で処理する内容
                  new double); //戻り値として期待する型
  std::cout << "result:" << *result << std::endl;

虚空2の設計

  • Optionに関するmapに対応する処理をC++でも行い安くする.
  • 利用者側からはifを使わなくてもいいというメリットを与える.
  • 引数とするlambdaはモナド則をできるだけ満たすように書かなければいけなくなるので,コードが関数型っぽく矯正できる(if文で切った中に長いプロシージャを書かれて辟易したことがあった)   
#include<boost/optional.hpp>
namespace KOKUU2{
namespace Match{  
  template<class T, class lambda, class OUT>//lambdaをキャプチャして変数をbind
  boost::optional<OUT> eval(boost::optional<T> x, lambda functor, OUT* out){
    delete out;
    if(x){
      auto res = static_cast<OUT>(std::bind(functor, x.get())()); //bindで目標のプロシージャを作る
      return boost::optional<OUT>(res);
    };
    return boost::none;
  };
}}//endnamepace

今後の方針

  • 虚空0は関数型言語の基礎機能の補助ライブラリとする
  • 虚空1は算術ライブラリとする
  • 虚空2はScalaの機能をC++で用いるライブラリとする
  • 虚空3はScalaz,Haskell相当のライブラリとする
    こんな感じで開発していきます.