preprocess-time lambda expression

69
λ expression for PP を作ってみました digitalghost http://d.hatena.ne.jp/DigitalGhost/ http://twitter.com/DecimalBloat

Upload: digitalghost

Post on 27-May-2015

927 views

Category:

Technology


0 download

TRANSCRIPT

Page 1: Preprocess-time Lambda Expression

λ expression for PPを作ってみました

digitalghosthttp://d.hatena.ne.jp/DigitalGhost/

http://twitter.com/DecimalBloat

Page 2: Preprocess-time Lambda Expression

自己紹介

●きりんさんがすきです。

でもC++のほうがもーっとすきです。

●プリプロセッサで遊んでます

●実は仕事でC++を使ったことは一度もない

●他の方の発表見てから資料作成余裕でした

Page 3: Preprocess-time Lambda Expression

今日の話

1.前提2.この発表に説得力を付ける努力

1.どーきらしきもの2.簡単な例

3.使い方1.基本2.構文糖

4.実用例1.BOOST_PP_REPEATで

5.その他の話1.ChaosPreprocessor2.中途半端に形式的な文法3.今回のブツ4.ありがとう

Page 4: Preprocess-time Lambda Expression

前提

Page 5: Preprocess-time Lambda Expression

前提

●ラムダ式をなんとなく知っている

Page 6: Preprocess-time Lambda Expression

前提

●ラムダ式をなんとなく知っている

●Boost.Preprocessorのお世話になったことが

ある

Page 7: Preprocess-time Lambda Expression

前提

●ラムダ式をなんとなく知っている

●Boost.Preprocessorのお世話になったことが

ある

●BOOST_PP_ADD相当の機能が作れる

(もちろんプリプロセッサで)

Page 8: Preprocess-time Lambda Expression

この発表に説得力を

付ける努力

Page 9: Preprocess-time Lambda Expression

どーきらしきもの

●こんなことありませんか?

Page 10: Preprocess-time Lambda Expression

どーきらしきもの

●こんなことありませんか?

●BOOST_PP_REPEATを使うときステップごとの展

開用マクロをいちいち定義するのめんどくさい

Page 11: Preprocess-time Lambda Expression

どーきらしきもの

●こんなことありませんか?

●BOOST_PP_REPEATを使うときステップごとの展

開用マクロをいちいち定義するのめんどくさい

●引数がtupleのとき全要素にアクセスするためマクロ

を二段構えにするのめんどくさい

Page 12: Preprocess-time Lambda Expression

どーきらしきもの

●こんなことありませんか?

●BOOST_PP_REPEATを使うときステップごとの展

開用マクロをいちいち定義するのめんどくさい

●引数がtupleのとき全要素にアクセスするためマクロ

を二段構えにするのめんどくさい

※なければ何の役にも立たない話なので適当に時

間を潰してください。

Page 13: Preprocess-time Lambda Expression

どーきらしきもの

例:void fun0() 〜 void fun9()のfowarding

declarationを作る

Page 14: Preprocess-time Lambda Expression

どーきらしきもの

例:void fun0() 〜 void fun9()のfowarding

declarationを作る

#define FWD_DECL(z, n, d) \

void BOOST_PP_CAT(d, n)();

BOOST_PP_REPEAT(10, FWD_DECL, fun)

Page 15: Preprocess-time Lambda Expression

どーきらしきもの

例:void fun0() 〜 void fun9()のfowarding

declarationを作る

#define FWD_DECL(z, n, d) \

void BOOST_PP_CAT(d, n)();

BOOST_PP_REPEAT(10, FWD_DECL, fun)

展開結果void f0();void f1();…void f9();

Page 16: Preprocess-time Lambda Expression

どーきらしきもの

例:void fun0() 〜 void fun9()のfowarding

declarationを作る

#define FWD_DECL(z, n, d) \

void BOOST_PP_CAT(d, n)();

BOOST_PP_REPEAT(10, FWD_DECL, fun)

この#define FWD_DECLを定義するのが嫌だ

展開結果void f0();void f1();…void f9();

Page 17: Preprocess-time Lambda Expression

どーきらしきもの

例:void fun0() 〜 void fun9()のfowarding

declarationを作る

#define FWD_DECL(z, n, d) \

void BOOST_PP_CAT(d, n)();

BOOST_PP_REPEAT(10, FWD_DECL, fun)

この#define FWD_DECLを定義するのが嫌だ

ラムダ式使えればいいんじゃね?

展開結果void f0();void f1();…void f9();

Page 18: Preprocess-time Lambda Expression

どーきらしきもの

例:void fun0() 〜 void fun9()のfowarding

declarationを作る

#define FWD_DECL(z, n, d) \

void BOOST_PP_CAT(d, n)();

BOOST_PP_REPEAT(10, FWD_DECL, fun)

この#define FWD_DECLを定義するのが嫌だ

ラムダ式使えればいいんじゃね?

作ってみました

展開結果void f0();void f1();…void f9();

Page 19: Preprocess-time Lambda Expression

どーきらしきもの

例:void fun0() 〜 void fun9()のfowarding

declarationを作る

#define FWD_DECL(z, n, d) \

void BOOST_PP_CAT(d, n)();

BOOST_PP_REPEAT(10, FWD_DECL, fun)

この#define FWD_DECLを定義するのが嫌だ

ラムダ式使えればいいんじゃね?

作ってみました

●http://patch-tag.com/r/digitalghost/pplambda/home

展開結果void f0();void f1();…void f9();

Page 20: Preprocess-time Lambda Expression

簡単な例

さっきのfun0〜fun9をラムダ式で

Page 21: Preprocess-time Lambda Expression

簡単な例

さっきのfun0〜fun9をラムダ式で

BOOST_PP_REPEAT(10, PP_LAMBDA_EVAL_Z,

(LAMBDA3 (void)

APPLY2(BOOST_PP_CAT)(3_, 2_)

(();),

fun))

Page 22: Preprocess-time Lambda Expression

簡単な例

さっきのfun0〜fun9をラムダ式で

BOOST_PP_REPEAT(10, PP_LAMBDA_EVAL_Z,

(LAMBDA3 (void)

APPLY2(BOOST_PP_CAT)(3_, 2_)

(();),

fun))

●PP_LAMBDA_EVAL_Zはラムダ式の評価器

Page 23: Preprocess-time Lambda Expression

簡単な例

さっきのfun0〜fun9をラムダ式で

BOOST_PP_REPEAT(10, PP_LAMBDA_EVAL_Z,

(LAMBDA3 (void)

APPLY2(BOOST_PP_CAT)(3_, 2_)

(();),

fun))

●PP_LAMBDA_EVAL_Zはラムダ式の評価器

●LAMBDA3から(();)までがラムダ式本体

Page 24: Preprocess-time Lambda Expression

簡単な例

さっきのfun0〜fun9をラムダ式で

BOOST_PP_REPEAT(10, PP_LAMBDA_EVAL_Z,

(LAMBDA3 (void)

APPLY2(BOOST_PP_CAT)(3_, 2_)

(();),

fun))

●PP_LAMBDA_EVAL_Zはラムダ式の評価器

●LAMBDA3から(();)までがラムダ式本体

●#defineとか最初からいらんかったんや!

Page 25: Preprocess-time Lambda Expression

使い方

Page 26: Preprocess-time Lambda Expression

基本1

PP_EVAL_LAMBDA(

LAMBDA2

(BOOST_PP_CAT) LPAREN ARG1 COMMA ARG2 RPAREN,

(Azniyan, Kawaiinar))

Page 27: Preprocess-time Lambda Expression

基本1

PP_EVAL_LAMBDA(

LAMBDA2

(BOOST_PP_CAT) LPAREN ARG1 COMMA ARG2 RPAREN,

(Azniyan, Kawaiinar))

●PP_EVAL_LAMBDA(expr, params)はラムダ式

の評価器

Page 28: Preprocess-time Lambda Expression

基本1

PP_EVAL_LAMBDA(

LAMBDA2

(BOOST_PP_CAT) LPAREN ARG1 COMMA ARG2 RPAREN,

(Azniyan, Kawaiinar))

●PP_EVAL_LAMBDA(expr, params)はラムダ式

の評価器

●第一引数がラムダ式

Page 29: Preprocess-time Lambda Expression

基本1

PP_EVAL_LAMBDA(

LAMBDA2

(BOOST_PP_CAT) LPAREN ARG1 COMMA ARG2 RPAREN,

(Azniyan, Kawaiinar))

●PP_EVAL_LAMBDA(expr, params)はラムダ式

の評価器

●第一引数がラムダ式

●第二引数はラムダ式の引数

Page 30: Preprocess-time Lambda Expression

展開すると

PP_EVAL_LAMBDA(

LAMBDA2

(BOOST_PP_CAT) LPAREN ARG1 COMMA ARG2 RPAREN,

(Azniyan, Kawaiinar))

Page 31: Preprocess-time Lambda Expression

展開すると

PP_EVAL_LAMBDA(

LAMBDA2

(BOOST_PP_CAT) LPAREN ARG1 COMMA ARG2 RPAREN,

(Azniyan, Kawaiinar))

BOOST_PP_CAT ( Azniyan , Kawaiinar )

Page 32: Preprocess-time Lambda Expression

展開すると

PP_EVAL_LAMBDA(

LAMBDA2

(BOOST_PP_CAT) LPAREN ARG1 COMMA ARG2 RPAREN,

(Azniyan, Kawaiinar))

BOOST_PP_CAT ( Azniyan , Kawaiinar )

AzniyanKawaiinar

Page 33: Preprocess-time Lambda Expression

展開すると

PP_EVAL_LAMBDA(

LAMBDA2

(BOOST_PP_CAT) LPAREN ARG1 COMMA ARG2 RPAREN,

(Azniyan, Kawaiinar))

BOOST_PP_CAT ( Azniyan , Kawaiinar )

AzniyanKawaiinar

※http://twitter.com/azniyan

Page 34: Preprocess-time Lambda Expression

基本2

●LAMBDAnは「n引数のラムダ式」という意味

(nは1〜3)

●以下のルール

●(hoge) → hoge●LPAREN → (●RPAREN → )●COMMA → ,●ARGn → ラムダ式のn個目の引数

の組み合わせ(nは1〜3)

Page 35: Preprocess-time Lambda Expression

もう一度あずにやんかわいいなあ

PP_EVAL_LAMBDA(

LAMBDA2

(BOOST_PP_CAT) LPAREN ARG1 COMMA ARG2 RPAREN,

(Azniyan, Kawaiinar))

BOOST_PP_CAT ( Azniyan , Kawaiinar )

AzniyanKawaiinar

Page 36: Preprocess-time Lambda Expression

もう一度あずにやんかわいいなあ

PP_EVAL_LAMBDA(

LAMBDA2

(BOOST_PP_CAT) LPAREN ARG1 COMMA ARG2 RPAREN,

(Azniyan, Kawaiinar))

BOOST_PP_CAT ( Azniyan , Kawaiinar )

AzniyanKawaiinar

LPARENやRPARENを並べた結果がマクロ呼び出しの形ならそれも展開される

Page 37: Preprocess-time Lambda Expression

LPARENとか書くのめんどくさい…

Page 38: Preprocess-time Lambda Expression

LPARENとか書くのめんどくさい…

●構文糖あります

Page 39: Preprocess-time Lambda Expression

LPARENとか書くのめんどくさい…

●構文糖あります

●APPLYn(f)(expr1, expr2, …)

= (f) LPAREN expr1 COMMA expr2 COMMA …

RPAREN

Page 40: Preprocess-time Lambda Expression

LPARENとか書くのめんどくさい…

●構文糖あります

●APPLYn(f)(expr1, expr2, …)

= (f) LPAREN expr1 COMMA expr2 COMMA …

RPAREN

●n(expr1, expr2, …)

= LPAREN expr1 COMMA expr2 COMMA …

RPAREN

Page 41: Preprocess-time Lambda Expression

LPARENとか書くのめんどくさい…

●構文糖あります

●APPLYn(f)(expr1, expr2, …)

= (f) LPAREN expr1 COMMA expr2 COMMA …

RPAREN

●n(expr1, expr2, …)

= LPAREN expr1 COMMA expr2 COMMA …

RPAREN

※ただしnは1〜3

Page 42: Preprocess-time Lambda Expression

あずにやん with 構文糖

PP_EVAL_LAMBDA(

LAMBDA2

(BOOST_PP_CAT) LPAREN ARG1 COMMA ARG2 RPAREN,

(Azniyan, Kawaiinar))

Page 43: Preprocess-time Lambda Expression

あずにやん with 構文糖

PP_EVAL_LAMBDA(

LAMBDA2

(BOOST_PP_CAT) LPAREN ARG1 COMMA ARG2 RPAREN,

(Azniyan, Kawaiinar))

は、こう書き換えられる

Page 44: Preprocess-time Lambda Expression

あずにやん with 構文糖

PP_EVAL_LAMBDA(

LAMBDA2

(BOOST_PP_CAT) LPAREN ARG1 COMMA ARG2 RPAREN,

(Azniyan, Kawaiinar))

は、こう書き換えられる

PP_EVAL_LAMBDA(

LAMBDA2

APPLY2(BOOST_PP_CAT) (ARG1, ARG2),

(Azniyan, Kawaiinar))

Page 45: Preprocess-time Lambda Expression

あずにやん with 構文糖

PP_EVAL_LAMBDA(

LAMBDA2

(BOOST_PP_CAT) LPAREN ARG1 COMMA ARG2 RPAREN,

(Azniyan, Kawaiinar))

こうも書き変えられる

PP_EVAL_LAMBDA(

LAMBDA2

(BOOST_PP_CAT) 2(ARG1, ARG2),

(Azniyan, Kawaiinar))

●APPLYを使うより短く書けるけど見た目がキモ

Page 46: Preprocess-time Lambda Expression

実用例

Page 47: Preprocess-time Lambda Expression

BOOST_PP_REPEATで

●導入で登場した例

BOOST_PP_REPEAT(10, PP_LAMBDA_EVAL_Z,

(LAMBDA3 (void)

APPLY2(BOOST_PP_CAT)(3_, 2_)

(();),

fun))

Page 48: Preprocess-time Lambda Expression

BOOST_PP_REPEATで

●導入で登場した例

BOOST_PP_REPEAT(10, PP_LAMBDA_EVAL_Z,

(LAMBDA3 (void)

APPLY2(BOOST_PP_CAT)(3_, 2_)

(();),

fun))

●ポイントは PP_LAMBDA_EVAL_Z

Page 49: Preprocess-time Lambda Expression

PP_LAMBDA_EVAL_Z

●ラムダ式で繰り返しを書くときに使う、EVALの

ラッパ

Page 50: Preprocess-time Lambda Expression

PP_LAMBDA_EVAL_Z

●ラムダ式で繰り返しを書くときに使う、EVALの

ラッパ

●「Z」はBOOST_PP_REPEATの繰り返し用関数

マクロの一つ目の引数に由来

Page 51: Preprocess-time Lambda Expression

PP_LAMBDA_EVAL_Z

●ラムダ式で繰り返しを書くときに使う、EVALの

ラッパ

●「Z」はBOOST_PP_REPEATの繰り返し用関数

マクロの一つ目の引数に由来

●BOOST_PP_REPEAT_FROM_TO や、

BOOST_PP_ENUMでもこのマクロを使えます

Page 52: Preprocess-time Lambda Expression

PP_LAMBDA_EVAL_Z

●ラムダ式で繰り返しを書くときに使う、EVALの

ラッパ

●「Z」はBOOST_PP_REPEATの繰り返し用関数

マクロの一つ目の引数に由来

●BOOST_PP_REPEAT_FROM_TO や、

BOOST_PP_ENUMでもこのマクロを使えます

●マジンガーもドラゴンボールも関係ないです

Page 53: Preprocess-time Lambda Expression

PP_LAMBDA_EVAL_Z

#define FWD_DECL(z, n, d) \

void BOOST_PP_CAT(d, n)();

BOOST_PP_REPEAT(10, FWD_DECL,

fun)

Page 54: Preprocess-time Lambda Expression

PP_LAMBDA_EVAL_Z

#define FWD_DECL(z, n, d) \

void BOOST_PP_CAT(d, n)();

BOOST_PP_REPEAT(10, FWD_DECL,

fun)

BOOST_PP_REPEAT(10, PP_LAMBDA_EVAL_Z,

(LAMBDA3 (void)

APPLY2(BOOST_PP_CAT)(3_, 2_)

(();),

fun))

Page 55: Preprocess-time Lambda Expression

PP_LAMBDA_EVAL_Z

#define FWD_DECL(z, n, d) \

void BOOST_PP_CAT(d, n)();

BOOST_PP_REPEAT(10, FWD_DECL,

fun)

BOOST_PP_REPEAT(10, PP_LAMBDA_EVAL_Z,

(LAMBDA3 (void)

APPLY2(BOOST_PP_CAT)(3_, 2_)

(();),

fun))

Page 56: Preprocess-time Lambda Expression

PP_LAMBDA_EVAL_Z

#define FWD_DECL(z, n, d) \

void BOOST_PP_CAT(d, n)();

BOOST_PP_REPEAT(10, FWD_DECL,

fun)

BOOST_PP_REPEAT(10, PP_LAMBDA_EVAL_Z,

(LAMBDA3 (void)

APPLY2(BOOST_PP_CAT)(3_, 2_)

(();),

fun))

繰り返し用マクロをEVAL_Zに変更

Page 57: Preprocess-time Lambda Expression

PP_LAMBDA_EVAL_Z

#define FWD_DECL(z, n, d) \

void BOOST_PP_CAT(d, n)();

BOOST_PP_REPEAT(10, FWD_DECL,

fun)

BOOST_PP_REPEAT(10, PP_LAMBDA_EVAL_Z,

(LAMBDA3 (void)

APPLY2(BOOST_PP_CAT)(3_, 2_)

(();),

fun))

繰り返し用マクロをEVAL_Zに変更

Page 58: Preprocess-time Lambda Expression

PP_LAMBDA_EVAL_Z

#define FWD_DECL(z, n, d) \

void BOOST_PP_CAT(d, n)();

BOOST_PP_REPEAT(10, FWD_DECL,

fun)

BOOST_PP_REPEAT(10, PP_LAMBDA_EVAL_Z,

(LAMBDA3 (void)

APPLY2(BOOST_PP_CAT)(3_, 2_)

(();),

fun))

繰り返し用マクロをEVAL_Zに変更

三つ目の引数をラムダ式と繰り返しマクロの引数のタプルにする

Page 59: Preprocess-time Lambda Expression

その他の話

Page 60: Preprocess-time Lambda Expression

Chaos Preprocessor

Page 61: Preprocess-time Lambda Expression

Chaos Preprocessor

●http://sourceforge.net/projects/chaos-pp/

Page 62: Preprocess-time Lambda Expression

Chaos Preprocessor

●http://sourceforge.net/projects/chaos-pp/

●Boost.PPの作者によるプリプロセッサメタプロ

グラミングライブラリ

Page 63: Preprocess-time Lambda Expression

例:Active Argument

●ドキュメントの一番最初に紹介されている機能

Page 64: Preprocess-time Lambda Expression

例:Active Argument

●ドキュメントの一番最初に紹介されている機能#define A(n) \ CHAOS_PP_DEFER(A_INDIRECT)()(CHAOS_PP_INC(n)) \ /**/#define A_INDIRECT() A

#define X(arg) arg#define Y(arg) X(arg)#define Z(arg) Y(arg)

A(0) // A_INDIRECT()(1)X( A(0) ) // A_INDIRECT()(2)Y( A(0) ) // A_INDIRECT()(3)Z( A(0) ) // A_INDIRECT()(4)

Page 65: Preprocess-time Lambda Expression

例:Active Argument

●ドキュメントの一番最初に紹介されている機能#define A(n) \ CHAOS_PP_DEFER(A_INDIRECT)()(CHAOS_PP_INC(n)) \ /**/#define A_INDIRECT() A

#define X(arg) arg#define Y(arg) X(arg)#define Z(arg) Y(arg)

A(0) // A_INDIRECT()(1)X( A(0) ) // A_INDIRECT()(2)Y( A(0) ) // A_INDIRECT()(3)Z( A(0) ) // A_INDIRECT()(4)

●どう使うんだろう…

Page 66: Preprocess-time Lambda Expression

中途半端に形式的な文法

pp-lambda: LAMBDA n pp-lambda-expr

pp-lambda-expr: pp-lambda-term pp-lambda-expr pp-lambda-term

pp-lambda-term: pp-lambda-literal pp-lambda-parameter pp-lambda-macro-call COMMA LPAREN RPAREN pp-lambda-tuple

pp-lambda-macro-call: APPLY n ( balanced-pp-tokens ) ( pp-lambda-expr-list )

pp-lambda-expr-list: pp-lambda-expr pp-lambda-expr-list , pp-lambda-expr

pp-lambda-parameter: digit underscore

pp-lambda-literal: ( balanced-pp-tokens )

pp-lambda-tuple: digit ( pp-lambda-expr-list )

underscore: 直前に空白文字がない _

n: 直前に空白文字がない digit

Page 67: Preprocess-time Lambda Expression

今回のブツ

●http://patch-tag.com/r/digitalghost/pplambda/home

●darcs get http://patch-tag.com/r/digitalghost/pplambda

●http://sites.google.com/site/ilikemanaka/code/pplambda.tar.bz2

Page 68: Preprocess-time Lambda Expression

ありがとう

●kothaさん

●http://www.kotha.net/

●アドバイスなどいただきました

Page 69: Preprocess-time Lambda Expression

終わり