diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2011-10-25 23:04:48 -0400 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2011-10-25 23:04:48 -0400 |
commit | 2987f69f690d8433ad3aaa9e9f41949455ada2cb (patch) | |
tree | b08a9038924133265563690bab95ac8b6d79fc17 | |
parent | 4e61cfe45d3fa26f73870c0242798c9d42eb5baf (diff) | |
download | txr-2987f69f690d8433ad3aaa9e9f41949455ada2cb.tar.gz txr-2987f69f690d8433ad3aaa9e9f41949455ada2cb.tar.bz2 txr-2987f69f690d8433ad3aaa9e9f41949455ada2cb.zip |
* filter.c (function_filter): Function removed.
(get_filter): Treat (:fun ...) syntax as a single function
call with extra arguments, currying it up as curried function that
invokes match_funcall once.
* match.c (match_funcall): Extended to take a list of the
additional arguments from get_filter. Adds these to the
function call form generated for the v_func call.
* match.h (match_funcall): Declaration updated.
* txr.1: Function Filter additional arguments documented.
-rw-r--r-- | filter.c | 8 | ||||
-rw-r--r-- | match.c | 17 | ||||
-rw-r--r-- | match.h | 2 | ||||
-rw-r--r-- | txr.1 | 47 |
4 files changed, 56 insertions, 18 deletions
@@ -137,17 +137,11 @@ static val compound_filter(val filter_list, val string) return reduce_left(func_n2(string_filter), filter_list, string, nil); } -static val function_filter(val functions, val string) -{ - return reduce_left(swap_12_21(func_n2(match_funcall)), - functions, string, nil); -} - val get_filter(val spec) { if (consp(spec)) { if (car(spec) == fun_k) { - return curry_12_2(func_n2(function_filter), rest(spec)); + return curry_123_2(func_n3(match_funcall), second(spec), rest(rest(spec))); } else { val filter_list = mapcar(func_n1(get_filter), spec); @@ -2819,14 +2819,17 @@ repeat_spec_same_data: return cons(c.bindings, if3(c.data, cons(c.data, c.data_lineno), t)); } -val match_funcall(val name, val arg) +val match_funcall(val name, val arg, val other_args) { cons_bind (in_spec, in_bindings, uw_get_match_context()); spec_bind (specline, spec_linenum, first_spec, in_spec); - val arg1_sym = make_sym(lit("arg1")), arg2_sym = make_sym(lit("arg2")); - val bindings = cons(cons(arg1_sym, arg), in_bindings); + val in_arg_sym = make_sym(lit("in_arg")); + val out_arg_sym = make_sym(lit("out_arg")); + val bindings = cons(cons(in_arg_sym, arg), in_bindings); val spec = cons(list(spec_linenum, - list(name, arg1_sym, arg2_sym, nao), nao), nil); + cons(name, + cons(in_arg_sym, cons(out_arg_sym, other_args))), + nao), nil); match_files_ctx nc; (void) first_spec; @@ -2834,17 +2837,17 @@ val match_funcall(val name, val arg) if (ret == nil) sem_error(spec_linenum, lit("filter: (~s ~s ~s) failed"), name, - arg, arg2_sym, nao); + arg, out_arg_sym, nao); if (ret == decline_k) sem_error(spec_linenum, lit("filter: function ~s not found"), name, nao); { - val out = assoc(nc.bindings, arg2_sym); + val out = assoc(nc.bindings, out_arg_sym); if (!out) sem_error(spec_linenum, lit("filter: (~s ~s ~s) did not bind ~s"), name, - arg, arg2_sym, arg2_sym, nao); + arg, out_arg_sym, out_arg_sym, nao); return cdr(out); } } @@ -25,6 +25,6 @@ */ void match_init(void); -val match_funcall(val name, val arg); +val match_funcall(val name, val arg, val other_args); int extract(val spec, val filenames, val bindings); extern val choose_s; @@ -3041,12 +3041,14 @@ A function can be used as a filter. For this to be possible, the function must conform to certain rules: .IP 1. -The function must take exactly two arguments. +The function must take two special arguments, which may be followed +by additional arguments. .IP 2. When the function is called, the first argument will be bound to a string, -and the second argument will be unbound. The function must produce a string -value by binding it to the second argument. +and the second argument will be unbound. The function must produce a +value by binding it to the second argument. If the filter is to be used +as the final filter in a chain, it must produce a string. For instance, the following is a valid filter function: @@ -3078,6 +3080,45 @@ Of course, function filters can be used in a chain: ... @(end) +Here is a split function which takes an extra argument. + + @(define split (in out sep)) + @ (next :list in) + @ (coll)@(maybe)@token@sep@(or)@token@(end)@(end) + @ (bind out token) + @(end) + +Furthermore, note that it produces a list rather than a string. +This function separates the argument in into tokens according to the +separator text sep. + +Here is another function, join, which catenates a list: + + @(define join (in out sep)) + @ (output :into out) + @ (rep)@in@sep@(last)@in@(end) + @ (end) + @(end) + +Now here is these two being used in a chain: + + @(bind text "how,are,you") + @(output :filter (:fun split ",") (:fun join "-")) + @text + @(end) + +Output: + + how-are-you + +When the filter invokes a function, it generates the first two arguments +internally to pass in the input value and capture the output. The remaining +arguments from the (:fun ...) construct are also passed to the function. +Thus the "," and "-" are passed as the sep argument to split and join. + +Note that split puts out a list, which join accepts. So the overall filter +chain operates on a string: a string goes into split, and a string comes out of +join. .SS The Deffilter Directive |