2010-10-02 60 views
0

我正在嘗試一些計劃中的樂趣。我正在嘗試創建一個Area函數來獲取它正在操作的事物的類型,然後根據對象的類型調用不同的函數。這裏是我的代碼:如何在Scheme中使用eval中的外部變量?

(define (area object) 
    (if (not (null? (eval (word 'area- (get-type object))))) 
     (eval (list (word 'area- (get-type object)) 'object)) 
     #f 
) 
) 

Scheme不喜歡這個,因爲它說對象是一個未綁定的變量。不,我不能拿走報價,因爲那實際上是將價值放在那裏,然後Scheme抱怨列表不正確。

我能做些什麼來使用eval中的對象的值?

注:方案顯然抓住全局變量「對象」就好了,所以它基本上忽略它在一個函數內。

一些相關語言的信息在這裏:http://docs.racket-lang.org/guide/eval.html,這似乎表明Scheme中沒有解決方案,但是如果您知道一個我想聽到它。

+0

就像Eli所說的那樣,使用基於名稱的調度機制是非常糟糕和破裂的。 Scheme不是PHP。只是不要去那裏。 :-P – 2010-10-02 08:46:11

+0

爲什麼這樣做是不正確的,克里斯? – 2010-10-03 01:10:24

回答

3

沒有一個 - 這是一個功能。 eval正在對運行時動態生成的表單進行評估。因此,如果需要了解本地綁定,那麼您需要編譯(lamba (x) x)(lambda (y) y),因爲名稱很重要。但這僅僅是一個小貼士,圍繞着實現這種功能還有很多問題。

至於你的問題 - 即使有可能做你想做的事情,這是一個脆弱的解決方案,取決於名稱。請記住,在Scheme中,您可以使用類似於任何其他值的函數 - 因此,不要調用get-type並將其與某個符號組合以獲取名稱,使您的對象包含所需的函數(此時更好地稱爲「方法「)。

喜歡的東西:

(define (area object) 
    ((get-area-method object) object)) 

顯然,這樣做意味着在不打算全路小點:

(define (area object) 
    (get-area object)) 

這只是

(define area get-area) 

但第一可能更像一個通用的面向對象系統的典型,有一種方法來獲取方法,所以它可能對你有用。這個方向可能會帶你:

(define (area object) 
    ((get-method object 'get-area) object)) 
0

顯然有一種方法可以做我想做的計劃。下面是代碼:

(define (area object) 
    ((eval (list 'identity (word 'area- (get-type object)))) object) 
) 

基本上訣竅是這樣的:因爲EVAL只知道全局變量,我仍然可以使用eval裏的身份函數返回一個全局變量的值。在這種情況下,我感興趣的全局變量是一個函數,就像任何其他變量一樣。然後我可以返回這個值並將其用作調用我原始參數的過程。這使我可以構造我想從全局作用域獲得的變量的名稱,並獲取並使用該變量中包含的過程,從而完成我期待的結果。

這裏有一個更清楚地版本:

(define (area object) 
    ((get-function (word 'area- (get-type object))) object) 
) 

(define (get-function function) 
    (eval (list 'identity function))) 

顯然的是,非空部分將無法正常工作,但是,因爲試圖獲得一個不存在的原因未綁定變量誤差函數的身份。所以,仍然需要小心地調用一個支持它的類型的操作符。

+1

這是非常錯誤的。從使用「身份」是多餘的事實開始(您可以直接「評估」符號 - 相同的結果),然後從那裏得到您的「乾淨」版本的「get-function」,它本身就是一個身份功能。 – 2010-10-02 04:58:56

+0

但是,如何評估構造符號?也許(eval(list(append something?)問題是,eval從列表中構造一個過程,所以如果我(eval'thing)真的沒有參數調用(thing),而不是僅僅返回值的東西 – 2010-10-02 05:07:09

+0

不,這是錯誤的,'(eval'x)'只返回全局'x'的值,它不會調用任何函數(但請參閱我的答案 - 您不應該使用'eval'來處理這些事情。 ) – 2010-10-02 05:16:11

2

球拍有classes and methods,你應該使用它!

(define circle% 
    (class object% 
    (init radius) 
    (define r radius) 
    (super-new) 
    (define/public (area) 
     (* pi r r)))) 

(define rectangle% 
    (class object% 
    (init width height) 
    (define w width) 
    (define h height) 
    (super-new) 
    (define/public (area) 
     (* w h)))) 

(define unit-circle (new circle% [radius 1])) 
(define unit-square (new rectangle% [width 1] [height 1])) 

(send unit-circle area) ; => 3.141592653589793 
(send unit-square area) ; => 1 

很多小於基於域名的派遣哈克。

相關問題