Arulx Z
Arulx Z

Reputation: 193

And operator Lisp

Why does and operator returns a value? What is the returned value dependent on?

When I try the following example -

(write (and a b c d)) ; prints the greatest integer among a b c d

where a, b, c and d are positive integers, then and returns the greatest of them.

However when one of a, b, c and d is 0 or negative, then the smallest integer is returned. Why is this the case?

Upvotes: 1

Views: 140

Answers (2)

Kaz
Kaz

Reputation: 58627

and can be regarded as a generalization of the two-place if. That is to say, (and a b) works exactly like (if a b). With and in the place of if we can add more conditions: (and a1 a2 a3 a4 ... aN b). If they all yield true, then b is returned. If we use if to express this, it is more verbose, because we still have to use and: (if (and a1 a2 a3 ... aN) b). and also generalizes in that it can be used with only one argument (if cannot), and even with no arguments at all (yields t in that case).

Mathematically, and forms a group. The identity element of that group is t, which is why (and) yields t. To describe the behavior of the N-argument and, we just need these rules:

(and) -> yield t

(and x y) -> { if x is true evaluate and yield y
             { otherwise yield nil

Now it turns out that this rule for a two-place and obeys the associative law: namely (and (and x y) z) behaves the same way as (and x (and y z)). The effect of the above rules is that no matter in which of these two ways we group the terms in this compound expression, x, y, and z are evaluated from left to right, and evaluation either stops at the first nil which it encounters and yields nil, or else it evaluates through to the end and yields the value of z.

Thus because we have this nice associative property, the rational thing to do in a nice language like Lisp which isn't tied to infix operators is to recognize that since the associative grouping doesn't matter, let's just have the flat syntax (and x1 x2 x3 ... xN), with any number of arguments including zero. This syntax denotes any one of the possible associations of N-1 binary ands which all yield the same behavior.

In other words, let's not make the poor programmer write a nested (and (and (and ...) ...) ...) to express a four-term and, and just let them write (and ...) with four arguments.

Summary:

  • the zero-place and yields t, which has to do with t being the identity element for the and operation.
  • the two-place and yields the second value if the first one is true. This is a useful equivalence to the two-place if. Binary and could be defined as yielding t when both arguments are true, but that would be less useful. In Lisp, any value that is not nil is a Boolean true. If we replace a non-nil value with t, it remains Boolean true, but we have lost potentially useful information.
  • the behavior of the n-place and is a consequence of the associative property; or rather preserving the equivalence between the flat N-argument form and all the possible binary groupings which are already equivalent to each other thanks to the associative property.
  • One consequence of all this is that we can have an extended if, like (if cond1 cond2 cond3 cond4 ... condN then-form), where then-form is evaluated and yielded if all the conditions are true. We just have to spell if using the and symbol.

Upvotes: 2

Óscar López
Óscar López

Reputation: 236124

As stated in the documentation:

The macro and evaluates each form one at a time from left to right. As soon as any form evaluates to nil, and returns nil without evaluating the remaining forms. If all forms but the last evaluate to true values, and returns the results produced by evaluating the last form. If no forms are supplied, (and) returns t.

So the returned value doesn't depend on which value is the "greatest" or "smallest" of the arguments.

Upvotes: 7

Related Questions