From owner-freebsd-questions@FreeBSD.ORG Wed May 21 07:46:53 2008 Return-Path: Delivered-To: freebsd-questions@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id A93B0106566C for ; Wed, 21 May 2008 07:46:53 +0000 (UTC) (envelope-from jonathan@hst.org.za) Received: from hermes.hst.org.za (onix.hst.org.za [209.203.2.133]) by mx1.freebsd.org (Postfix) with ESMTP id B842B8FC25 for ; Wed, 21 May 2008 07:46:51 +0000 (UTC) (envelope-from jonathan@hst.org.za) Received: from sysadmin.hst.org.za (sysadmin.int.dbn.hst.org.za [10.1.1.20]) (authenticated bits=0) by hermes.hst.org.za (8.13.8/8.13.8) with ESMTP id m4L7kxxf025016 (version=TLSv1/SSLv3 cipher=RC4-MD5 bits=128 verify=NO) for ; Wed, 21 May 2008 09:46:59 +0200 (SAST) (envelope-from jonathan@hst.org.za) From: Jonathan McKeown Organization: Health Systems Trust To: freebsd-questions@freebsd.org Date: Wed, 21 May 2008 09:50:06 +0200 User-Agent: KMail/1.7.2 References: <7d6fde3d0805190149y7a3bfa75j2ca6a67cef66e8f6@mail.gmail.com> <200805201133.50963.jonathan@hst.org.za> <20080520154400.115e8817@gumby.homeunix.com.> In-Reply-To: <20080520154400.115e8817@gumby.homeunix.com.> MIME-Version: 1.0 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: 7bit Content-Disposition: inline Message-Id: <200805210950.06869.jonathan@hst.org.za> X-Spam-Score: -4.381 () ALL_TRUSTED,AWL,BAYES_00 X-Scanned-By: MIMEDefang 2.61 on 209.203.2.133 Subject: Re: Now what would you expect this to print out? X-BeenThere: freebsd-questions@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: User questions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 21 May 2008 07:46:53 -0000 On Tuesday 20 May 2008 16:44, RW wrote: > On Tue, 20 May 2008 11:33:50 +0200 > > Jonathan McKeown wrote: > > On Tuesday 20 May 2008 02:41, RW wrote: > > > On Mon, 19 May 2008 21:46:03 +1200 > > > > > > Jonathan Chen wrote: > > > > find /usr/src \( -name Makefile -or -name '*.mk' \) -print > > > > > > Why does that make a difference, when print always evaluates to > > > true? > > > > > > x AND true = x > > > > > > so > > > > > > (a OR b) AND true = a OR b > > > a OR (b AND true) = a OR b > > > > It makes a difference (as in programming) because -print is used for > > its side-effect rather than its value, and the binding order > > influences when the side-effect happens. > > That's still a bit counter-intuitive because in normal programming > languages the binding order modifies side-effects via the evaluation > order. And in both cases the evaluation order would be expected to be > left-to-right, with -print running last. Yes. I'm actually talking rubbish. find evaluates its argument expression left-to-right, and the ``precedence'' actually applies to term grouping rather than evaluation order. (This does affect the outcome, but not in the way I glibly said it did). What I should have said is that like a lot of programming languages, find is lazy when it comes to Boolean expressions: when it gets a TRUE in an -or or a FALSE in an -and, the value of the whole expression must be TRUE or FALSE respectively, regardless of what the remaining terms are, so why bother evaluating them? (It's usually referred to as short-circuiting). > I guess what you are saying is that the side-effect of print is based-on > a Boolean "running-value". And without the brackets, the first test has > been evaluated, but not yet ORed into that "running-value", by the time > that print runs. That's not quite how it works. Rewriting find /usr/src -name Makefile -or -name '*.mk' -print using extra parens to emphasise the implicit grouping, and including the implicit -and, gives: find /usr/src -name Makefile -or \( -name '*.mk' -and -print \) in other words, an -or with two terms, one of which happens to be an expression. If -name Makefile is true, the -or is satisfied, so nothing else is evaluated, and find goes on to the next filename. Otherwise, the expression in the second term has to be evaluated. If -name '*.mk' is false, the -and is satisfied (which also satisfies the -or) and find moves to the next filename. If it's true, the -and can't be satisfied without evaluating the -print. The end result is that only files matching '*.mk' are printed. Rewriting the other case, find /usr/src \( -name Makefile -or -name '*.mk' \) -and -print If the first expression is false, the -and is satisfied and the -print is not evaluated. If the first expression is true (meaning either of the -name arguments is true), then the -and can't be satisfied without evaluating the -print. The last case is find /usr/src -name Makefile -or -name '*.mk' find quickly analyses this, finds no output action, and converts it to the second form above, internally placing parens around the whole expression and an -and -print after it. Jonathan