[c t] ([val ch] (foo ch val))
有一些情况下,列表并不意味着“作为函数进行评估”。例如:
(ns com.foo.bar
(:require …))
在上面的代码中,没有调用名为
:require
的函数。
另一个利用列表进行非函数应用的例子是
letfn
:
(letfn [(foo [x] (+ (bar 1) x))
(bar [x] (+ 2 x))]
(+ (foo 5) (bar 7)))
如上所示,
letfn
有两个列表,一个以符号
foo
开头,另一个以符号
bar
开头,这两个列表都不是传统的函数调用。相反,
letfn
正在定义两个新函数,一个名为
foo
,另一个名为
bar
。表达式的其余部分被视为“主体”,在其中使用这些函数。
与
letfn
类似,
alt
定义了一个名为
val
的值和一个名为
ch
的通道,然后剩余的表达式(
(foo ch val)
)被视为“主体”,在其中使用这两个名称。
< h1 >
alt!/ alt!!
的解释:
我觉得最容易将alt!
和alt!!
视为类似于cond
,只不过它不是测试条件来选择要执行的主体,而是等待通道来选择要执行的主体。每个子句由两个部分组成,就像cond
一样-第一部分(“通道操作”)用于指定alt!
应等待的通道,第二部分(“结果表达式”)指定如果该通道首先传递一个值应该发生什么。
因为您可能希望在发生这种情况时访问通道传递的值或通道本身,所以
结果表达式让您有机会将值和通道绑定到符号,并执行具有这些绑定的代码主体。因此,以下子句...
[c t]
([val ch]
(foo ch val))
…的意思是:
这个调用 alt!
的通道操作之一应该阻塞在尝试从两个通道 c
或 t
中 获取 值的过程中。如果其中任何一个在这个调用 alt!
中的任何其他通道操作之前发送了一个值,那么使用从首先传递值的通道获取的值将执行 (foo ch val)
,并将 val
绑定到传递val
的通道(它将是c
或t
中的一个),将ch
绑定到传递val
的通道。
以下是需要翻译的子句...
[[out input-val]]
([val ch]
(bar ch val))
...的意思是:
这个对alt!
的调用中,其中一个通道操作应该阻塞在尝试将input-val
放入名为out
的通道上。如果在此对alt!
的调用中任何其他通道操作之前成功了,那么使用val
绑定到input-val
和ch
绑定到out
(成功接收值的通道)执行(bar ch val)
。
总的来说,这两个子句将被写成:
(alt!
[c t]
([val ch]
(foo ch val))
[[out input-val]]
([val ch]
(bar ch val)))
[c t]
是一个端口向量。[val ch]
是一个绑定(正如你所说)。ch
是可以从中获取的通道;而val
是取出的值。然后使用该绑定来评估函数foo
。请参见https://gist.github.com/konacaret/d1f5c19cfbe46d3b97a3,了解此简单示例。 - konacaret