引用一个函数名然后使用它

Quoting a function name then using it

我正在编写一个程序来记录到各个地方。其中我有一些日志功能:

(define (write-to-file destination content)
      (with-output-to-file destination
          (λ ()
           (displayln 
            content))
        #:mode 'text #:exists 'append))

(define (write-to-port destination content)
  (displayln content destination))

我想在 运行 时使用这些功能。所以我制作了一个列表列表来保存我的配置:

(define log-destinations
  '((write-to-file "my.log")
    (write-to-port (current-error-port))))

所以我有一个递归使用列表的函数log-destinations:

(define (send-log-content content destinations)
  (unless (null? destinations)
    (let ([ destination (car destinations)])
      (#%app (car destination) (cadr destination) content)) 
    (send-log-content content (cdr destinations))))

但是在 运行 时间我得到:

application: not a procedure;
 expected a procedure that can be applied to arguments
  given: 'write-to-file
  arguments...:
   "my.log"
   "[info] web: 2021/03/21 16:26:35 +11:00 /\n"
  context...:

这表明我没有正确引用函数名称。那么如何在 log-destinations 中适当地引用函数名称以便在 运行 时间正确调用它?

此处使用列表文字:

(define log-destinations
  '((write-to-file "my.log")
    (write-to-port (current-error-port))))

write-to-filewrite-to-port是符号,(current-error-port)是引用列表。您需要 log-destinations 中的子列表来包含 过程 write-to-filewrite-to-port。此外,您需要实际完成 (current-error-port) 的评估才能获得错误端口,也就是说您需要评估列表中的参数。

引用列表来创建列表文字意味着在创建列表时不会计算参数。但是,您可以在评估参数时使用 list 过程创建列表:

(define log-destinations
  (list (list write-to-file "my.log")
        (list write-to-port (current-error-port))))

或者,您可以使用反引号语法,即 quasiquotation。 Quasiquotation 允许您创建一个列表模板,并在一定程度上控制列表成员的评估方式。使用反引号对列表进行准引号,然后在应评估的参数前放置一个逗号:

(define log-destinations
  `((,write-to-file "my.log")
    (,write-to-port ,(current-error-port))))

我不清楚你为什么要使用 #%app;我的猜测是您将 (current-error-port) 视为过程应用程序中的列表。通过上述更改,您应该能够将过程调用更改为:

((car destination) (cadr destination) content)