2013-03-24 36 views
5

Làm cách nào để viết một hàm để giải quyết một biểu tượng trong một môi trường từ vựng?clojure - giải quyết một biểu tượng bên trong let

(let [foo some-var] 
    (let [sym 'foo] 
    (resolve-sym sym))) 

Tôi muốn nhận được var 'foo bị ràng buộc.

+3

Hãy không tạo ra vars mới, vì vậy về cơ bản bạn không thể giải quyết chúng – Ankur

+0

Nhưng nó có thể để có được môi trường bên trong một macro với & env. – navgeet

+0

@navgeet, không, điều đó là không thể. '(defmacro m [x & env] '(x env))' sẽ mở rộng theo cách này: '(m 1 2 3 4 5) ->' (1 (2 3 4 5))', tức là '& env' sẽ cung cấp cho bạn quyền truy cập vào varargs. Không có cách nào trong Clojure để có được môi trường từ vựng hiện tại. –

Trả lời

4

Tôi không hoàn toàn chắc chắn lý do tại sao tôi muốn một cái gì đó như thế này, nhưng có vẻ như nó chắc chắn có thể được thực hiện. từ http://clojuredocs.org/circumspec/circumspec.should/local-bindings

(defmacro local-bindings 
    "Produces a map of the names of local bindings to their values. 
    For now, strip out gensymed locals. TODO: use 1.2 feature." 
    [] 
    (let [symbols (remove #(.contains (str %) "_") 
         (map key @clojure.lang.Compiler/LOCAL_ENV))] 
    (zipmap (map (fn [sym] `(quote ~sym)) symbols) symbols))) 


(let [foo 1 bar 2] 
    (local-bindings)) 
=> {foo 1, bar 2} 
1

Đây là cả hơn, ít hơn và nghiêng tới hơn bạn muốn:

(define (make-let-core name value body) 
    `(CORE LET ,name ,value ,body)) 

(define (env-extend env a-name its-denotation) 
    (lambda (name) 
    (if (equal? name a-name) 
     its-denotation 
     (if env (env name) 'unknown)))) 

(define (env-base) 
    (lambda (name) 
    (if (member name '(let resolve-sym #| ... |#)) 
     'syntactic-keyword 
     'unknown))) 

(define (expand exp env) 
    (cond ((literal? exp) ...) 
     ((symbol? exp) ...) 
     ((list? exp) 
     (let ((operator (car exp)) 
       (operands (cdr exp))) 
      (cond ((symbol? operator) 
        (case (env operator) 
        ((syntactic-keyword) 
        (case operator 
         ((let) 
         (let ((bound-name (caar operands)) 
           (bound-value (cadar operands)) 
           (body (cdr operands))) 
          (make-let-core bound-name 
             (expand bound-value env) 
             (expand body 
               (env-extend bound-name 
                  'variable))))) 
         ((resolve-sym) 
         (let ((name (car operands))) 
          ;; right here 
          ...)) 
         (...))) 
        ((variable) ;; function call 
        ...) 

        ((unknown) ;; syntax error 
        ...))) 

       ((list? operator) ;; function call 
        ...) 

       (else ;; syntax error 
        ...)))) 
     (else ;; syntax error 
     ...))) 
+0

Có vẻ như @navgeet đang tìm kiếm một giải pháp Clojure, cái này không phải. – dfreeman

+0

và, thậm chí nó không phải là một giải pháp ... – GoZoner

+0

Vâng, câu hỏi được gắn thẻ với "lisp". –

Các vấn đề liên quan