diff options
-rw-r--r-- | autoload.c | 2 | ||||
-rw-r--r-- | stdlib/op.tl | 3 | ||||
-rw-r--r-- | tests/012/op.tl | 12 | ||||
-rw-r--r-- | txr.1 | 66 |
4 files changed, 82 insertions, 1 deletions
@@ -712,7 +712,7 @@ static val op_set_entries(val fun) lit("op"), lit("do"), lit("lop"), lit("ldo"), lit("ap"), lit("ip"), lit("ado"), lit("ido"), lit("ret"), lit("aret"), lit("opip"), lit("oand"), lit("lopip"), lit("loand"), - lit("opf"), lit("lopf"), lit("flow"), lit("lflow"), + lit("opf"), lit("lopf"), lit("flow"), lit("lflow"), lit("tap"), nil }; autoload_set(al_fun, name, fun); diff --git a/stdlib/op.tl b/stdlib/op.tl index 79786f20..6c3966b1 100644 --- a/stdlib/op.tl +++ b/stdlib/op.tl @@ -276,3 +276,6 @@ (defmacro lflow (val . opip-args) ^(call (lopip ,*opip-args) ,val)) + +(defmacro tap (. args) + ^(prog1 @1 ,args)) diff --git a/tests/012/op.tl b/tests/012/op.tl index 1652b3c8..47f1f80d 100644 --- a/tests/012/op.tl +++ b/tests/012/op.tl @@ -113,3 +113,15 @@ (mtest (remove-if (opf orf (< 10) (> 5)) (range 0 20)) (5 6 7 8 9 10) (remove-if (lopf orf (> 10) (< 5)) (range 0 20)) (5 6 7 8 9 10)) + +(test + (let ((x 0) (y 0)) + (list (flow x + (+ 2) + (tap inc y @1) + (* 4) + (tap inc y @1) + (+ 5) + (tap inc y @1)) + y)) + (13 23)) @@ -59934,6 +59934,72 @@ and the expression returns a function similar to .codn "(lambda (. rest) 42)" . +.coNP Macro @ tap +.synb +.mets (tap << arg +) +.syne +.desc +The +.code tap +macro is intended for use in conjunction with +.codn opip , +.code flow +and other macros in that family. It is a short-hand for writing a pipeline +element which performs a side-effecting operation, but unconditionally returns +the original input value. + +The exact expansion of +.code tap +is unspecified, but the following equivalence indicates a possible +expansion strategy: + +.verb + (tap ...) <--> (prog1 @1 (...)) +.brev + +Assuming that expansion strategy, the expression +.code "(tap put-line `foo: @1`)" +would expand to +.codn "(prog1 @1 (put-line `foo: @1`))" . + +Note: +.codn tap , +in addition to being useful for inserting necessary +side effects into pipelines, is also +useful for inserting temporary debug print forms. For that purpose, inserting +the `prinl` function is often enough: + +.verb + (flow 10 (+ 2) print (* 4)) +.brev + +Here, the pipeline will calculate +.code "(* 4 (+ 2 10))" +with the side effect of the value of +.code "(+ 2 10)" +being printed. With +.codn tap , +the output can be customized, allowing multiple output +points to be distinguished. + +.verb + (flow 10 + (tap put-line `input: @1`) + (+ 2) + (tap put-line `+ 2: @1`) + (* 4) + (tap put-line `* 4: @1`)) + -> 48 +.brev + +Output produced: + +.verb + input: 10 + + 2: 12 + * 4: 48 +.brev + .coNP Function @ dup .synb .mets (dup << func ) |