如果'适用'将给定函数应用于列表的所有元素,为什么以下不起作用:
> (apply println (list "a" "b" "c"))
. . println: contract violation
expected: output-port?
given: "b"
argument position: 2nd
other arguments...:
>
https://docs.racket-lang.org/reference/procedures.html和https://docs.racket-lang.org/guide/application.html中给出的示例与add(+)函数有关。有人可以提供其他应用示例并解释它是如何工作的。感谢。
答案 0 :(得分:4)
就像(apply + (list 1 2 3 4))
相当于(+ 1 2 3 4)
,(apply println (list "a" "b" "c"))
相当于(println "a" "b" "c")
。但是,这不是println
的有效用法。正如错误消息所示,第二个参数应该是输出端口,而不是字符串。
要使用println
正确调用apply
,您必须提供有效的参数列表,例如:
(apply println (list "a"))
;; or
(apply println (list "a" (current-output-port))
以下是使用带有任意数量参数的函数的apply
的一些示例,因此无论列表的长度如何,它都将始终有效:
(apply * (list 1 2 3 4)) ; 24
(apply list (list 1 2 3 4)) ; (list 1 2 3 4) ¹
(apply set (list 1 2 3 4)) ; (set 1 2 3 4)
¹好吧,你不会真正将apply
与list
一起使用,因为它只会让你返回相同的列表(或者更确切地说是它的副本),但你可以。
答案 1 :(得分:3)
如果您想申请程序,例如。 (proc a b c)
但参数在列表中提供。您可以执行(proc (car l) (cadr l) (caddr l))
,但也可以执行(apply proc l)
。如果您有前面想要的其他参数,您甚至可以(apply proc 5 l)
,它与(proc 5 (car l) (cadr l) (caddr l))
相同。 apply
接受任意数量的参数,但最后一个必须是最终参数的列表。
了解apply
不是折叠是很重要的。如果你有一个只有一个参数的过程,那么你可以用一个恰好一个元素的列表来应用它,否则过程就会失败。
(cons 1 2) ; ==> (1 . 2)
(apply cons '(1 2)) ; ==> (1 . 2)
(cons 1 2 3) ; ==> ERROR cons: arity mismatch
(apply cons '(1 2 3)); ==> ERROR cons: arity mismatch
apply
与休息参数相反:
(define (proc arg1 . argn)
(apply list arg1 argn))
(proc 1 2 3 4) ; ==> (1 2 3 4)
不是折叠
;; a two arity add
(define (add a b)
(+ a b))
(apply add '(1 2)) ; ==> 3
(apply add '(1 2 3)) ; ==> ERROR add: arity mismatch
;; foldl is a fold
(foldl add 0 '(1 2 3)) ; ==> 6