On Tuesday 20 May 2008 16:44, RW wrote:
> On Tue, 20 May 2008 11:33:50 +0200
> Jonathan McKeown <[EMAIL PROTECTED]> wrote:
> > On Tuesday 20 May 2008 02:41, RW wrote:
> > > On Mon, 19 May 2008 21:46:03 +1200
> > >
> > > Jonathan Chen <[EMAIL PROTECTED]> 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 

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 

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.

freebsd-questions@freebsd.org mailing list
To unsubscribe, send any mail to "[EMAIL PROTECTED]"

Reply via email to