編程語言有類型推斷的話,我們就直接寫 Ruby 直接編譯到二進位了嗎?

我的水平只能實現很簡單的腳本解釋器, 因此對後邊的知識感到疑惑,,

比如今天也看到一門語言, 大概一些介紹.. http://ruby-china.org/topics/16489

語言嘗試實現類型推斷, 為了直接用 Ruby 的語法書寫, 同時能編譯到二進位..

對於類型推斷, 我在學習 Haskell (的基礎部分)中了解, 無需聲明類型, 編譯時自動推斷,

Ruby 語法和 Haskell 的還是很大, 並沒有嚴格的類型匹配, 所以我又不敢用 Haskell 類比..

然後我想問的是, 有了類型推斷, 我們真的是現在寫腳本語言那樣, 然後直接能編譯到二進位嗎?

聽說有 Pypy 是這麼干, 直接能把 Python 編譯到二進位高效地運行..

但我在想, 這裡邊是否是通過增加了很多限制來達到的?

比如說上邊的語言提到數組賦值會限定類型之類的.. 其實還是有限制的?

類型推斷能帶來什麼程度上的改變?


Haskell是靜態類型系統,類型在編譯期都已經確定了。但Python之類的動態語言無法做到精確的類型推斷。就像:

def func():
if random.random()&<0.5: return 0 else: return "a string"

你說這個函數返回值是什麼類型?(如果你認為類型是Object就當我沒說)

PyPy並沒有把代碼完全編譯成機器碼。它是JIT編譯,經常執行的代碼塊(比如一個循環體),有可能類型不那麼「動態」,才會把它編譯成機器碼加速執行。js V8,Java之類都是這種策略。

————————————————————————

把PyPy和Google的Unladen-Swallow記混了。。。PyPy沒用LLVM


任何語言都可以被編譯到native,和是不是靜態類型沒有一毛錢關係。

靜態類型只是在一些時候可以提升執行效率的一個做法,僅此而已。

Ruby一行代碼的信息量超小的。你寫代碼的人什麼都不說,到執行的時候就知道了,解釋器也很為難啊。


現在這堆動態語言都有 eval,從理論上斷絕了編譯成不帶解釋器的二進位代碼的可能

而如果沒有 eval 這樣的東西,那麼「腳本語言」是可以編譯成機器代碼的。最原始的辦法就是做這樣的翻譯:

# py
def func():
if random.random()&<0.5: return 0 else: return "a string"

// C
// 感謝評論告訴我 python 中「值」這個 tagged union 的名字…
pyObject func(){
if(lt(invoke_method(random, "random"), val_number(0.5))) {
return val_number(0);
} else {
return val_string("a string");
}
}

當然,後者沒做任何優化……


要看你說的二進位代碼是指Native Code還是Bytecode

把Ruby編譯為Native代碼必然還是要一定的約束才行。

最重要的就是要在編譯期確定其類型(顯式聲明也好,類型推斷也好),否則必然不能夠脫離一個運行時環境。

如果說說編譯為Bytecode,當然現在的Ruby實現也有,也是要依賴一個運行時環境(YARV / LLVM 啥的)。PyPy的做法也是如此。

同樣,許多高級一些的系統編程語言也是需要依賴一定的運行時(因為GC之類高級特性),比如Go和D語言,雖然兩者都是靜態類型,都是顯式的編譯為Native文件。

Crystal的做法應該沒有脫離上面幾種情況。

至於類型推斷的好處,一方面可以簡化顯式類型聲明帶來的一些多餘的操作(雖然很多時候這些東西是很有必要的),另一方面,又不會失卻靜態類型和強類型的安全性和高效,所以這基本是一個追求效率的語言現常常採取的做法。

參考:

Type inference

類型和程序設計語言 (豆瓣)


Ruby是動態類型語言,想要進行精準的類型推斷是不可能的。王垠的PySonar做到了推導所有可能的類型,據說是很先進的成果了。

Haskell是靜態類型語言,當然可以進行精確的類型推斷了。

Python並不能想C那樣「原生態」的編譯成可執行文件,都是額外加了一層解釋器的邏輯,本質上沒什麼改變。


就算是動態語言,也是可以編譯成native執行。感覺上面的幾個答案字裡行間也透露出了動態語言不能編譯成native執行這個意思,這是不對的

實際上一個語言的實現是否是編譯成native執行這個事,完全是看作者意願和實際需求來的。


推薦閱讀:

D 編程語言是用於開發的絕佳語言的 5 個理由
阻擋你學會 Haskell 最大的兩個問題是什麼?
面向對象編程的下一階段是什麼?
運算符的優先順序、結合性、求值次序,新舊規則比較的解釋有點看不懂,求解釋?

TAG:編程語言 | Ruby | Haskell | 編譯原理 |