tags:

views:

163

answers:

3

I have a situation where I'd like to do something like...

(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

Is this possible somehow? As far as I know define-global doesn't exist, so define statements inside procedures apply only to the local environment.

This is intended for creating a 'def' procedure for an embedded DSL in scheme, so in addition to making the definition I need to store the definition in my own symbol table. Eventually I want to 'intercept' symbol look-ups to apply my own transformation, returning an expression for the symbol look-up instead of actually performing it.

I'm using Gambit-C Scheme.

Thanks.

+3  A: 

No, at least not without any Gambit specific low-level hooks. But this is for a good reason: what you're suggesting would make it impossible to do efficient compilation, since bindings can change at any time.

If your goal is to implement a DSL, then keeping the values in your own table, and doing the lookup in code that implements variable lookup in your DSL makes a lot of sense. In addition, it will naturally lead you to an implementation where the DSL lives in its own world, separately from the code that implements it. (For example, if you have the above, then what would you expect to happen when code inside the DSL defines a variable called def?)

Eli Barzilay
Thanks. I'd love to 'hook' into the define system to implement my own symbol table, but if I try to do it with a macro for example it doesn't seem to work across `(read)`. This is all in the name of trying to take advantage of Scheme's own `eval`. If I implement my own `eval` I guess everything's possible, but trying to hook into symbol look-up seems impossible. :( Too bad because otherwise using Scheme's eval makes a lot of things easier, such as allowing user-defined macros.
Steve
+1  A: 

There might be a way to pull this off. I was looking for a means of pulling this off in a toy scheme and happened across a means of defining within a specific environment. If gambit has an environment option to eval, then you should be able to get the environment in you parent scope with a call to (interaction-environment). Either save this in the global environment or pass it through arguments. You could be able to do something like:

(define global-environment (interaction-environment))

;; ;; other code and decent into the call stack

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

This should evaluated the expression using the passed in environment and get about what you want. If everything is working correctly. It hinges on having the call to get a reference to the global environment and an eval that can take an environment as an argument.

Novice Schemer
Quite nice idea! :-) I've tested something similar, and it works!
Jay
A: 
;; 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>
Jyaan