我可以在Scheme中的过程中定义全局吗?

时间:2009-12-12 20:29:21

标签: scheme

我有一种情况,我想做一些像......

(define (def a b)
    (store a b) ; store the definition of 'a' somewhere
    (define-global a b)) ; also define 'a' so that its definition
                         ; is accessible later in the program

这有可能吗?据我所知define-global不存在,所以程序中的define语句仅适用于本地环境。

这是为了在方案中为嵌入式DSL创建'def'过程,因此除了定义之外,我还需要将定义存储在我自己的符号表中。最终我想“拦截”符号查找以应用我自己的转换,返回符号查找的表达式,而不是实际执行它。

我正在使用Gambit-C Scheme。

感谢。

3 个答案:

答案 0 :(得分:4)

不,至少没有任何Gambit特定的低级别钩子。但这是有充分理由的:你所建议的将无法进行有效的编译,因为绑定可以随时改变。

如果您的目标是实现DSL,那么将值保存在您自己的表中,并在DSL中实现变量查找的代码中进行查找非常有意义。此外,它自然会引导您实现DSL在其自己的世界中的实现,与实现它的代码分开。 (例如,如果你有上述内容,那么当DSL中的代码定义了一个名为def的变量时,你会发生什么?)

答案 1 :(得分:1)

可能有办法解决这个问题。我正在寻找一种在玩具计划中实现这一目标的方法,并且在特定环境中进行定义。如果gambit具有eval的环境选项,那么您应该能够通过调用(interaction-environment)来获取父作用域中的环境。将其保存在全局环境中或通过参数传递。你可以做类似的事情:

(定义全球环境(互动环境))

;; ;;其他代码和体面的调用栈

(eval(cons'define(cons symbol-a(cons value'())))global-environment)

这应该使用传入的环境评估表达式并获得您想要的内容。如果一切正常。它取决于获得对全局环境的引用的调用以及可以将环境作为参数的eval。

答案 2 :(得分:0)

;; It's always possible to create a global variable
;; (assigned to #f so you know if it's been assigned to yet)
;; and just use it later.
(define *some-global-var* #f)
;; then later on...
(set! *some-global-var* 234234) ;; or w/e you want
(if *some-global-var* ;; it's been assigned
    (do-something *some-global-var*))

;; But in your case, a (hash) table is definitely
;; much better than unorganized free variables.
;; Gambit-C has hash tables built in. So, you can
;; define the hash table early on...
(define *globals* (make-table))
;; And assign to it later. Use the "variable name"
;; for the key.
(table-set! *globals* 'x 3)
(table-set! *globals* 'y 4)
;; Whenever you want you plan to access
;; a lot, it's best to use a "let"
(let ((x (table-ref *globals* 'x)) (y (table-ref *globals* 'y)))
  (println "The sum of " x " and " y " is " (+ x y) "."))
The sum of 3 and 4 is 7.

;; Gambit also has structures, and they too are useful
;; for organizing data (*kind of* like C structs).
;; Note that it's possible to assign structures to hash
;; tables -- just like anything else -- and sometimes
;; it's *very* useful to do so.
(define-structure person name age)
(define jy (make-person "jyaan" 9000))
(person-name jy)
"jyaan"
(person-age-set! jy 25)
(println jy)
#<person #3 name: "jyaan" age: 25>