編程語言有類型推斷的話,我們就直接寫 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 最大的兩個問題是什麼?
※面向對象編程的下一階段是什麼?
※運算符的優先順序、結合性、求值次序,新舊規則比較的解釋有點看不懂,求解釋?