srfi.197
- パイプラインオペレータ ¶このモジュールは、複数の操作を組み合わせるマクロを提供します。 Clojureの「スレッドマクロ」に似たものです。
ひとつの関数適用の結果を別の関数に渡して…というのをつなげてゆくと、 しばしば式のネストが深くなってしまいます:
(g (f (e (d (c (b (a arg)))))))
Gaucheでは$
マクロを使えば上の式はこうも書けます
(手続きを作る参照):
($ g $ f $ e $ d $ c $ b $ a arg)
ネストは浅くなりましたが、適用順は依然として右から左で、 また前の結果を引数として渡す位置が最後の引数に限られます。
このモジュールのchain
マクロを使うと、
上の式は左から右にデータを流すように書けます:
(chain (a arg) (b _) (c _) (d _) (e _) (f _) (g _))
2番目以降の式中の_
は、前の結果をその位置の引数で受け取ることを示します。
上の式は概念的には次の式と等価です。
(let* ((tmp (a arg)) (tmp (b tmp)) (tmp (c tmp)) (tmp (d tmp)) (tmp (e tmp))) (g tmp))
引数をはめ込む場所を明示できるので、他の引数も自由に渡せます:
(chain x (y a _) (z _ b)) ≡ (let* ((tmp x) (tmp (y a tmp))) (z tmp b))
多値を受け取って複数の引数として渡すこともできます:
(chain mv-expr (f _ _) (g _ _)) ≡ (let*-values (((tmp1 tmp2) mv-expr) ((tmp1 tmp2) (f tmp1 tmp2))) (g tmp1 tmp2))
[SRFI-197]{srfi.197
}
省略可能なplaceholderとellipsis引数は、
リテラルシンボルでなければなりません。与えられた場合は、
デフォルトのプレースホルダ_
とエリプシス...
を置き換えます。
各stepは(datum …)
の形で、
datumは式、プレースホルダ、あるいはエリプシスです。
但し、エリプシスは最後の要素としてのみ許され、現れた場合は直前がプレースホルダ
でなければなりません。
概念的には、各stepはプレースホルダの数だけ引数を取る手続きへと展開されます。 手続きに渡された引数は順にプレースホルダの箇所に充てられます。 stepの最後がエリプシスだった場合は、直前のプレースホルダが “rest” 引数として 動作します。
stepが一つ以上の値を期待する場合、直前のstepもしくは initial-valueは同じ数だけの値を生成せねばなりません。
(chain expr (f _ a _ ...)) ≡ (let*-values (((tmp1 . tmp2) expr)) (apply f tmp1 a tmp2))
[SRFI-197]{srfi.197
}
chain
の変種で、中間の結果が#f
になった場合にその後のstepの
評価を行わず直ちに#f
を返します。
initial-valueはひとつの値を返す式です。
placeholderはstep中でプレースホルダーとして使われるリテラルシンボルです。
省略時には_
が使われます。
chain
と違い、各stepはたかだか1個のプレースホルダーしか
含むことができません。stepがプレースホルダーを含んでいない場合、
直前のstepの結果は操作を打ちきるかどうかの判定のみに使われ、その後捨てられます。
[SRFI-197]{srfi.197
}
chain
の変種で、stepを適用するかどうかを選べるものです。
chain-and
と同じく、各stepはプレースホルダーをたかだか1個までしか
含むことができません。
各guardは式です。各ステップで、まずguardが評価され、 それが真ならば直前に実行された結果がプレースホルダーに束縛されて 対応するstepが実行されます。guardが偽ならば、 stepは実行されず、直前の結果が次のステップへと持ち越されます。
(chain-when expr ((p? x) (f _)) ((q? x) (g _))) ≡ (let* ([tmp expr] [tmp (if (p? x) (f tmp) tmp)]) (if (q? x) (g tmp) tmp))
[SRFI-197]{srfi.197
}
(chain-lambda step ...) ≡ (lambda args (chain (apply values args) step ...))
[SRFI-197]{srfi.197
}
chain
と似ていますが、評価順が右から左になります。
各stepはひとつだけプレースホルダーシンボルを持たなければなりません。 このマクロは単にステップをネストした式に変換するだけです。
(nest (f a _) (g _ b) (h _) expr) ≡ (f a (g (h expr) b))
[SRFI-197]{srfi.197
}
nest
の評価順が逆になったものです。
各stepはひとつだけプレースホルダーシンボルを持たなければなりません。 このマクロは単にステップをネストした式に変換するだけです。
(nest expr (h _) (g _ b) (f a _)) ≡ (f a (g (h expr) b))