Date: Wed, 21 May 2008 09:50:06 +0200 From: Jonathan McKeown <jonathan@hst.org.za> To: freebsd-questions@freebsd.org Subject: Re: Now what would you expect this to print out? Message-ID: <200805210950.06869.jonathan@hst.org.za> In-Reply-To: <20080520154400.115e8817@gumby.homeunix.com.> References: <7d6fde3d0805190149y7a3bfa75j2ca6a67cef66e8f6@mail.gmail.com> <200805201133.50963.jonathan@hst.org.za> <20080520154400.115e8817@gumby.homeunix.com.>
next in thread | previous in thread | raw e-mail | index | archive | help
On Tuesday 20 May 2008 16:44, RW wrote: > On Tue, 20 May 2008 11:33:50 +0200 > > Jonathan McKeown <jonathan@hst.org.za> wrote: > > On Tuesday 20 May 2008 02:41, RW wrote: > > > On Mon, 19 May 2008 21:46:03 +1200 > > > > > > Jonathan Chen <jonc@chen.org.nz> 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
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200805210950.06869.jonathan>