2009-07-23 74 views
27

我這裏盛產希基說某處閱讀:延續Clojure中

「我想延續可能是在理論上整齊 ,但在實踐中沒有」

我不熟悉使用Clojure。
1. clojure是否有延續?
2.如果不是,你不需要延續?我已經看到了很多很好的例子,特別是從this guy。什麼是替代方案?
3.如果是,是否有文檔?

+1

您的問題標題似乎沒有太多的問題文字。 – 2009-07-23 17:04:46

+0

更好嗎? – unj2 2009-07-23 17:09:53

回答

26

在談到延續,你將有兩種不同的人之間的區別:

  • 一流的延續 - 繼續支持,是深度整合用語言(Scheme或Ruby)。 Clojure不支持一流的延續。 (CPS) - CPS只是一種編碼風格,任何支持匿名函數的語言都會允許這種風格(也適用於Clojure)。

例子:

-- Standard function 
double :: Int -> Int 
double x = 2 * x 

-- CPS-function – We pass the continuation explicitly 
doubleCPS :: Int -> (Int -> res) -> res 
doubleCPS x cont = cont (2 * x) 
; Call 
print (double 2) 

; Call CPS: Continue execution with specified anonymous function 
double 2 (\res -> print res) 

在維基百科上閱讀continuation

我不認爲延續是一種好語言所必需的,但特別是Haskell等功能語言中的一流延續和CPS可能是非常有用的(intelligent backtracking example)。

+9

關於您的兩點中的第二點,在一般情況下是否不需要尾部調用優化來使CPS可用?考慮一個標準函數,將其包裝在「while(!aborted)」塊中以使其重複,直到中止。 CPS風格的函數是不是等同使用它作爲延續?因此你會得到無限的遞歸,並且需要tail-call優化。我只是想在這裏大聲,所以請告訴我,如果這是有道理的:-) – harms 2009-07-23 18:01:16

13

延續是語言中必備的功能嗎?

不是。很多語言沒有延續。

如果不是,你不需要延續?我已經看到了很多很好的例子,特別是來自這個傢伙。什麼是替代方案?

調用堆棧

+7

+1爲調用堆棧 – Dario 2009-07-23 17:24:27

7

延續的一個常見用途是在控制結構的執行:從函數返回,從一個循環破壞,異常處理等大多數語言(如Java,C++等)提供這些功能作爲核心語言的一部分。有些語言不會(例如:Scheme)。相反,這些語言將連續性作爲第一類對象進行公開,並讓程序員定義新的控制結構。因此Scheme應該被看作是一種編程語言工具包,而不是一種完整的語言。

在Clojure中,我們幾乎不需要直接使用延續,因爲幾乎所有的控制結構都是由語言/虛擬機組合提供的。儘管如此,頭等延續可以成爲主管程序員手中的強大工具。特別是在Scheme中,continuations比其他語言中的等價類更好(例如C中的setjmp/longjmp對)。 This文章有更多細節。

順便說一句,瞭解Rich Hickey如何證明他對繼續的看法會很有趣。任何鏈接?

+1

你需要有什麼功能,以便語言是「完整的」? – unj2 2009-08-05 17:10:04

+2

它應該是「完整的」而不是「完整的」。當我說「完成」時,我並不是說圖靈完整。我的意思是人們通常從「現代」語言期望的功能。例如,使用try-catch進行異常處理。 Scheme沒有提供,但是使用first-class continuation可以實現自己的異常處理機制。 – 2009-08-06 03:45:38

+8

良好的Lispers通過增加對這個問題的語言來編寫程序。換句話說,您將Lisp轉換爲最適合解決當前問題的語言。這是Lisp和其他語言之間的一個很大的區別。 Paul Graham在他的書「On Lisp」中詳細解釋了這一點。我不知道你是誰或你做了什麼,但我想你沒有在Lisp中編寫任何重要的軟件。否則,我不必解釋這一點。我維護自己的計劃並每天使用它來解決現實世界的問題。 – 2009-08-07 08:52:17

0

嗯...... Clojure的->實現你所追求的......但是,隨着宏觀代替

5

摘要延續

延續是用於描述控制流語義的抽象的概念。從這個意義上說,它們都以任何提供控制操作符的語言存在並且不存在(記住,它們是抽象的)(就像任何圖靈完備語言必須的那樣),就像存在數字一樣(作爲抽象實體)和不存在(作爲有形實體)。

Continuations描述控制效果,如函數調用/返回,異常處理,甚至是goto。除了別的之外,一個充分建立的語言將被設計爲具有基於延續的抽象(例如,例外)。 (也就是說,一個有根據的語言將由控制操作員組成,這些控制操作員的設計考慮到了延續性。當然,對於一種語言來說,控制抽象的操作是完全合理的,因爲用戶可以構建控制抽象在上面自己的抽象。)

一流的延續

如果延續的概念是reified作爲一門語言的第一類對象,那麼我們有一個工具,在所有類型的控制效果可建成。例如,如果一種語言具有一流的延續,但不是例外,我們可以在延續之上構造異常。

用一流的延續問題

儘管一流的延續在許多情況下,一個強大的和有用的工具,也有一些缺點的語言揭露他們:

  • 建立不同抽象在繼續之上可能會導致構成時出現意外/不直觀的行爲。例如,如果我使用延續來中止計算,則可能會跳過finally塊。
  • 如果可以隨時請求當前延續,那麼語言運行時間必須是結構化的,以便可以隨時產生當前延續的一些數據結構表示。這給運行時帶來了一定程度的負擔,這些功能無論好壞都常常被認爲是「異國情調」。如果託管的語言(如Clojure託管在JVM上),那麼該表示必須能夠適應託管平臺提供的框架。語言可能還會有其他特徵要維護(例如,C interop),這會限制解決方案空間。諸如此類的問題增加了「阻礙不匹配」的可能性,並且可能使高性能解決方案的開發嚴重複雜化。

加一等延續到語言

通過元編程,可以爲一流的延續支持添加到語言。通常,這種方法涉及將代碼轉換爲continuation-passing style(CPS),其中當前延續作爲每個函數的明確參數傳遞。

例如,David Nolen的delimc庫通過一系列宏變換實現Clojure程序各部分的分隔延續。同樣,我編寫了pulley.cps,它是一個將代碼轉換爲CPS的宏編譯器,以及運行時庫,以支持更多核心Clojure功能(例如異常處理)以及與本機Clojure代碼進行互操作。

這種方法的一個問題是如何處理原生(Clojure)代碼和轉換(CPS)代碼之間的邊界。具體而言,由於無法捕獲本機代碼的延續,因此您需要禁止(或以某種方式限制)與基本語言進行交互操作,或者爲用戶設置負擔以確保上下文將允許他們希望實際捕獲的任何延續被抓獲。

pulley.cps傾向於後者,儘管已經做了一些嘗試以允許用戶管理這一點。例如,可以禁止CPS代碼調用本地代碼。此外,還提供了一種機制來提供現有原生功能的CPS版本。

在具有足夠強類型系統(如Haskell)的語言中,可以使用類型系統來封裝可能使用來自功能純代碼的控制操作(即延續)的計算。

摘要

我們現在必須直接回答你的三個問題所需的信息:

  1. Clojure的不支持,由於實際的考慮一流的延續。
  2. 所有語言都是建立在理論意義上的延續上,但很少有語言將延續作爲第一類對象來展現。但是,可以通過例如轉換成CPS來將延續添加到任何語言。
  3. 查閱關於delimc和/或pulley.cps的文檔。