Received: from mout.gmx.net (mout.gmx.net [212.227.15.15]) by h1439878.stratoserver.net (8.14.4/8.14.4/Debian-2ubuntu2.1) with ESMTP id t772hWYF010147 for ; Fri, 7 Aug 2015 04:43:33 +0200 Received: from relay.uni-heidelberg.de ([129.206.100.212]) by mx-ha.gmx.net (mxgmx006) with ESMTPS (Nemesis) id 0LvQUl-1Ygbgy0u03-010g0C for ; Fri, 07 Aug 2015 04:43:27 +0200 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 t772fIkM029930 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Fri, 7 Aug 2015 04:41:18 +0200 Received: from listserv.uni-heidelberg.de (listserv.uni-heidelberg.de [127.0.0.1]) by listserv.uni-heidelberg.de (8.13.8/8.13.8) with ESMTP id t76M13LN025837; Fri, 7 Aug 2015 04:41:17 +0200 Received: by LISTSERV.UNI-HEIDELBERG.DE (LISTSERV-TCP/IP release 16.0) with spool id 12511326 for LATEX-L@LISTSERV.UNI-HEIDELBERG.DE; Fri, 7 Aug 2015 04:41:17 +0200 Received: from relay.uni-heidelberg.de (relay.uni-heidelberg.de [129.206.100.212]) by listserv.uni-heidelberg.de (8.13.8/8.13.8) with ESMTP id t772fHpm011471 for ; Fri, 7 Aug 2015 04:41:17 +0200 Received: from mail-yk0-f173.google.com (mail-yk0-f173.google.com [209.85.160.173]) by relay.uni-heidelberg.de (8.14.1/8.14.1) with ESMTP id t772fBQb029878 (version=TLSv1/SSLv3 cipher=RC4-SHA bits=128 verify=FAIL) for ; Fri, 7 Aug 2015 04:41:14 +0200 Received: by ykcq64 with SMTP id q64so73868079ykc.2 for ; Thu, 06 Aug 2015 19:41:11 -0700 (PDT) X-Received: by 10.129.132.8 with SMTP id u8mr5296201ywf.175.1438915271162; Thu, 06 Aug 2015 19:41:11 -0700 (PDT) MIME-Version: 1.0 References: <55A8C0C2.3040908@morningstar2.co.uk> <20150717095912.GA6487@hzdr.de> <55A8E267.1030901@morningstar2.co.uk> <20150717140025.GA10619@hzdr.de> <55A90BC0.6020102@morningstar2.co.uk> Content-Type: multipart/alternative; boundary=94eb2c07a850998443051caf91d1 Message-ID: Date: Fri, 7 Aug 2015 02:41:01 +0000 Reply-To: Mailing list for the LaTeX3 project Sender: Mailing list for the LaTeX3 project From: Sean Allred Subject: Re: expl3 boolean expressions: lazy evaluation To: LATEX-L@LISTSERV.UNI-HEIDELBERG.DE In-Reply-To: Precedence: list List-Help: , List-Unsubscribe: List-Subscribe: List-Owner: List-Archive: Envelope-To: X-GMX-Antispam: 0 (Mail was not recognized as spam); Detail=V3; X-GMX-Antivirus: 0 (no virus found) X-UI-Filterresults: notjunk:1;V01:K0:fYFTl7ahux4=:IWg8bXHhlz3LQKUgvRnWw+0Q1b rF88x8mU5qj3aeG1p+X9iF2xsjkIqlv1syz++gRhx9Xki3kIn4rKE3bBVA4Ohehlbdb8fiJTq GEB8DTyz+Drdrh9c75QO8OPItgstaErnGWeEa3JiNA2AmQEjypz8kK5mKo9HOpv07LoWsKNeo 4pRKdCmQU/4rStt9u6tHjx1NT3Fr0Z2UeZD7RhtYYpYH4aIOl6RtEJdjcWX7Iudc/vJIgQ4wU U0PMu2ylfzKGvnsPhjwiSyH7EdRsnhMLi33LGabrS17Td3SxhO3CuR8Y+v15yUzp2IOWOIH+v cFmuHq1H4NqN8wbwo2JSG9tGGAEjsHqxj0og8YDQwU8aY0+U9/5RsG/Fi1jY+oyi8VluYyqUf 9gHGgwy/KoPKoybUvQsFaXvc7BBTeunT27cA7gAWGXTdGrE2Zu7JOIINc1eagePWKcP7JOr5u de946KvL7vzBPl738vIh4utawXzEzHu4sLqi2i7aamGa6mo9Ng5tWLLjMu+UCvmZ0WBHwtQ/M aPIA7o+m3loz2odsVN8npVkBv2sBAgq+2DipIMc3E8M4BFlc7ETtLRDmg2IUvJt6OV9mgPbY7 MarYc4UCjaYgtsvhKyY+RGdfAsnIAgdZxVdwkN9Wh66RVFJ8O1KIgekVIkOcbjcvswmtlW+QZ 8hbz+ZxE19MxFGaA3ij72Lo/ZkoKszmdKLOrefo285yXC/Ij2amT5twGfRQRQCa4Vk7mP6q2K pMfJqCC+7KZlNncy9AJ4yuFWh56V6vxxM8MIgLwl1xa8+BQPrpEfGOAYb98GfWOPU4jm0Uiue 5cq1e0PGPPlqSr86wsnJAxuqEtBd4fkeGyQUF2oOmrCUxqqTNva5cfoapA8kYC1pObZ6cWTy2 qvaUBSS1vVgjZdWQB+snqpnvzXxfb36InFZBXqB1P8IYT33dgrSwbysLP0AnKl5qTPAAKZQso gw9e2QOVO6hlqE2uSq+J6Dli/ZjXnQHiy6KW/icwHTHJstR9UZWBmb9JpVF53a91ylHxY23bY waoSGKDDjJb0RY50gXz1BtUMdeg/CqsYVn29dC5BdixGvmGasve/oNhz+Z3M3IWf0q6bcCQ2g kZzPwMU7+i9k9Soa0WrlK+x0AjckVP3Baqj0ppiCAnatcFmHfRdMWF7Cmj15Wp/4G2EOtNbCY Yc0ORCpYd9UxyL/hrpJH79ejGItROaLKvz2udl1DZV+9zAIpZgoNlPugBD1pI3ZFQPShdIpjD jPv2zibp536aMHNzTHbCF42giknsqLsyJOPO5w9RfaXoFzQEN1n7qlIQvknDxD8rcsmp9fJXD DrAEnuS5YjmqkGnSuqJl1HH107W9GqrNB9wDvu8HqBrdZeFIWBooTujUbebZpaU5Q/JWMVVHr BF5/bg74nVvyankjoIWuEl6peKkwDLLFTcdiDzZsrEU2KkuViS0VX00gE9HmKRaWEgEBvO7KU qbRByV25qO2lwmiGxwqH/HslF+7oU= X-UI-Loop:V01:2RMIvOn2Lrw=:X2jUoXCPyzQ1l4gc0617MxnxljB0ODLuFMk9aumgg7Y= X-UI-Out-Filterresults: notjunk:1;V01:K0:kzyu1URm23s=:G97NQOA1VuRsKIxheRL0na d5DJV9YKRqgHIiyR5eYB60Q2t8Nu5WxCNEGiJ1wDfq20S/rre75M7KbjB70DA8u2FEiiJ4vd+ 6LgH1hlqo7fF0Wnl/2RYziJ02lVzgjJUc8my0LH0j0oDl8bo4A6SQZIyKN/fj9HnhDCBEKzPt Q0hLvOxdGey8ZixJeA3dAxmn6yyfDZ939uPHjTjWvwMKaka/ZnnmsOdXqE80/MQAOywHFvMR8 CI5/udNx8GjTLp2CfgY/NEEMIEtZqRB9ezYGJvO+HoZ1yOCFPHE0g4ATt1BnRDgQHZnfls3tj f+A4xeOP9Li+jb5QO3qellopguxyFK+b6iSvwYInTKRtrnP3r9HG9lY2xk7WfnFgshr6Xsv5i 8a6TRIWwH/ccrv8Y8GwWZQ1K/KOaekMJeaq5MVQm79LeaZ6oYugMGAkjTa+nEYsnyZJnFh/Rn mu9lK+wprHQjT0uN73VUFzJHNz2g00f3DLglMG+LHWOPAXgc/Bhg X-Scanned-By: MIMEDefang 2.71 on 85.214.41.38 Status: R X-Status: X-Keywords: X-UID: 7815 --94eb2c07a850998443051caf91d1 Content-Type: text/plain; charset=UTF-8 Hi Bruno :) Disclaimer: I've completely reversed my stance on this. See below. > Can you clarify what your suggested \bool_validate:n is meant to do? > Your description is too short for me to have any idea what it is. \bool_validate:n is just a thought to allow the programmer to introduce the functionality rather than impose it on him/her. When parsing the overall expression in, say, \bool_if:nF { \pbj_is_peanut_butter_jelly_time_p: % (A) && \pbj_can_dance_p: % (B) && ! ( \pbj_has_suit_p:N \g_tmp_person || % (C) \bool_validate:n % or maybe \bool_eval_all:n { \token_if_eq_meaning_p:NN #1 ? || % (D) \token_if_eq_meaning_p:NN #1 ! % (E) } ) } { dance ~ like ~ there's ~ no ~ tomorrow } A and B will short-circuit as they do today. If A is false, B through E will not be evaluated. If A is true and B is false, ... etc. If ( A && B && !C), we'll get to \bool_validate:n. This will evaluate everything in its argument *without* short-circuiting. I explained that for the sake of clarity, because... > The cheapest change in terms of amount of code and of > maintainability is to drop lazy evaluation of boolean expressions. > This will require changing in minor ways a few packages where lazy > evaluation of boolean expressions is assumed. ...this is probably the wiser option, on second thought. Lazy evaluation could probably be easily implemented on top of a non-lazy version. (This would just be an implementation of shunting-yard.) > Actually, there is currently a mess of code that is only there to > support lazy evaluation. If we get rid of lazy evaluation, I strongly > expect the code underlying boolean expressions to become simpler. I believe it must by the very nature of the problem. Lazy evaluation takes a bit of knowledge about the operators in itself (in addition to the knowledge needed to actually evaluate the expression). > In fact, I believe it would be possible to provide a form of lazy > evaluation when explicitly requested by the programmer. ... I promise, I just read this :) Yes, I agree this would be a good idea. We'd get some modularization for free, as well. ---- As long as the ability to short-circuit expressions remains, that's probably 'good enough'. (There's a good argument to say 'the simpler, the better', so removing lazy evaluation from the 'default' behavior may the the Right thing to do, anyways.) Thanks for making me think about this again, and sorry it took me so long to respond! Your email was buried in short order :( All the best, -Sean On Thu, Jul 23, 2015 at 8:34 PM Bruno Le Floch wrote: > Hi Sean, > > > I don't believe it's out of the question to wrap macro-parameters in some > > sort of \bool_validate:n (if such a thing doesn't already exist) that > would > > run the checks and issue appropriate errors on a case-by-case basis. I > > believe it's important to assume the programmer knows what he or she is > > doing and let them account for this themselves. Otherwise, you introduce > > complexity where none is needed for a large portion of folks. > > Can you clarify what your suggested \bool_validate:n is meant to do? > Your description is too short for me to have any idea what it is. > > If we leave things as they are, I am pretty certain that programmers > will fall into the pitfall of thinking that > > \bool_if:nTF > { > \token_if_eq_meaning_p:NN #1 ? || > \token_if_eq_meaning_p:NN #1 ! > } > > is safe, even though it will break horribly if `#1` is `(` or `)` > (technically I haven't tested so perhaps this works by chance). > > The reason I am certain of this is that I fell into this trap (before > I stopped using boolean expressions), even though I was aware of it. > This is why we need to change something. The cheapest change in terms > of amount of code and of maintainability is to drop lazy evaluation of > boolean expressions. This will require changing in minor ways a few > packages where lazy evaluation of boolean expressions is assumed. > > > Not to mention that it is just that much more to test and maintain. > > Actually, there is currently a mess of code that is only there to > support lazy evaluation. If we get rid of lazy evaluation, I strongly > expect the code underlying boolean expressions to become simpler. > > In fact, I believe it would be possible to provide a form of lazy > evaluation when explicitly requested by the programmer. Something > like > > \bool_if:nTF > { > \tl_if_exist_p:N #1 && > \bool_lazy:n { \tl_if_empty_p:N #1 } > } > > would do some trickery under the hood to prevent expansion of > `\tl_if_empty_p:N #1` if `\tl_if_exist_p:N #1` gives the result > `false`. > > > Regards, > > Bruno > --94eb2c07a850998443051caf91d1 Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable
Hi Bruno :)

Disclaimer: I= 9;ve completely reversed my stance on this. See below.

=
> Can you clarify what your suggested \bool_validate:n is meant to = do?
> Your description is too short for me to have any idea wh= at it is.

\bool_validate:n is just a thought to al= low the programmer to
introduce the functionality rather than imp= ose it on him/her.=C2=A0 When
parsing the overall expression in, = say,

=C2=A0 =C2=A0 \bool_if:nF
=C2=A0 = =C2=A0 =C2=A0 {
=C2=A0 =C2=A0 =C2=A0 =C2=A0 \pbj_is_peanut_butter= _jelly_time_p: =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 % (A)
=
=C2=A0 =C2=A0 =C2=A0 =C2=A0 &&
=C2=A0 =C2=A0 =C2=A0 = =C2=A0 \pbj_can_dance_p: =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 % (B)
<= div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 &&
=C2=A0 =C2=A0 =C2=A0 = =C2=A0 ! (
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 \pbj_has_sui= t_p:N \g_tmp_person || =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0% (C)
=
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 \bool_validate:n % or maybe = \bool_eval_all:n
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= {
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 \token= _if_eq_meaning_p:NN #1 ? || =C2=A0 =C2=A0 =C2=A0 =C2=A0 % (D)
=C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 \token_if_eq_meaning_p= :NN #1 ! =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0% (E)
=C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 }
=C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 )
=C2=A0 =C2=A0 =C2=A0 } { dance ~ like ~ there'= ;s ~ no ~ tomorrow }

A and B will short-circuit as= they do today.=C2=A0 If A is false, B through
E will not be eval= uated.=C2=A0 If A is true and B is false, ... etc.

If ( A && B && !C), we'll get to \bool_validate:n.=C2= =A0 This will evaluate
everything in its argument *without* short= -circuiting.

I explained that for the sake of clar= ity, because...

> The cheapest change in terms = of amount of code and of
> maintainability is to drop lazy eva= luation of boolean expressions.
> This will require changing i= n minor ways a few packages where lazy
> evaluation of boolean= expressions is assumed.

...this is probably the w= iser option, on second thought.=C2=A0 Lazy
evaluation could proba= bly be easily implemented on top of a non-lazy
version. =C2=A0(Th= is would just be an implementation of shunting-yard.)

<= div>> Actually, there is currently a mess of code that is only there to<= /div>
> support lazy evaluation.=C2=A0 If we get rid of lazy evaluat= ion, I strongly
> expect the code underlying boolean expressio= ns to become simpler.

I believe it must by the ver= y nature of the problem.=C2=A0 Lazy evaluation
takes a bit of kno= wledge about the operators in itself (in addition to
the knowledg= e needed to actually evaluate the expression).

>= ; In fact, I believe it would be possible to provide a form of lazy
> evaluation when explicitly requested by the programmer.
<= br>
... I promise, I just read this :) Yes, I agree this would be= a good
idea.=C2=A0 We'd get some modularization for free, as= well.

----

As long as th= e ability to short-circuit expressions remains, that's
probab= ly 'good enough'. =C2=A0(There's a good argument to say 'th= e simpler,
the better', so removing lazy evaluation from the = 'default' behavior
may the the Right thing to do, anyways= .)

Thanks for making me think about this again, an= d sorry it took me so
long to respond!=C2=A0 Your email was burie= d in short order :(

All the best,
-Sean<= /div>


O= n Thu, Jul 23, 2015 at 8:34 PM Bruno Le Floch <blflatex@gmail.com> wrote:
Hi Sean,

> I don't believe it's out of the question to wrap macro-paramet= ers in some
> sort of \bool_validate:n (if such a thing doesn't already exist) t= hat would
> run the checks and issue appropriate errors on a case-by-case basis. I=
> believe it's important to assume the programmer knows what he or s= he is
> doing and let them account for this themselves. Otherwise, you introdu= ce
> complexity where none is needed for a large portion of folks.

Can you clarify what your suggested \bool_validate:n is meant to do?
Your description is too short for me to have any idea what it is.

If we leave things as they are, I am pretty certain that programmers
will fall into the pitfall of thinking that

=C2=A0 =C2=A0 \bool_if:nTF
=C2=A0 =C2=A0 =C2=A0 {
=C2=A0 =C2=A0 =C2=A0 =C2=A0 \token_if_eq_meaning_p:NN #1 ? ||
=C2=A0 =C2=A0 =C2=A0 =C2=A0 \token_if_eq_meaning_p:NN #1 !
=C2=A0 =C2=A0 =C2=A0 }

is safe, even though it will break horribly if `#1` is `(` or `)`
(technically I haven't tested so perhaps this works by chance).

The reason I am certain of this is that I fell into this trap (before
I stopped using boolean expressions), even though I was aware of it.
This is why we need to change something.=C2=A0 The cheapest change in terms=
of amount of code and of maintainability is to drop lazy evaluation of
boolean expressions.=C2=A0 This will require changing in minor ways a few packages where lazy evaluation of boolean expressions is assumed.

> Not to mention that it is just that much more to test and maintain.
Actually, there is currently a mess of code that is only there to
support lazy evaluation.=C2=A0 If we get rid of lazy evaluation, I strongly=
expect the code underlying boolean expressions to become simpler.

In fact, I believe it would be possible to provide a form of lazy
evaluation when explicitly requested by the programmer.=C2=A0 Something
like

=C2=A0 =C2=A0 \bool_if:nTF
=C2=A0 =C2=A0 =C2=A0 {
=C2=A0 =C2=A0 =C2=A0 =C2=A0 \tl_if_exist_p:N #1 &&
=C2=A0 =C2=A0 =C2=A0 =C2=A0 \bool_lazy:n { \tl_if_empty_p:N #1 }
=C2=A0 =C2=A0 =C2=A0 }

would do some trickery under the hood to prevent expansion of
`\tl_if_empty_p:N #1` if `\tl_if_exist_p:N #1` gives the result
`false`.


Regards,

Bruno
--94eb2c07a850998443051caf91d1--