Received: from mx0.gmx.net (mx0.gmx.net [213.165.64.100]) by h1439878.stratoserver.net (8.14.2/8.14.2/Debian-2build1) with SMTP id q165fJEm025990 for ; Mon, 6 Feb 2012 06:41:20 +0100 Received: (qmail 8646 invoked by alias); 6 Feb 2012 05:41:14 -0000 Delivered-To: GMX delivery to rainer.schoepf@gmx.net Received: (qmail invoked by alias); 06 Feb 2012 05:40:30 -0000 Received: from relay.uni-heidelberg.de (EHLO relay.uni-heidelberg.de) [129.206.100.212] by mx0.gmx.net (mx112) with SMTP; 06 Feb 2012 06:40:30 +0100 Received: from listserv.uni-heidelberg.de (listserv.uni-heidelberg.de [129.206.100.94]) by relay.uni-heidelberg.de (8.14.1/8.14.1) with ESMTP id q165cR39001247 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Mon, 6 Feb 2012 06:38:27 +0100 Received: from listserv.uni-heidelberg.de (localhost.localdomain [127.0.0.1]) by listserv.uni-heidelberg.de (8.13.1/8.13.1) with ESMTP id q164jSIG011310; Mon, 6 Feb 2012 06:38:26 +0100 Received: by LISTSERV.UNI-HEIDELBERG.DE (LISTSERV-TCP/IP release 16.0) with spool id 1938719 for LATEX-L@LISTSERV.UNI-HEIDELBERG.DE; Mon, 6 Feb 2012 06:38:26 +0100 Received: from relay.uni-heidelberg.de (relay.uni-heidelberg.de [129.206.100.212]) by listserv.uni-heidelberg.de (8.13.1/8.13.1) with ESMTP id q165cQUi019277 for ; Mon, 6 Feb 2012 06:38:26 +0100 Received: from neptune.ucc.ie (neptune.ucc.ie [143.239.153.183]) by relay.uni-heidelberg.de (8.14.1/8.14.1) with ESMTP id q165cB1N001206 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) for ; Mon, 6 Feb 2012 06:38:15 +0100 Received: from csmvddesktop (csmvddesktop.ucc.ie [143.239.74.97]) (using TLSv1 with cipher DHE-RSA-AES128-SHA (128/128 bits)) (No client certificate requested) (Authenticated sender: dongen) by neptune.ucc.ie (Postfix) with ESMTPSA id 8F480200B4 for ; Mon, 6 Feb 2012 05:38:32 +0000 (GMT) References: <20120202131844.GA16372@csmvddesktop> <20120202133153.GA16604@csmvddesktop> <20120203151218.GA30208@csmvddesktop> <4F2BFFA6.1020306@morningstar2.co.uk> <20120203155926.GA30436@csmvddesktop> <20120205160826.GA6939@csmvddesktop> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="oyUTqETQ0mS9luUI" Content-Disposition: inline User-Agent: Mutt/1.5.21 (2010-09-15) Message-ID: <20120206054259.GB9462@csmvddesktop> Date: Mon, 6 Feb 2012 05:43:00 +0000 Reply-To: Mailing list for the LaTeX3 project Sender: Mailing list for the LaTeX3 project From: dongen Subject: Re: Mapping Functions Versions for All and Some To: LATEX-L@listserv.uni-heidelberg.de In-Reply-To: Precedence: list List-Help: , List-Unsubscribe: List-Subscribe: List-Owner: List-Archive: X-GMX-Antispam: 0 (eXpurgate); Detail=5D7Q89H36p5+Mpb3vmnHTDIU8u+6N2XmmbZdtUIjxY8FaAV3JRAl8RCULbHK25jI03Yr9 PfBzNZrdyc32zIhVV7FCaTM9XAGukVBIVNeFkuKcW3c55mp8NhbfAJoNaBhWrghKxibAJUjraNVN FNOqQN57WOxmD2Z3T68ur01FTi2JmW0atYINibLBdrImmrIu//3dt0Qznw=V1; X-Resent-By: Forwarder X-Resent-For: rainer.schoepf@gmx.net X-Resent-To: rainer@rainer-schoepf.de Status: R X-Status: X-Keywords: X-UID: 7023 --oyUTqETQ0mS9luUI Content-Type: text/plain; charset=us-ascii Content-Disposition: inline * Bruno Le Floch [2012-02-05 13:01:41 -0500]: Hi Bruno, Thanks again for your comments. I've learned a lot. I've incorporated most of your changes but some don't work, most are related to regex. BTW, some of your suggestions in relation to regex are not documented. For example, \u. As it stands, the output that's generated by \meaning looks OK, but it isn't. I don't know enough of plain TeX to know why, but I suspect it has to do with (regex) substitutions that involve \#1. The following paragraph explains why. If you look at the .tex file (I'm attaching .sty and .tex) you will see that I'm redefining \recurrence_f_2:n in the exact same way as \meaning suggests it's defined. After this definition \f works flawlessly. Without, it will fail for any argument greater than 1. I suspect that this is because the printed #1 may not be correspond to the positional parameter #1. At the very end of this email, I'll say a bit more about the substitutions. The following are some more comments to your previous email. : (4) As it is, the code will un forever on negative input. You should : probably use \int_compare_p:n {#1>0} or something like that in the _2 : function. That's deliberate. I wanted to keep things simple. : (5) Of course you know it, this code will run exponentially slowly for : large input. That is difficult to solve (but doable; I can give : details) if you want an expandable function which expands to the value : of your recursion. For a non-expandable function of the form : \recursion_get_value_f:nN { } (dunno how the : function should be called), getting a linear-time solution should be : easier: it involves storing the intermediate results as you get them. Thanks. I know the solution. As soon as everything works, I want to provide a flag, which the user can use to tell whether or not to cache the previously computed values. : - Naming a function \foo:xx doesn't magically cause expansion of the : args. You need to define \foo:nn, then \cs_generate_variant:Nn \foo:nn : { xx }. Thanks. I now understand. When I'll provide my remaining comments about the expl3 documentation I'll once more give some comments about that part of the documentation. I think the documentation is right but it's not clear for somebody who is new to the matter. (Or for that sake, somebody like me who doesn't know enough low-level TeX. It would be nicer if the documentation could be explained without reference to TeX. I think it should be possible.) : - Variables should be renamed to indicate whether they are local or : global, and in the team we always put the variable's type (tl, : int,...) at the end. Thanks. : [ snip ] : \cs_new_nopar:Npn \recurrence_define_constant:xx #1#2{% : \edef\recurrence_current_case_count{\int_use:N \recurrence_case_count} : % Shudder. : % => \int_set_eq:NN \l_recurrence_current_case_int \l_recurrence_case_int : % (of course, you'll need \int_new:N \l_recurrence_current_case_int before) : \int_incr:N \recurrence_case_count : \cs_new_nopar:cpx {\recurrence_case_name:n : \recurrence_current_case_count} ##1{ : \exp_not:N : \int_compare:nTF {##1=#1} {#2} : {\cs:w \recurrence_case_name:N \recurrence_case_count : \cs_end:{##1}} : } : } : % - If you use \int_eval:n in the previous function, you can drop the : % recurrence_current_case variable completely, and use : % \recurrence_case_name:n { \l_recurrence_case_int + 1 } That doesn't work. If I use \cs_new_nopar:cpx {\recurrence_case_name:n {\l_recurrence_case_count_int - 1}} ##1{ I get a run time error, even for f{0}. I haven't had the time to look into it but I'll do it when everything else works. (Saving the variable is my least concern.) : % #1 is name : % #2 is index : % #3 is tl list : \cs_new_nopar:Npn \recurrence_sanitise:nnN #1#2#3{ : \regex_replace_all:nnN {#2} {\#1} #3 % This \# looks very odd. : Perhaps "\cP\#" ? : \regex_replace_all:nnN {\b#1\b\[([^\]]+)\]} {\\#1:n\{\1\}} #3 : } I've now changed this to: % #1 is name % #2 is index % #3 is tl list \cs_new_nopar:Npn \recurrence_sanitise:nnN #1#2#3{ \regex_replace_all:nnN {#2} {\#1} #3 \regex_replace_all:nnN {\b#1\[([^\]]+)\]} {\\#1:n \cB\{\1 \cE\}} #3 } \cs_generate_variant:Nn \recurrence_sanitise:nnN {VV} \cP\# doesn't work. I get the following error: Illegal parameter number in definition of \regex_replacement_tl:n. : % The second \b does nothing. Including #1 directly is risky if it : % contains special characters that should be escaped. Instead, : % you should try " \u{l_recurrence_name_tl} " (or whatever tl var : % contains that #1). l_recurrence_name_tl is indeed the one. I tried \u{l_recurrence_name_tl} but then the substitution didn't work at all. : % \\#1:n\{\1\} : % => \c{\u{l_recurrence_name_tl}:n} \cB\{ \1 \cE\} : % What does this do? Well, \c{...} is like the c-type argument : % (think \exp_not:c). \u{...} is like the v-type argument, and : % unpacks the variable \l_recurrence_name_tl, so that's similar : % to your \\#1:n, except that it produces an actual control sequence : % instead of a string of characters with catcode other. I tried \c{\u{l_recurrence_name_tl}:n} as well but again, the substitution didn't work at all. : [ snip ] Thanks! Regards, Marc --oyUTqETQ0mS9luUI Content-Type: text/x-tex; charset=us-ascii Content-Disposition: attachment; filename="recurrence.sty" \NeedsTeXFormat{LaTeX2e} \ProvidesPackage{recurrence}[2012/02/02 Recurrence Equation Support] %\usepackage{tikz} \usepackage{xparse} \usepackage{expl3} \usepackage{l3regex} \usepackage{l3int} \ExplSyntaxOn \tl_new:N \l_recurrence_bin_tl \tl_new:N \l_recurrence_temp_seq \tl_new:N \l_recurrence_name_tl \tl_new:N \l_recurrence_index_tl \tl_new:N \l_recurrence_rhs_tl \tl_new:N \l_recurrence_guard_tl \int_new:N \l_recurrence_case_count_int \int_new:N \l_recurrence_current_case_count_int % FOLLOWING NOT USED \regex_const:Nn \c_recurrence_true_regex { true } \regex_const:Nn \c_recurrence_integer_regex { ^[-+]*[0-9]+$ } \tl_const:Nn \c_recurrence_prefix_tl { recurrence } % #1 is expression \cs_new_protected_nopar:Npn \recurrence_is_integer:nTF #1{ \regex_match:NnTF \c_recurrence_integer_regex {#1} } \cs_generate_variant:Nn \recurrence_is_integer:nTF { V } \cs_new_nopar:Npn \recurrence_case_name:nn #1#2{ \tl_use:N \c_recurrence_prefix_tl _ #1 _ #2:n } % #1 is integer variable \cs_new_nopar:Npn \recurrence_case_name:n #1{ \recurrence_case_name:nn \l_recurrence_name_tl {\int_eval:n #1} } % #1 is index % #2 is rhs \cs_new_nopar:Npn \recurrence_define_constant:xx #1#2{% \int_set_eq:NN \l_recurrence_current_case_count_int \l_recurrence_case_count_int \int_incr:N \l_recurrence_case_count_int \cs_new_nopar:cpx {\recurrence_case_name:n \l_recurrence_current_case_count_int} ##1{ \exp_not:N \int_compare:nTF {##1=#1} {#2} {\cs:w \recurrence_case_name:n \l_recurrence_case_count_int \cs_end:{##1}} } } % #1 is guard tl % #2 is rhs tl \cs_new_nopar:Npn \recurrence_case_definition:xx #1#2{ \int_set_eq:NN \l_recurrence_current_case_count_int \l_recurrence_case_count_int \int_incr:N \l_recurrence_case_count_int \cs_new_nopar:cpx {\recurrence_case_name:n \l_recurrence_current_case_count_int} ##1{ \exp_not:N \bool_if:nTF {#1} {#2} {\cs:w \recurrence_case_name:n \l_recurrence_case_count_int \cs_end:{##1}} } } % #1 is name tl % #2 is index tl \cs_new_nopar:Npn \recurrence_case_definition:NN #1#2{ \recurrence_sanitise:VVN #1 #2 \l_recurrence_rhs_tl \recurrence_sanitise:VVN #1 #2 \l_recurrence_guard_tl \regex_replace_all:NnN \c_recurrence_true_regex {\c{int_compare_p:n} \cB\{ 1 = 1 \cE\}} \l_recurrence_guard_tl \recurrence_case_definition:xx \l_recurrence_guard_tl \l_recurrence_rhs_tl } % #1 is name % #2 is index % #3 is tl list \cs_new_nopar:Npn \recurrence_sanitise:nnN #1#2#3{ \regex_replace_all:nnN {#2} {\#1} #3 \regex_replace_all:nnN {\b#1\[([^\]]+)\]} {\\#1:n \cB\{\1 \cE\}} #3 } \cs_generate_variant:Nn \recurrence_sanitise:nnN {VV} \cs_new_nopar:Npn \recurrence_error_definition:{ \int_set_eq:NN \l_recurrence_current_case_count_int \l_recurrence_case_count_int \cs_new:cpx {\recurrence_case_name:n \l_recurrence_current_case_count_int}##1{ 0\exp_not:N \msg_expandable_error:n {\tl_use:N \l_recurrence_name_tl[~##1~]~undefined.} } } \cs_new_nopar:Npn \recurrence_wrapper_definitions:{ \cs_new_nopar:cpx { \l_recurrence_name_tl } ##1{% \exp_not:N \int_eval:n {\exp_not:c { \l_recurrence_name_tl :n } {##1}} } \cs_new_nopar:cpx { \l_recurrence_name_tl :n } ##1{% \exp_not:N \exp_args:Nf \exp_not:c { \recurrence_case_name:n 0 } { \exp_not:N \int_eval:n {##1} } } } \cs_new_nopar:Npn \recurrence_rec_def:n #1{ \group_begin: \clist_set:Nn \recurrence_csv_list {#1} \clist_map_inline:Nn \recurrence_csv_list { \regex_extract_once:nnNTF { ^(\w+)\[(\w+)\]\=(.+?)\|(.+)\|(.+) } {##1|true||} \l_recurrence_temp_seq { % at this stage, \l_recurrence_temp_seq has 6 items, % 0th: a[i]= expression | guard | guard option \seq_pop:NN \l_recurrence_temp_seq \l_recurrence_bin_tl \seq_pop:NN \l_recurrence_temp_seq \l_recurrence_name_tl \seq_pop:NN \l_recurrence_temp_seq \l_recurrence_index_tl \seq_pop:NN \l_recurrence_temp_seq \l_recurrence_rhs_tl \seq_pop:NN \l_recurrence_temp_seq \l_recurrence_guard_tl \recurrence_is_integer:VTF \l_recurrence_index_tl {\recurrence_define_constant:xx \l_recurrence_index_tl \l_recurrence_rhs_tl} {\recurrence_case_definition:NN \l_recurrence_name_tl \l_recurrence_index_tl} } { \recurrence_error } } \recurrence_error_definition: \recurrence_wrapper_definitions: \group_end: } \DeclareDocumentCommand\NewRecDef{ m }{ \recurrence_rec_def:n {#1} } \ExplSyntaxOff --oyUTqETQ0mS9luUI Content-Type: text/x-tex; charset=us-ascii Content-Disposition: attachment; filename="recurrence.tex" \documentclass[12pt]{article} \usepackage[paper=a4paper,landscape]{geometry} \usepackage{recurrence} \begin{document} \section{Start} %\tracingmacros=1 \NewRecDef{f[0]=1, f[1]=1, f[i]=f[i-1]+f[i-2]} \begin{tt} \begin{tabular}{ll} f & \meaning\f \\ f:n & \expandafter\meaning\csname f:n\endcsname \\ recurrence\_f\_0:n & \expandafter\meaning\csname recurrence_f_0:n\endcsname \\ recurrence\_f\_1:n & \expandafter\meaning\csname recurrence_f_1:n\endcsname \\ recurrence\_f\_2:n & \expandafter\meaning\csname recurrence_f_2:n\endcsname \\ recurrence\_f\_3:n & \expandafter\meaning\csname recurrence_f_3:n\endcsname \end{tabular} \end{tt} \ExplSyntaxOn \f{0}, \f{1}, % \f{2} % fails \cs_set_nopar:cpn {recurrence_f_2:n} #1 { \bool_if:nTF { \c_true_bool }{\f:n{#1-1}+\f:n{#1-2}}{\recurrence_f_3:n {#1}} } \f{2}, \f{3}, \f{4}, \f{5}, \f{6}, \f{7}, \f{8}, \f{9}, \f{10}, \f{11}, \f{12}, \f{13}, \f{14}, \f{15}, \f{16}, \f{17}, \f{18}, \f{19}, \f{20}, \f{21 - 1}, \end{document} --oyUTqETQ0mS9luUI--