2009-12-12 2 views
2

J'ai une situation où je voudrais faire quelque chose comme ...Puis-je définir un global à l'intérieur d'une procédure dans 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 

Est-ce possible en quelque sorte? Autant que je sache, define-global n'existe pas, donc les instructions define à l'intérieur des procédures ne s'appliquent qu'à l'environnement local. Ceci est destiné à créer une procédure 'def' pour un schéma DSL intégré, donc en plus de faire la définition, j'ai besoin de stocker la définition dans ma propre table de symboles. Finalement, je veux «intercepter» les recherches de symboles pour appliquer ma propre transformation, renvoyer une expression pour la recherche de symboles au lieu de l'exécuter réellement. J'utilise Gambit-C Scheme.

Merci.

Répondre

3

Non, du moins pas sans crochets de faible niveau spécifiques à Gambit. Mais c'est pour une bonne raison: ce que vous proposez rendrait impossible une compilation efficace, puisque les liaisons peuvent changer à tout moment. Si votre objectif est d'implémenter un DSL, alors garder les valeurs dans votre propre table, et faire la recherche dans le code qui implémente la recherche de variable dans votre DSL a beaucoup de sens. De plus, il vous conduira naturellement à une implémentation où la DSL vit dans son propre monde, indépendamment du code qui l'implémente. (Par exemple, si vous avez ce qui précède, qu'attendez-vous lorsque le code à l'intérieur du DSL définit une variable appelée def?)

+0

Merci. J'adorerais "accrocher" dans le système de définition pour implémenter ma propre table de symboles, mais si j'essaye de le faire avec une macro par exemple cela ne semble pas marcher sur '(lire)'. Tout cela dans le but d'essayer de tirer profit du propre 'eval' de Scheme. Si j'implémente mon propre 'eval', je suppose que tout est possible, mais essayer de s'accrocher à la recherche de symboles semble impossible. :(Dommage car sinon utiliser l'eval de Scheme facilite beaucoup de choses, comme autoriser des macros définies par l'utilisateur – Steve

1

Il pourrait y avoir un moyen de retirer ceci. Je cherchais un moyen de tirer cela dans un jeu de jouets et est arrivé à travers un moyen de définir dans un environnement spécifique. Si gambit a une option d'environnement à évaluer, vous devriez pouvoir obtenir l'environnement dans votre portée parent avec un appel à (interaction-environment). Enregistrez-le dans l'environnement global ou transmettez-le via des arguments. Vous pourriez être en mesure de faire quelque chose comme:

(définition de l'environnement global (interaction environnement))

;; ;; autre code et décent dans la pile d'appel

(eval (contre « define (symbole d'un contre (valeur de contre »()))) environnement mondial)

Cela devrait évaluer l'expression en utilisant le passé dans l'environnement et obtenez ce que vous voulez. Si tout fonctionne correctement. Il dépend d'avoir l'appel pour obtenir une référence à l'environnement global et un eval qui peut prendre un environnement comme argument.

+0

Assez bonne idée! :-) J'ai testé quelque chose de similaire, et ça marche! – Jay

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> 
Questions connexes