评估引用函数参数的代码

Evaluating code which refers to function parameters

更新:这个问题的原版没有完整描述我的情况的局限性。它现在包括一个示例,为了简单起见,还有一个可测试的最小示例。

我正在尝试将一段代码传递到程序中,以便稍后进行评估。具有所有约束的系统如下所示:

; External Library code - cannot be changed
(define (serialize-parameters . args)
  (format some-file "~A~%" args))

(define (function-called-later-possibly-after-a-system-reboot callback)
  (apply callback some-default-parameters (deserialize-parameters some-file)))

; Internal library code - can be changed, but the value of `code-snippet` cannot be hardcoded
(define (callback some-default-parameters code-snippet)
  (eval code-snippet (current-module))

; Application code - can be changed, can be hardcoded
(define (main)
  (serialize-parameters #:code-snippet '(format #t "~A~%" some-default-parameters)))

要点是允许应用程序在回调函数中执行任意代码片段。回调函数接收应用程序未知的其他参数,并且可能会在调用之间发生变化。

一个重要的约束是应用程序要发送给回调的参数被写入一个文件,然后在稍后的时间点(可能在系统重启后)读回。

此示例更易于测试,但未捕获所有约束:

(define (test foo bar)
    (eval bar (current-module)))

(test "value of foo" '(format #t "~A~%" foo))

运行 这个程序的结果是 Unbound variable: foo。我想要的是 test 函数的定义方式是调用的结果将 "value of foo\n" 打印到终端。这在 Guile 中可能吗?

谢谢。

这行不通。 eval 需要一个环境,你传递它 (current-module)。这是模块中的顶级绑定,如 test 但不是任何词法绑定,如 foobar。它们只是不存在于 (current-module) 返回的环境中。

你可以这样做:

(define foo "value of foo")
(eval '(format #t "~A~%" foo) (current-module))
; prints "value of foo"
; ==> #t

此外,房间里的大象是您可以使用 lambda 执行此操作:

(define (test value proc)
  (proc value))

(test "value to process" (lambda (foo) (format #t "~A~%" foo)))
; prints "value to process"
; ==> #t

或者,但我猜你不能在回调中使用 format,因为 "code-snippet" 可以有许多不同的值:

(define (main)
  (serialize-parameters #:code-snippet "~A~%"))

(define (callback some-default-parameters code-snippet)
  (format #t code-snippet some-default-parameters))

编辑

我认为你可以半硬编码:

(define (main)
  (serialize-parameters #:code-snippet 'print-format))

(define (callback argument message)
  (case message
    ((print-format) (format #t "~A~%" argument))
    ((other-message) (handle-message ...))
    (else ...)))

您甚至可以将其设为动态调度程序。例如。你做这样的事情:

(define messages '())
(define (register-callback message proc)
  (set! messages (cons (cons message proc) messages)))

(define (callback argument message)
  (let ((found (assq message messages)))
    (when found
      ((cdr found) argument))))

(register-callback 'print-format (lambda (arg) (format #t "~A~%" arg)))

(callback "test" 'print-format) ; prints "test"

现在只有消息存储在文件中,该文件很容易是任何数据文字。