Guile / Scheme - 重新定义另一个模块的内部功能

时间:2014-02-16 20:42:20

标签: scheme guile

假设我有以下两个文件:

;; demo.scm
(define-module (demo)
  #:export (f))

(define (g x) 1)
(define (f x) (g x))

...并在同一目录中:

;; use-demo.scm
(add-to-load-path ".")
(use-modules (demo))

(define (g x) (+ x 1))
(display (f 5))
(newline)

在Guile(2)中运行use-demo.scm,我得到输出1。所以看起来函数f已“关闭”模块g中定义的函数demo。有没有办法解决这个问题?我真的想使用我在g中重新定义的use-demo.scm版本。

2 个答案:

答案 0 :(得分:1)

好的,只是为了记录,我做了一些研究,并且发布了针对这个特定问题的解决方案,以防有人帮助。

诀窍是在本地重新定义g,而是将新函数“注入”demo模块的名称到值的映射。

(add-to-load-path ".")
(use-modules (demo))

(module-define! (resolve-module '(demo)) 'g
  (lambda (x) (+ x 1)))

(display (f 5))
(newline)

答案 1 :(得分:0)

如果您希望能够覆盖特定功能,则可以使用parameters对其进行配置。这有一些优点:

  1. 您无需致电reload-module将模块重新置于原始配置中。
  2. 更改仅适用于需要修改行为的代码范围。
  3. 使用多个线程时,它可以正常工作。
  4. 显然,主要的缺点是你需要为你想要覆盖的每个函数添加一些样板(虽然这就是卫生宏的用途,呵呵)。

    以下代码可能有效。我还没跑过。

    ;; demo.scm
    
    (define-module (demo)
      #:export (f))
    
    (define (default-g x) 1)
    (define p (make-parameter default-g))
    (define (f x) ((p) x))
    
    
    ;; use-demo.scm
    (add-to-load-path ".")
    (use-modules (demo))
    
    (define (my-g x) (+ x 1))
    (parameterize ((@@ (demo) p) my-g)
      (display (f 5))
      (newline))
    

    显然,如果您可以提供有关此功能的应用程序的其他信息,我可能会建议其他方法(还有其他一些方法)。