在Racket中应用+以外的示例

时间:2016-08-19 17:30:18

标签: scheme racket

如果'适用'将给定函数应用于列表的所有元素,为什么以下不起作用:

> (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.htmlhttps://docs.racket-lang.org/guide/application.html中给出的示例与add(+)函数有关。有人可以提供其他应用示例并解释它是如何工作的。感谢。

2 个答案:

答案 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)

¹好吧,你不会真正将applylist一起使用,因为它只会让你返回相同的列表(或者更确切地说是它的副本),但你可以。

答案 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