From: Eric Blake Date: Wed, 15 Oct 2008 17:55:45 +0000 (-0600) Subject: Add m4_curry. X-Git-Tag: v2.63b~234 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c6b172ee196b189c4074f5e623f22d9b47decb6f;p=thirdparty%2Fautoconf.git Add m4_curry. * lib/m4sugar/m4sugar.m4 (m4_curry, _m4_curry): New macros. * tests/m4sugar.at (m4@&t@_map_args): Rename... (m4@&t@_map_args and m4@&t@_curry): ...and add currying tests. * doc/autoconf.texi (Looping constructs) : Document currying as a way to add parameters. (Evaluation Macros) : Document the new macro. * NEWS: Likewise. Signed-off-by: Eric Blake --- diff --git a/ChangeLog b/ChangeLog index 4e4127d4..79100bc2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,14 @@ 2008-10-17 Eric Blake + Add m4_curry. + * lib/m4sugar/m4sugar.m4 (m4_curry, _m4_curry): New macros. + * tests/m4sugar.at (m4@&t@_map_args): Rename... + (m4@&t@_map_args and m4@&t@_curry): ...and add currying tests. + * doc/autoconf.texi (Looping constructs) : Document + currying as a way to add parameters. + (Evaluation Macros) : Document the new macro. + * NEWS: Likewise. + Improve suggested test filtering. * lib/m4sugar/m4sh.m4 (_AS_DETECT_SUGGESTED_PRUNE): New macro, extracted from... diff --git a/NEWS b/NEWS index 1ba23cc5..147639b3 100644 --- a/NEWS +++ b/NEWS @@ -13,7 +13,8 @@ GNU Autoconf NEWS - User visible changes. ** Configure scripts now use shell functions. ** The following m4sugar macros are new: - m4_default_quoted m4_map_args m4_map_args_pair m4_set_map + m4_curry m4_default_quoted m4_map_args m4_map_args_pair + m4_set_map ** The following documented m4sh macros are new: AS_LINENO_PREPARE AS_ME_PREPARE AS_VAR_COPY diff --git a/doc/autoconf.texi b/doc/autoconf.texi index d539329e..3078869a 100644 --- a/doc/autoconf.texi +++ b/doc/autoconf.texi @@ -10930,7 +10930,7 @@ m4_count(m4_map_sep([m4_echo], [[,]], [[[a]], [[b]]])) @defmac m4_map_args (@var{macro}, @var{arg}@dots{}) @msindex{map_args} -Repeatedly invoke @var{macro} with each successive @var{arg} as its +Repeatedly invoke @var{macro} with each successive @var{arg} as its only argument. In the following example, three solutions are presented with the same expansion; the solution using @code{m4_map_args} is the most efficient. @@ -10943,6 +10943,30 @@ m4_map([ m4_echo], [[[plain]], [[active]]]) m4_map_args([ m4_echo], [plain], [active]) @result{} plain active @end example + +In cases where it is useful to operate on additional parameters besides +the list elements, the macro @code{m4_curry} can be used in @var{macro} +to supply the argument currying necessary to generate the desired +argument list. In the following example, @code{list_add_n} is more +efficient than @code{list_add_x}. + +@example +m4_define([list], [[1], [2], [3]])dnl +m4_define([add], [m4_eval(([$1]) + ([$2]))])dnl +dnl list_add_n(N, ARG...) +dnl Output a list consisting of each ARG added to N +m4_define([list_add_n], +[m4_shift(m4_map_args([,m4_curry([add], [$1])], m4_shift($@@)))])dnl +list_add_n([1], list) +@result{}2,3,4 +list_add_n([2], list) +@result{}3,4,5 +m4_define([list_add_x], +[m4_shift(m4_foreach([var], m4_dquote(m4_shift($@@)), + [,add([$1],m4_defn([var]))]))])dnl +list_add_x([1], list) +@result{}2,3,4 +@end example @end defmac @defmac m4_map_args_pair (@var{macro}, @dvar{macro-end, macro}, @ @@ -11010,6 +11034,19 @@ This macro returns the decimal count of the number of arguments it was passed. @end defmac +@defmac m4_curry (@var{macro}, @var{arg}@dots{}) +@msindex{curry} +This macro performs argument currying. The expansion of this macro is +another macro name that expects exactly one argument; that argument is +then appended to the @var{arg} list, and then @var{macro} is expanded +with the resulting argument list. + +@example +m4_curry([m4_curry], [m4_reverse], [1])([2])([3]) +@result{}3, 2, 1 +@end example +@end defmac + @defmac m4_do (@var{arg}, @dots{}) @msindex{do} This macro loops over its arguments and expands each @var{arg} in diff --git a/lib/m4sugar/m4sugar.m4 b/lib/m4sugar/m4sugar.m4 index 2d50230d..ee8ee63e 100644 --- a/lib/m4sugar/m4sugar.m4 +++ b/lib/m4sugar/m4sugar.m4 @@ -726,6 +726,20 @@ m4_define([_m4_apply], m4_define([m4_count], [$#]) +# m4_curry(MACRO, ARG...) +# ----------------------- +# Perform argument currying. The expansion of this macro is another +# macro that takes exactly one argument, appends it to the end of the +# original ARG list, then invokes MACRO. For example: +# m4_curry([m4_curry], [m4_reverse], [1])([2])([3]) => 3, 2, 1 +# Not quite as practical as m4_incr, but you could also do: +# m4_define([add], [m4_eval(([$1]) + ([$2]))]) +# m4_define([add_one], [m4_curry([add], [1])]) +# add_one()([2]) => 3 +m4_define([m4_curry], [$1(m4_shift($@,)_$0]) +m4_define([_m4_curry], [[$1])]) + + # m4_do(STRING, ...) # ------------------ # This macro invokes all its arguments (in sequence, of course). It is diff --git a/tests/m4sugar.at b/tests/m4sugar.at index d6f40a7a..f34bca36 100644 --- a/tests/m4sugar.at +++ b/tests/m4sugar.at @@ -37,21 +37,6 @@ AT_CHECK_M4SUGAR([-o-],, [$2], [$3]) ])# AT_CHECK_M4SUGAR_TEXT -# Order of the tests: -# - m4_warn -# -# - m4_require -# uses warn/error code. -# -# - m4_split -# -# - m4_append -# -# - m4_join -# -# - m4_text_wrap -# uses m4_split code. - ## --------- ## ## m4_defn. ## ## --------- ## @@ -866,13 +851,27 @@ hi AT_CLEANUP -## --------------------- ## -## m4_map_args{,_pair}. ## -## --------------------- ## +## ---------------------------------- ## +## m4_map_args{,_pair} and m4_curry. ## +## ---------------------------------- ## -AT_SETUP([m4@&t@_map_args]) +AT_SETUP([m4@&t@_map_args and m4@&t@_curry]) AT_KEYWORDS([m4@&t@_map_args_pair m4@&t@_reverse]) +dnl First, make sure we can curry in isolation. +AT_CHECK_M4SUGAR_TEXT( +[[m4_curry([m4_echo])([1]) +m4_curry([m4_curry], [m4_reverse], [1])([2])([3]) +m4_define([add], [m4_eval(([$1]) + ([$2]))])dnl +m4_define([add_one], [m4_curry([add], [1])])dnl +add_one()([4]) +]], +[[1 +3, 2, 1 +5 +]]) + +dnl Now, check that we can map a list of arguments. AT_CHECK_M4SUGAR_TEXT([[m4_define([active], [ACTIVE])dnl m4_map_args([ m4_echo]) m4_map_args([ m4_echo], [plain], [active]) @@ -901,6 +900,21 @@ plainACTIVE , 2, 1, 4, 3 ]]) +dnl Finally, put the two concepts together, to show the real power of the API. +AT_CHECK_M4SUGAR_TEXT( +[[m4_define([add], [m4_eval(([$1]) + ([$2]))])dnl +m4_define([list], [[-1], [0], [1]])dnl +dnl list_add_n(value, arg...) +dnl add VALUE to each ARG and output the resulting list +m4_define([list_add_n], + [m4_shift(m4_map_args([,m4_curry([add], [$1])], m4_shift($@)))]) +list_add_n([1], list) +list_add_n([2], list) +]], [[ +0,1,2 +1,2,3 +]]) + AT_CLEANUP