標籤:

eval 之源

(LCTT 譯註:本文標題 「The root of all eval」 影射著名歌曲「The root of all evil」(萬惡之源))

唉,eval 這個函數讓我愛恨交織,而且多半是後者居多。

$ perl -Emy $program = q[say "OH HAI"]; eval $programnOH HAIn

當 eval 函數在 Perl 6 中被重命名為 EVAL 時,我感到有點震驚(這要追溯到 2013 年,在這裡討論規範之後)。我一直沒有從內心接受這樣這樣的做法。雖然這是個很好的意見,但是在這個意見上我似乎或多或少是孤獨的。

理由是「這個函數真的很奇怪,所以我們應該用大寫標記」。就像我們用 BEGIN 和其他 phaser 一樣。使用 BEGIN 和其他 phaser,鼓勵使用大寫,這點我是同意的。phaser 能將程序「脫離正常控制流」。 但是 eval 函數並不能。(LCTT 譯註: 在 Perl 6 當中,phaser 是在一個特定的執行階段中調用的代碼塊。)

其他大寫的地方像是 .WHAT 這樣的東西,它看起來像屬性,但是會在編譯時將代碼變成完全不同的東西。因為這發生在常規情況之外,因此大寫甚至是被鼓勵的。

eval 歸根到底是另一個函數。是的,這是一個潛在存在大量副作用的函數。但是那麼多的標準函數都有大量的副作用。(舉幾個例子:shell、 die、 exit)你沒看到有人呼籲將它們大寫。

我猜有人會爭論說 eval 是非常特別的,因為它以正常函數所沒有的方式鉤到編譯器和運行時裡面。(這也是 TimToady 在將該函數重命名的提交中的提交消息中解釋的。)這是一個來自實現細節的爭論,然而這並不令人滿意。這也同樣適用與剛才提到的那些小寫函數。

雪上加霜的是,更名後 EVAL 也更難於使用:

$ perl6 -emy $program = q[say "OH HAI"]; EVAL $programn===SORRY!=== Error while compiling -enEVAL is a very dangerous function!!! (use the MONKEY-SEE-NO-EVAL pragma to override this error,nbut only if youre VERY sure your data contains no injection attacks)nat -e:1n------> program = q[say "OH HAI"]; EVAL $program?<EOL>n$ perl6 -euse MONKEY-SEE-NO-EVAL; my $program = q[say "OH HAI"]; EVAL $programnOH HAIn

首先,注入攻擊是一個真實的問題,並不是一個笑話。我們應該互相教育對方和新手。

其次,這個錯誤消息("EVAL is a very dangerous function!!!")完全是恐嚇多於幫助。我覺得當我們向人們解釋代碼注入的危險時,我們需要冷靜並且切合實際,而不是用三個感嘆號。這個錯誤信息對已經知道什麼是注入攻擊的人來說是有意義的,對於那些不了解這種風險的人員,它沒有提供任何提示或線索。

(Perl 6 社區並不是唯一對 eval 歇斯底里的,昨天我偶然發現了一個 StackOverflow 主題,關於如何將一個有類型名稱的字元串轉換為 JavaScript 中的相應構造函數,一些人不幸地提出了用 eval,而其他人立即集結起來指出這是多麼不負責任,就像膝跳反射那樣——「因為 eval 是壞的」)。

第三,「MOKNEY-SEE-NO-EVAL」。拜託,我們能不能不要這樣……汗,啟用一個核彈級的函數時,就像是猴子般的隨機引用和輕率的嘗試,我奇怪地發現啟用 EVAL 函數的是一個稱為 NO-EVAL 的東西。這並不符合「最少驚喜Least Surprise」原則。

不管怎樣,有一天,我意識到我可以同時解決全大寫名字問題和該指令的必要問題:

$ perl6 -emy &eval = &EVAL; my $program = q[say "OH HAI"]; eval $programnOH HAIn

我很高興我能想到這點子並記錄下來。顯然我們把它改回了舊名字,這個非常危險的功能(!!!)就又好了。 耶!

via: The root of all eval

作者:Carl M?sak 譯者:geekpi 校對:wxy

本文由 LCTT 原創編譯,Linux中國 榮譽推出

推薦閱讀:

邏輯表達式的短路是如何實現的?
for 循環為什麼不支持小數?
Scala以cascade的方式調用函數有什麼不妥嗎?
遊戲的數值系統的實現和演化
電腦語言「0,1」的蘊涵的數理邏輯知識 到底是什麼樣的?如何後天將其與思維模式結合?

TAG:Perl | eval | 编程 |