为什么 (apply 或 [true false]) 在 Clojure 中不起作用?

发布于 2024-09-04 07:06:32 字数 161 浏览 6 评论 0原文

根据我对 apply 的理解,它解包一个列表并将元素转换为函数的参数。

我看到 (apply + [1 2 3]) 按预期工作,即:它相当于 (+ 1 2 3)。

那么为什么 (apply or [true false]) 无效呢?它不等于 (或 true false) 吗?

From what I understand about apply, it unpacks a list and turns the elements into arguments for a function.

I see that (apply + [1 2 3]) works as expected, i.e: it's equivalent to (+ 1 2 3).

Why then is (apply or [true false]) invalid? Isn't it equivalent to (or true false) ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

清醇 2024-09-11 07:06:33

or 是一个宏,不能将其用作值。

创建一个匿名函数,通过 eval 在运行时扩展

(apply #(eval (list* 'or %&)) [true false])

or is a macro, which you can't use as value.

Create an anonymous function, expanding or at runtime via eval:

(apply #(eval (list* 'or %&)) [true false])
北座城市 2024-09-11 07:06:33

需要注意的重要事项之一是评估模型。 短路,因此:(或true:某个永远不会被计算的随机表达式:)永远不会计算最后一个。 or 传统上与“逻辑或”一样用作控制结构。

(fxyz) 的传统模型中,对 x、y 和 z 进行求值,并对它们应用 f。

在使用(apply f vec)时,不会对向量的内容进行求值,而是按原样进行处理。这在符号向量中最为明显,它们在这种情况下不会对其绑定进行评估。然而,Clojure 的向量创建模型与其他 Lisp 有所不同,这一事实使这一点变得模糊,[abcd] 生成一个包含符号 a 求值的向量。 >、bcd。对比大多数 Lisp,其中 #(abcd) 不计算符号,而只是与计算 (vector 'a 'b 'c 'd) 相同(或者事实上(应用向量'(abcd)))。

因此,即使可以应用特殊的句法形式,其结果也会具有不透明的语义。 or 首先评估它的第一个参数,如果为 true,它会停止并返回该参数,否则它会转到第二个参数并重复直到最后一个。在 apply 的情况下,参数已经全部求值,是否应该再次求值?最有可能导致运行时错误?

从实现的角度来看,如果语法也是“对象”,那么性能将会非常低,并且需要更复杂的评估模型。因此它们不是在运行时解析的,而是在编译时重写为编译器原语。

但是,正是由于这个原因,当 or 在逻辑上使用而不是作为控制结构时,我自己发现使用函数 or/fand/ 很方便fif/f 等可用,它们是真实的过程并评估其所有参数,因此可以应用。

One of the important things to note though is the evaluation model. or short-circuits, therefore: (or true :some random expression that never gets evaluated:) never evaluates the last. or is traditionally used as much as a control structure as a 'logical or'.

In the traditional model of (f x y z), x, y, and z are evaluated, and f is applied to them.

In the use of (apply f vec) the contents of the vector are not evaluated, they are taken as is. This is most clearly visible with a vector of symbols, they do not evaluate in this context to their bindings. However, this is obfuscated by the fact that Clojure's model for vector creation is some-what different then other lisps, [a b c d] yields a vector which contains the evaluations of the symbols a, b, c, and d. Contrasting most Lisps, wherein #(a b c d) does not evaluate the symbols, and just is identical to evaluating (vector 'a 'b 'c 'd) (or in fact (apply vector '(a b c d))).

So even if it were possible to apply special syntactic forms, it's result would have an opaque semantics. or first evaluates its first argument, if true, it stops and returns that, else it goes to the second and repeats until at the last. In the case of apply, the arguments are already all evaluated, should it then evaluate some a second time? Most likely resulting into a runtime error along the way?

From an implementation perspective, it would be very performance enhibative if syntax was were also 'objects' and would require a much more complex evaluation model. So they are not resolved at runtime, but rather rewritten to compiler primitives at compile time.

But, for this very reason, when or is used logically rather than as a control structure, I myself find it handy to have functions or/f, and/f, if/f, et cetera available which are true procedures and evaluate all of their arguments and thus can be applied.

南笙 2024-09-11 07:06:32

因为 or 是一个宏,而不是一个普通的函数。您可以使用 (some Identity [true false]) 获得相同的效果。

Because or is a macro, not a normal function. You can get the same effect with (some identity [true false]).

落叶缤纷 2024-09-11 07:06:32

作为 or 的替代,您可以使用 (some 谓词 coll)。

clojure.core/some ([pred coll])
返回第一个逻辑真值
(pred x) 对于 coll 中的任何 x,否则
零。一个常见的习惯用法是使用一组
作为 pred,例如这将
如果 :fred 位于则返回 :fred
序列,否则为零:(some #{:fred} coll)

As an alternative to or you can use (some predicate coll).

clojure.core/some ([pred coll])
Returns the first logical true value
of (pred x) for any x in coll, else
nil. One common idiom is to use a set
as pred, for example this will
return :fred if :fred is in the
sequence, otherwise nil: (some #{:fred} coll)

财迷小姐 2024-09-11 07:06:32

你可以尝试一下 true 吗?和假的?谓词,


user=> (some true? [true false false])
true
user=> (not (some true? [true false false]))
false
user=> (some false? [true false false])
true
user=> (not (some false? [true false false]))
false

You can try some with true? and false? predicates,


user=> (some true? [true false false])
true
user=> (not (some true? [true false false]))
false
user=> (some false? [true false false])
true
user=> (not (some false? [true false false]))
false

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文