srfi.197
- Pipeline operators ¶This module provides a set of macros to compose multiple operations. It is similar to Clojure’s “threading macro”.
When you’re passing a result of some procedure to another procedure and so on, sometimes you get a deeply nested expression:
(g (f (e (d (c (b (a arg)))))))
In Gauche, you can also write the above expression with $
macro
(see Making procedures):
($ g $ f $ e $ d $ c $ b $ a arg)
Deep nesting is avoided, but it’s still right-to-left, and the placement of argument to receive the previous result is limited to the last position.
With chain
macro in this module, you can write it
from left to right:
(chain (a arg) (b _) (c _) (d _) (e _) (f _) (g _))
The _
in the second expressions and after indicates the place
where previous result is passed.
It is conceptually expanded to the following:
(let* ((tmp (a arg)) (tmp (b tmp)) (tmp (c tmp)) (tmp (d tmp)) (tmp (e tmp))) (g tmp))
Because the placeholder is explicit, you can pass additional arguments:
(chain x (y a _) (z _ b)) ≡ (let* ((tmp x) (tmp (y a tmp))) (z tmp b))
Or even use multiple values:
(chain mv-expr (f _ _) (g _ _)) ≡ (let*-values (((tmp1 tmp2) mv-expr) ((tmp1 tmp2) (f tmp1 tmp2))) (g tmp1 tmp2))
[SRFI-197]{srfi.197
}
The optional placeholder and ellipsis are, if given,
literal symbols. It replaces the default placeholder and ellipsis
symbols, _
and ...
, respectively.
Each step is (datum …)
, where each datum
must be either an expression, placeholder symbol, or the ellipsis symbol.
The ellipsis symbol must appear in the last position, if any,
and must immediately follow the placeholder symbol.
Conceptually, each step becomes a procedure that takes as many arguments as the placeholders. If the step ends with ellipsis symbol, the last placeholder works as the “rest” arguments.
If a step expects more than one value, the previous step or initial-value is expected to yield that many values.
(chain expr (f _ a _ ...)) ≡ (let*-values (((tmp1 . tmp2) expr)) (apply f tmp1 a tmp2))
[SRFI-197]{srfi.197
}
A variant of chain
that stops and returns #f
immedialy when the intermediate result becomes #f
.
The initial-value is an expression that yields one value.
The placeholder is a literal symbol to be used as the placeholder
in step; if omitted, _
is used.
Unlike chain
, a step can only contain zero or one placeholder
symbol. If step doesn’t contain placeholder symbol, the previous
step’s result isn’t passed, but it is still checked if it’s #f
.
[SRFI-197]{srfi.197
}
A variant of chain
where you can select whether each step
is applied or skipped.
Each step can have at most one placeholder symbol, just as
chain-and
.
Each guard is an expression. For each step, guard is
evaluated, and if it yields a true value, the previous result is
passed to the placeholder in the corresponding step. If
guard yields #f
, however, step is skipped and
the previous value is passed through to the next 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
}
Similar to chain
, except the order of steps is right-to-left.
Each step must have exactly one placeholder symbol, for this macro simply nests the steps:
(nest (f a _) (g _ b) (h _) expr) ≡ (f a (g (h expr) b))
[SRFI-197]{srfi.197
}
Similar to nest
except the nesting is in reverse order.
Each step must have exactly one placeholder symbol, for this macro simply nests the steps:
(nest expr (h _) (g _ b) (f a _)) ≡ (f a (g (h expr) b))