2010-07-16 27 views
7

我希望能夠在訪問它之前測試一個變量是否被定義。如何在引用它之前測試變量是否已定義?

我喜歡指定一個「調試級別」的全局。如果調試級別爲0,則不會給出額外的輸出。當大於1時,給出調試輸出,數字越大則越冗長。

我也想設置它,以便程序運行,並假設一個0級,如果我沒有得到定義它。喜歡的東西:。(其中defined?是神奇的,我不知道該怎麼辦

(if (and (defined? debug-level) (> debug-level 1)) 
    (diplay "Some debugging info")) 

我走過的形式彙總看着The Scheme Programming Language, 4th Edition,我看到的可能性是identifier?唯一一個它沒有。不行

我使用SISC 1.16.6(聲稱R5RS規範)和切斯嬌小方案V8(聲稱R6RS達標)

編輯我試着用guard包裝eval,如:

(guard (x (else #f)) (eval 'debug-level)) 

由於'debug-level被引用,因此可以評估並傳遞給eval。然後,當eval試圖評估它時,會發生錯誤,我希望guard會被捕獲。它沒有。

編輯2我發現我想換行調試跟蹤到一個單獨的程序,並且定義該程序也可以以0的原因默認定義debug-level用於使用一個單獨的過程中的文件是降低過程中可以工作的行數,並且還允許在需要時重定向調試輸出。

回答

4

這完全取決於實現提供,它看起來像大多數實現不令人滿意地提供它。

在SISC方案,它看起來像你可以使用GETPROP這種效果,但環境不會自動更新哦,你看,有這個東西叫做交互環境,你可以使用:

 
#;> (getprop 'cons (interaction-environment)) 
#<native procedure cons> 
#;> (getprop 'x (interaction-environment)) 
#f 
#;> (define x 100) 
#;> (getprop 'x (interaction-environment)) 
100 

但它只適用於頂層。

 
#;> (define (foo y) 
    (let ((e (interaction-environment))) 
    (display "Is X bound? ") (display (getprop 'x e)) 
    (newline) 
    (display "Is Y bound? ") (display (getprop 'y e)) 
    (newline))) 
#;> (foo 1) 
#;> Is X bound? 100 
Is Y bound? #f 

對於Chez,您再次有TOP-LEVEL-BOUND?和INTERACTION-ENVIRONMENT。對於R5RS

+0

謝謝。我很害怕,答案不會是廣泛的便攜,這將是無論是在R6RS或實施具體的新的東西。 +1,但我打算讓這個答案的年齡了一下,看看是否有更好的想法得到接受是正確的之前公佈。 – 2010-07-16 21:02:46

1

要備份一位,defined?功能的問題是,如果你寫

(defined? debug-level) 

計劃將試圖評估debug-level,這當然是因爲它沒有定義的錯誤。作爲一種特殊情況,這種形式必須由編譯器/解釋器在內部執行。

這種特殊形式不是R5RS標準的一部分(除非我錯過了它,請double-check)。因此,對於R5RS方案,除非您找到將此項作爲非標準擴展實現的方案,否則您運氣不佳。

+0

我不是問一個函數定義''因爲,如你所說,一個功能是行不通的?但是一個函數也不適用於'if',但是scheme有'if'。在其他工作中,尋找特殊形式或其他方式來實現結果。 (宏也許?) – 2010-07-16 19:32:52

+1

當然。我想說的是,這必須是該語言提供了內置的形式,如'if'之一,並且規範(R5RS至少)似乎不包括一個。 – 2010-07-16 19:37:25

2

笨重,但可行的解決方案。使用let-syntax經常忽略/遺忘的能力來重新定義關鍵字。這是笨重的,因爲你的整個文件被封裝在一個let語法中,並且因爲它給每個定義增加了一些開銷。我使用關聯列表來記憶定義,散列表將是一個選擇。

(define define-list '()) 
(define define-list-add 
    (lambda (key value) 
    (set! define-list (cons `(,key ,value) define-list)))) 

(let-syntax (
      (define (syntax-rules() 
         ((_ (pro-name args ...) body ...) 
         (begin 
          (define (pro-name args ...) body ...) 
          (define-list-add pro-name '((pro-name args ...) body ...)))) 
         ((_ pro-name pro) (begin 
              (define pro-name pro) 
              (define-list-add 'pro-name 'pro))) 

         )) 
      (defined? 
       (syntax-rules() 
       ((_ sym) (begin (if (assoc (quote sym) define-list) #t #f))))) 
      ) 
    (define y (lambda() x)) 

    (display (defined? y)) 
    (newline) 
    (display (defined? x)) 
) 

打印

#t 
#f 

下面在球拍:一個模塊用於重新定義定義存儲每個符號和定義在稱爲定義列表列表。宏定義了嗎?在這個列表中查看是否天氣符號已被定義。

(module qdefine mzscheme 
    (provide ;(all-from-except mzscheme let) 
    (rename define olddefine) 
    (rename quote-define define) 
    defined?) 

    (define define-list '()) 
    (define define-list-add 
    (lambda (key value) 
     (set! define-list (cons `(,key ,value) define-list)))) 

    (define-syntax quote-define 
    (syntax-rules() 
     ((_ (pro-name args ...) body ...) 
     (begin 
     (define (pro-name args ...) body ...) 
     (define-list-add pro-name '((pro-name args ...) body ...)))) 
     ((_ pro-name pro) (begin 
          (define pro-name pro) 
          (define-list-add 'pro-name 'pro))) 

    )) 

    (define-syntax defined? 
    (syntax-rules() 
     ((_ sym) (begin (if (assoc (quote sym) define-list) #t #f))))) 
) 
(require 'qdefine) 

(define y (lambda() x)) 

(defined? y) 
(defined? x) 

在guile中它只是被定義的嗎?顯然: http://www.delorie.com/gnu/docs/guile/guile_289.html

+1

球拍確實有反射工具做這樣的事情,但這樣的事情(包括'交互environment',無論狡詐呢,等)總是搖搖欲墜一種解決方案,遭受這樣或那樣的。 – 2010-07-17 22:29:18

+0

適用於便攜式解決方案。 – 2010-07-19 15:43:20

相關問題