和运算符 Lisp
And operator Lisp
为什么 and
运算符 returns 是一个值?返回值依赖于什么?
当我尝试下面的例子时 -
(write (and a b c d)) ; prints the greatest integer among a b c d
其中 a
、b
、c
和 d
是正整数,然后 and
returns 其中最大的。
然而,当a
、b
、c
和d
其中之一为0或负数时,则返回最小的整数。为什么会这样?
如 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
.
因此返回值不取决于参数的 "greatest" 或 "smallest" 值。
and
可以看作是二位if
的推广。也就是说,(and a b)
和 (if a b)
完全一样。用 and
代替 if
我们可以添加更多条件:(and a1 a2 a3 a4 ... aN b)
。如果它们都为真,则返回 b
。如果我们用if
来表达这个,就比较冗长了,因为我们还是要用and
:(if (and a1 a2 a3 ... aN) b)
。 and
也概括为它只能与一个参数一起使用(if
不能),甚至根本没有参数(在这种情况下产生 t
)。
在数学上,and
形成一个群。该组的标识元素是 t
,这就是 (and)
产生 t
的原因。要描述 N 参数 and
的行为,我们只需要这些规则:
(and) -> yield t
(and x y) -> { if x is true evaluate and yield y
{ otherwise yield nil
现在事实证明,这个二位 and
的规则服从 结合律 :即 (and (and x y) z)
的行为方式与 (and x (and y z))
。上述规则的效果是,无论我们以这两种方式中的哪一种方式对这个复合表达式中的项进行分组,x
、y
和 z
都是从左到右计算的,求值要么在它遇到的第一个 nil
处停止并产生 nil
,要么一直求值到最后并产生 z
.
的值
因此,因为我们有这个很好的关联 属性,在像 Lisp 这样不受中缀运算符约束的好语言中做的合理的事情是认识到,因为关联分组并不重要,让我们只使用平面语法 (and x1 x2 x3 ... xN)
,其中包含任意数量的参数,包括零。此语法表示 N-1
二进制 and
的任何一种可能关联,它们都产生相同的行为。
换句话说,我们不要让可怜的程序员写一个嵌套的 (and (and (and ...) ...) ...)
来表达一个四项 and
,而是让他们用四个参数写 (and ...)
。
总结:
- 零位
and
产生 t
,这与 t
作为 and
操作的标识元素有关。
- 如果第一个为真,则两位
and
产生第二个值。 这是对两位 if 的有用等价。当两个参数都为真时,二进制 and
可以定义为产生 t
,但这不太有用。在 Lisp 中,任何不是 nil
的值都是布尔值 true。如果我们用 t
替换非 nil
值,它仍然是布尔值 true,但我们已经丢失了潜在有用的信息。
- n 位的行为
and
是联想 属性 的结果;或者更确切地说,保留平面 N 参数形式与所有可能的二进制分组之间的等价性,由于结合 属性. ,它们已经彼此等价
- 所有这一切的一个结果是我们可以有一个扩展的
if
,如 (if cond1 cond2 cond3 cond4 ... condN then-form)
,其中 then-form
被评估并在所有条件都为真时产生。我们只需使用 and
符号拼写 if
。
为什么 and
运算符 returns 是一个值?返回值依赖于什么?
当我尝试下面的例子时 -
(write (and a b c d)) ; prints the greatest integer among a b c d
其中 a
、b
、c
和 d
是正整数,然后 and
returns 其中最大的。
然而,当a
、b
、c
和d
其中之一为0或负数时,则返回最小的整数。为什么会这样?
如 documentation 中所述:
The macro
and
evaluates each form one at a time from left to right. As soon as any form evaluates tonil
,and
returnsnil
without evaluating the remaining forms. If all forms but the last evaluate totrue
values, and returns the results produced by evaluating the last form. If no forms are supplied,(and)
returnst
.
因此返回值不取决于参数的 "greatest" 或 "smallest" 值。
and
可以看作是二位if
的推广。也就是说,(and a b)
和 (if a b)
完全一样。用 and
代替 if
我们可以添加更多条件:(and a1 a2 a3 a4 ... aN b)
。如果它们都为真,则返回 b
。如果我们用if
来表达这个,就比较冗长了,因为我们还是要用and
:(if (and a1 a2 a3 ... aN) b)
。 and
也概括为它只能与一个参数一起使用(if
不能),甚至根本没有参数(在这种情况下产生 t
)。
在数学上,and
形成一个群。该组的标识元素是 t
,这就是 (and)
产生 t
的原因。要描述 N 参数 and
的行为,我们只需要这些规则:
(and) -> yield t
(and x y) -> { if x is true evaluate and yield y
{ otherwise yield nil
现在事实证明,这个二位 and
的规则服从 结合律 :即 (and (and x y) z)
的行为方式与 (and x (and y z))
。上述规则的效果是,无论我们以这两种方式中的哪一种方式对这个复合表达式中的项进行分组,x
、y
和 z
都是从左到右计算的,求值要么在它遇到的第一个 nil
处停止并产生 nil
,要么一直求值到最后并产生 z
.
因此,因为我们有这个很好的关联 属性,在像 Lisp 这样不受中缀运算符约束的好语言中做的合理的事情是认识到,因为关联分组并不重要,让我们只使用平面语法 (and x1 x2 x3 ... xN)
,其中包含任意数量的参数,包括零。此语法表示 N-1
二进制 and
的任何一种可能关联,它们都产生相同的行为。
换句话说,我们不要让可怜的程序员写一个嵌套的 (and (and (and ...) ...) ...)
来表达一个四项 and
,而是让他们用四个参数写 (and ...)
。
总结:
- 零位
and
产生t
,这与t
作为and
操作的标识元素有关。 - 如果第一个为真,则两位
and
产生第二个值。 这是对两位 if 的有用等价。当两个参数都为真时,二进制and
可以定义为产生t
,但这不太有用。在 Lisp 中,任何不是nil
的值都是布尔值 true。如果我们用t
替换非nil
值,它仍然是布尔值 true,但我们已经丢失了潜在有用的信息。 - n 位的行为
and
是联想 属性 的结果;或者更确切地说,保留平面 N 参数形式与所有可能的二进制分组之间的等价性,由于结合 属性. ,它们已经彼此等价
- 所有这一切的一个结果是我们可以有一个扩展的
if
,如(if cond1 cond2 cond3 cond4 ... condN then-form)
,其中then-form
被评估并在所有条件都为真时产生。我们只需使用and
符号拼写if
。