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 o8MNFfj8007426 for ; Thu, 23 Sep 2010 01:15:42 +0200 Received: (qmail 23736 invoked by alias); 22 Sep 2010 23:15:35 -0000 Delivered-To: GMX delivery to rainer.schoepf@gmx.net Received: (qmail invoked by alias); 22 Sep 2010 23:15:35 -0000 Received: from relay2.uni-heidelberg.de (EHLO relay2.uni-heidelberg.de) [129.206.210.211] by mx0.gmx.net (mx112) with SMTP; 23 Sep 2010 01:15:35 +0200 Received: from listserv.uni-heidelberg.de (listserv.uni-heidelberg.de [129.206.100.94]) by relay2.uni-heidelberg.de (8.13.8/8.13.8) with ESMTP id o8MNATPi009654 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Thu, 23 Sep 2010 01:10:30 +0200 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 o8MM168J026230; Thu, 23 Sep 2010 01:08:42 +0200 Received: by LISTSERV.UNI-HEIDELBERG.DE (LISTSERV-TCP/IP release 16.0) with spool id 434513 for LATEX-L@LISTSERV.UNI-HEIDELBERG.DE; Thu, 23 Sep 2010 01:08:42 +0200 Received: from relay2.uni-heidelberg.de (relay2.uni-heidelberg.de [129.206.210.211]) by listserv.uni-heidelberg.de (8.13.1/8.13.1) with ESMTP id o8MN8gWH031618 for ; Thu, 23 Sep 2010 01:08:42 +0200 Received: from mail-iw0-f177.google.com (mail-iw0-f177.google.com [209.85.214.177]) by relay2.uni-heidelberg.de (8.13.8/8.13.8) with ESMTP id o8MNAIQS009588 for ; Thu, 23 Sep 2010 01:10:22 +0200 Received: by iwn36 with SMTP id 36so1304630iwn.22 for ; Wed, 22 Sep 2010 16:08:37 -0700 (PDT) MIME-Version: 1.0 Received: by 10.231.59.212 with SMTP id m20mr845338ibh.130.1285196917503; Wed, 22 Sep 2010 16:08:37 -0700 (PDT) Received: by 10.231.143.204 with HTTP; Wed, 22 Sep 2010 16:08:37 -0700 (PDT) References: <4C967C9B.5010706@gmx.de> <71ED7A5B-DE11-45D9-9785-95A1DC795080@gmail.com> <4C9724B4.3010301@residenset.net> <19607.26705.947540.499705@morse.mittelbach-online.de> <4C9840AB.4050805@gmx.de> <732A7500-5414-4818-87E3-33CB14463288@gmail.com> <4C98435A.1050507@gmx.de> <4C989ACB.5060000@morningstar2.co.uk> Content-Type: text/plain; charset=ISO-8859-1 X-Spam-Whitelist: Content-Transfer-Encoding: 8bit X-MIME-Autoconverted: from quoted-printable to 8bit by listserv.uni-heidelberg.de id o8MN8gWH031619 Message-ID: Date: Thu, 23 Sep 2010 01:08:37 +0200 Reply-To: Mailing list for the LaTeX3 project Sender: Mailing list for the LaTeX3 project From: =?ISO-8859-1?Q?Morten_H=F8gholm?= Subject: Re: boolean expressions in ExplSyntaxNames To: LATEX-L@listserv.uni-heidelberg.de In-Reply-To: <4C989ACB.5060000@morningstar2.co.uk> Precedence: list List-Help: , List-Unsubscribe: List-Subscribe: List-Owner: List-Archive: X-GMX-Antispam: 0 (Mail was not recognized as spam); Detail=5D7Q89H36p6i75npGen84eVAEFK/syJmFuaL1OLtauwJ5R/kaZ9HAe8peGX1DeqJL7BW4 1X28hmBsSaikXt0ebYfUaHmtXkk7HChP+4IT8t5foOuRzC8vyH8YP07l+7OgkY63m+qRZCiPVOZg mL0OA==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: 6440 On Tue, Sep 21, 2010 at 1:45 PM, Joseph Wright wrote: Late in the game... > On 21/09/2010 06:32, Arno Trautmann wrote: >>> >>> Why not just use&&  in the first place? >> >> Because of possible catcode-troubles? ;) >> Or maybe such a list might be more useful for a xor operation. > > How does the following look? The Boolean expressions are the most basic > versions (NOT takes one argument, others take two), but nesting seems to > work fine. There is definitely less code to this than the current > implementation, so there would be a performance gain. I know one could do this the way you have outlined. There are, however, a few gotcha (as always in TeX), which is why there have been different implementations. If you look back in time in the svn, you will also find that there was actually both "ands" and "ors" functions at one point. One typical gotcha when inside the \if machinery is ensuring we do not by accident put in things that will confuse the scanner. Thus modifying the example to say \fi: instead of \ERROR will now make it fail. This can of course be easily alleviated by carefully issuing \use_i:nn etc. in appropriate places so that the dangerous parts are not skipped by TeX's primitive scanner. If we are talking about user interface then I'd like to say that I am no big fan of having a plethora of \bool_and_p:nn, \bool_and_p:nnn, etc. Just too many functions for my taste. Instead, I'd like something simple such as \bool_and_p:n{ expr 1, expr 2, ..., expr n} \bool_or_p:n{ expr 1, expr 2, ..., expr n} This can be done in a simple and efficient way that does not involve primitive TeX conditionals. All it does is assume other _p functions return \c_true_bool or \c_false_bool *after* finishing any TeX conditional (as documented for a long time now). Idea is to evaluate the first predicate in the list into a 0 or 1 and then use a case switch depending on the result. \tl_new:Nn \c_bool_stop_tl{2~}% magic stop marker. \cs_set:Nn \bool_and_p:n { \exp_after:wN \bool_and_p_aux:Nn \tex_number:D #1 ,\c_bool_stop_tl, } \cs_set:Nn \bool_and_p_aux:Nn { \tex_ifcase:D #1~% number already expanded so a space to terminate % case 0: a false, so we return false. \exp_after:wN \bool_end_list_false:w \or: % case 1: true, try next one. \exp_after:wN \bool_and_p_aux:Nn \tex_number:D % yes, this works! % because \tex_number:D resolves the ending \fi: for us. \or: % case 2: made it to the end, hence true \exp_after:wN \c_true_bool \fi: } \cs_set:Nn \bool_or_p:n { \exp_after:wN \bool_or_p_aux:Nn \tex_number:D #1 ,\c_bool_stop_tl, } \cs_set:Nn \bool_or_p_aux:Nn { \tex_ifcase:D #1~% false, try next \exp_after:wN \bool_or_p_aux:Nn \tex_number:D \or: % true, skip to end \exp_after:wN \bool_end_list_true:w \or: % no true found, hence false \exp_after:wN \c_false_bool \fi: } % skipping the remainder when result is known. \cs_set:Npn \bool_end_list_false:w #1\c_bool_stop_tl#2{\c_false_bool} \cs_set:Npn \bool_end_list_true:w #1\c_bool_stop_tl #2{\c_true_bool} Again, minimal evaluation is done. Also, one can in reality use arbitrary single token delimiters, so \bool_or_p:n{\c_false_bool,\c_true_bool, \c_true_bool} and \bool_or_p:n{\c_false_bool ; \c_true_bool ; \c_true_bool} would both be legal. And we can of course easily define \bool_and_p:nnnn to be just \bool_and_p:n {#1,#2,#3,#4} if one wants to. A few comments below. > \documentclass{article} > \usepackage{expl3} > \ExplSyntaxOn > \cs_set_nopar:Npn \bool_if:nT #1 { >  \tex_ifodd:D \bool_if_p:n {#1} >    \tex_expandafter:D \use:n >  \tex_else:D >    \tex_expandafter:D \use_none:n >  \tex_fi:D > } > \cs_set_nopar:Npn \bool_if:nF #1 { >  \tex_ifodd:D \bool_if_p:n {#1} >    \tex_expandafter:D \use_none:n >  \tex_else:D >    \tex_expandafter:D \use:n >  \tex_fi:D > } > \cs_set_nopar:Npn \bool_if:nTF #1 { >  \tex_ifodd:D \bool_if_p:n {#1} >    \tex_expandafter:D \use_i:nn >  \tex_else:D >    \tex_expandafter:D \use_ii:nn >  \tex_fi:D > } > \cs_set_nopar:Npn \bool_if_p:n #1 { >  \tex_number:D #1 ~ > } I do not quite understand why this is done. Also, it does not return the correct token but a digit instead so not a proper predicate function. > \cs_set_nopar:Npn \bool_not_p:n #1 { >  \tex_ifnum:D \tex_number:D #1 = \c_true_bool No need for any equality test or \tex_number:D . Just use \if_predicate:w #1 \exp_after:wN \c_false_bool \tex_else:D \exp_after:wN \c_true_bool \tex_fi:D Generally just use \if_predicate:w instead of the \tex_ifnum:D. Less input and clearer what is going on. >    \c_false_bool >  \tex_else:D >    \c_true_bool >  \tex_fi:D > } > \cs_set_nopar:Npn \bool_and_p:nn #1#2 { >  \tex_ifnum:D \tex_number:D #1 = \c_true_bool >    \tex_ifnum:D \tex_number:D #2 = \c_true_bool >      \c_true_bool >    \tex_else:D >      \c_false_bool >    \tex_fi:D >  \tex_else:D >    \c_false_bool >  \tex_fi:D > } > \cs_set_nopar:Npn \bool_or_p:nn #1#2 { >  \tex_ifnum:D \tex_number:D #1 = \c_true_bool >    \c_true_bool >  \tex_else:D >    \tex_ifnum:D \tex_number:D #2 = \c_true_bool >      \c_true_bool >    \tex_else:D >      \c_false_bool >    \tex_fi:D >  \tex_fi:D > } > \cs_set_nopar:Npn \bool_xor_p:nn #1#2 { >  \tex_ifnum:D \tex_number:D #1 = \c_true_bool >    \tex_ifnum:D \tex_number:D #2 = \c_true_bool Just test for equality: If equal then false, otherwise true. This way you also avoid expanding the second test twice. >      \c_false_bool >    \tex_else:D >      \c_true_bool >    \tex_fi:D >  \tex_else:D >    \tex_ifnum:D \tex_number:D #2 = \c_true_bool >      \c_false_bool >    \tex_else:D >      \c_true_bool >    \tex_fi:D >  \tex_fi:D > } -- Morten