2010-05-14 35 views
5

R5RS給出建議的宏定義的庫語法形式:如果有的話,Scheme中的letrec定義有什麼錯誤?

http://schemers.org/Documents/Standards/R5RS/HTML/r5rs-Z-H-10.html#%_sec_7.3

,其也限定letrec,以一種非常複雜的方式,肯定不是我將如何定義它,我會簡單地使用:

(define-syntax letrec2 
    (syntax-rules() 
    ((letrec2 ((name val) ...) body bodies ...) 
    ((lambda() 
     (define name val) ... 
     body bodies ...))))) 

據我瞭解letrec的語義,我經常使用它作爲命名let。它以這種方式工作,然而,由於我與哲學家的辯論中有我認爲他們可以駁斥狹義相對論或已建立的音系理論的公平分享,所以我知道當你認爲你對複雜問題有一個簡單的解決方案時,錯誤。這個宏有些地方不符合letrec的語義,否則他們可能會使用它。

在這個定義中,定義對於letrec的本體來說是本地的,它們可以互相引用來進行相互遞歸,我不太確定什麼(如果有的話)是錯誤的。

回答

0

好吧,我終於找到原因,它就像沒用的那麼簡單,我的定義沒有錯,事實上是由於一些錯誤優於R5RS中的錯誤。

http://community.schemewiki.org/?scheme-faq-macros

查找「letrec」,你們都不能回答我的什麼是錯的問題,什麼也沒有錯顯然,R5RS曾在一個信息部分顯然是「勘誤表」。我現在被迫接受我自己的答案,我猜...

現在的問題是爲什麼R5RS作者沒有選擇這個簡單的解決方案,而是選擇了一個甚至包含錯誤的複雜問題。 ..

+0

引用我:「只有在某些實現中,內部定義纔是原始形式。」引用schemewiki:「仍然有一些Scheme實現只提供了一個原始的頂級定義,並根據letrecs實現了內部定義......」您的定義僅適用於某些實現。我引用了R5RS的介紹,以說明爲什麼我認爲R5RS作者沒有選擇你的實現。如果我關於R5RS哲學的觀點沒有道理,我願意回答你關於它的問題。 – Davorak 2010-06-11 23:56:50

+0

@Davorak好吧,從技術上講,定義將在所有實現中起作用。只是在一些實現中,它使用的內部'define'將被擴展爲'letrec'的本地實現。 – dubiousjim 2012-11-04 17:54:04

5

在我看來,你已經將實現的責任從宏推向了編譯器,這是R5RS設計者似乎試圖避免的。

事實上,本地定義是在R5RS中用letrec實現的。請參閱6.2.2 Internal definitions

我認爲設計師的意圖是總結了很好的introduction to the R5RS

編程語言應堆放在功能上面 功能不是設計,而是通過刪除 弱點和限制,使 附加功能顯得有必要。 方案表明,一個非常小的 數量形成 表情,與 他們是如何組成沒有限制的規則,足以形成 實用,高效的編程 語言足夠靈活,以 支持大多數主流編程 的今天使用的範例。

edit1: 內部定義的例子轉換爲r5rs版本的letrec。 PLT方案4.2.5收集/ R5RS/main.ss

(define-syntax (r5rs:body stx) 
(syntax-case stx (let) 
    [(_ (let() . body)) 
    #'(let() . body)] 
    [_ 
    ;; Convert internal definitions to `r5rs:letrec', as opposed 
    ;; to `letrec'. 
... 

在R5RS模式PLT的計劃不內部定義轉換成letrec的R5RS版本。 您也可以在任何內部定義的代碼上使用DrScheme的宏擴展器來爲自己測試。

+0

那麼,定義是一個原始的形式,而不是一個不同於letrec的庫形式。定義和設置!真的不能用其他功能來定義。 另外,其餘的我並不真正瞭解你的帖子如何與我的觀點相關,我仍然保持宏觀。而letrec是R5RS標準的一部分,儘管實現可能將其實現爲一個宏,但只要符合R5RS中給出的語義,就不是必需的。在這裏它仍然是一個宏,R5RS中的宏是'建議'。 – Zorf 2010-05-14 19:52:50

+0

@Lajla內部定義只是在某些實現中是一種基本形式。在一些實現中,內部定義可以根據letrec來定義。當內部定義是原始的時,你的宏只能用來定義letrec。內部定義通常是以letrec的形式定義的,因爲它遵循了我從R5RS的介紹中引用的哲學。 – Davorak 2010-05-14 23:01:44

+0

你有一些表明這一點的引用嗎?因爲如果那是真的,那顯然是解釋。但據我所知,定義總是原始的,因爲它具有完全獨特的語義,如在其中,它不能出現在很多地方,並根據宏來定義內部定義,實現需要將letrec-syntax添加到每個有一個身體的形式。你的源代碼只是說它是等價的,它並沒有明確說明它是如何實現的,但是如果你可以爲實現這個的實現提供一個引用,那麼它就是我們問題的明顯答案。 – Zorf 2010-05-15 02:39:02

0

好問題。

我想用define序列中的問題是這樣的:

「的的 表達式expr的計算順序...是不確定的, 所以程序不能 之前評估 參考任何由letrec表達綁定的變量 的所有值都被計算的」

這裏: http://www.scheme.com/tspl4/binding.html#./binding:s20

+0

但是,如果我沒有弄錯,這就是內部(和外部)定義的作用。這就是爲什麼他們可以自由地互相引用,相互遞解。 我也嘗試了所有的基本操作,如局部階乘,甚至相互遞歸?和奇怪?函數,根據letrec2定義一個named-let,讓它們在他們似乎都能工作的詞法環境上形成閉包。我很迷茫。 此外,R5RS標準似乎是針對這種方法定義的,因爲在letrec中定義的函數可以訪問定義的函數,但除非在letrec中明確定義,否則不能使用其他值。 – Zorf 2010-05-14 19:57:42

+0

我相信你錯了。 R5RS中的外部和內部定義各不相同。對於外部定義:(define a b)(define b 2)是第一個定義的語法錯誤,因爲b尚未定義。對於內部定義或letrec(letrec((ab)(b 2)a) - >#並且不應該是語法錯誤。與((lambda()) (define b 2) )) - ># Davorak 2010-05-14 23:19:10

+0

嗯,我想變得更加明確,但是我的字符太少了,是的,這是一個語法錯誤,但是:(define a(lambda(x)(+(b 2)x))) (定義b(lambda(x)(+ 1 x)))不是。正如我所說的,它們不能訪問之前沒有定義的值,但是它們可以訪問將在稍後定義的函數,這在外部和內部是相同的在這個例子中定義和(a 2)評估爲5的預期結果,這就是爲什麼我提出letrec的語義似乎是針對內部定義的原因,因爲letrec明確說它只能引用函數,而不是值 – Zorf 2010-05-15 02:36:20

3

R5RS狀態letrec的語義與內部定義完全一致,詳見the section devoted to the latter;我引用以下關鍵片段:

A <包含內部定義的主體>始終可以轉換爲完全等效的letrec表達式。

因此,定義內部定義letrec只是轉移問題。

而且,我覺得很簡單,定義一個letrec宏觀和有lambda desugar內部定義爲letrec,而不是所有的東西是複雜的代碼到lambda處理程序,並在此基礎之上建立letrec。這並沒有涉及到什麼是在非頂級範圍內引入相互遞歸綁定的更漂亮形式的問題...... ;-)

相關問題