eval 之源
(LCTT 譯註:本文標題 「The root of all eval」 影射著名歌曲「The root of all evil」(萬惡之源))
唉,eval
這個函數讓我愛恨交織,而且多半是後者居多。
$ perl -E'my $program = q[say "OH HAI"]; eval $program'
OH HAI
當 eval
函數在 Perl 6 中被重命名為 EVAL
時,我感到有點震驚(這要追溯到 2013 年,在這裡討論規範之後)。我一直沒有從內心接受這樣這樣的做法。雖然這是個很好的意見,但是在這個意見上我似乎或多或少是孤獨的。
理由是「這個函數真的很奇怪,所以我們應該用大寫標記」。就像我們用 BEGIN
和其他 phaser 一樣。使用 BEGIN
和其他 phaser,鼓勵使用大寫,這點我是同意的。phaser 能將程序「脫離正常控制流」。 但是 eval
函數並不能。(LCTT 譯註: 在 Perl 6 當中,phaser 是在一個特定的執行階段中調用的代碼塊。)
其他大寫的地方像是 .WHAT 這樣的東西,它看起來像屬性,但是會在編譯時將代碼變成完全不同的東西。因為這發生在常規情況之外,因此大寫甚至是被鼓勵的。
eval
歸根到底是另一個函數。是的,這是一個潛在存在大量副作用的函數。但是那麼多的標準函數都有大量的副作用。(舉幾個例子:shell
、 die
、 exit
)你沒看到有人呼籲將它們大寫。
我猜有人會爭論說 eval
是非常特別的,因為它以正常函數所沒有的方式鉤到編譯器和運行時裡面。(這也是 TimToady 在將該函數重命名的提交中的提交消息中解釋的。)這是一個來自實現細節的爭論,然而這並不令人滿意。這也同樣適用與剛才提到的那些小寫函數。
雪上加霜的是,更名後 EVAL
也更難於使用:
$ perl6 -e'my $program = q[say "OH HAI"]; EVAL $program'
===SORRY!=== Error while compiling -e
EVAL is a very dangerous function!!! (use the MONKEY-SEE-NO-EVAL pragma to override this error,
but only if you're VERY sure your data contains no injection attacks)
at -e:1
------> program = q[say "OH HAI"]; EVAL $program⏏<EOL>
$ perl6 -e'use MONKEY-SEE-NO-EVAL; my $program = q[say "OH HAI"]; EVAL $program'
OH HAI
首先,注入攻擊是一個真實的問題,並不是一個笑話。我們應該互相教育對方和新手。
其次,這個錯誤消息("EVAL is a very dangerous function!!!"
)完全是恐嚇多於幫助。我覺得當我們向人們解釋代碼注入的危險時,我們需要冷靜並且切合實際,而不是用三個感嘆號。這個錯誤信息對已經知道什麼是注入攻擊的人來說是有意義的,對於那些不了解這種風險的人員,它沒有提供任何提示或線索。
(Perl 6 社區並不是唯一對 eval
歇斯底里的,昨天我偶然發現了一個 StackOverflow 主題,關於如何將一個有類型名稱的字元串轉換為 JavaScript 中的相應構造函數,一些人不幸地提出了用 eval
,而其他人立即集結起來指出這是多麼不負責任,就像膝跳反射那樣——「因為 eval 是壞的」)。
第三,「MOKNEY-SEE-NO-EVAL」。拜託,我們能不能不要這樣……汗,啟用一個核彈級的函數時,就像是猴子般的隨機引用和輕率的嘗試,我奇怪地發現啟用 EVAL
函數的是一個稱為 NO-EVAL
的東西。這並不符合「 最少驚喜 」原則。
不管怎樣,有一天,我意識到我可以同時解決全大寫名字問題和該指令的必要問題:
$ perl6 -e'my &eval = &EVAL; my $program = q[say "OH HAI"]; eval $program'
OH HAI
我很高興我能想到這點子並記錄下來。顯然我們把它改回了舊名字,這個非常危險的功能(!!!
)就又好了。 耶!
via: http://strangelyconsistent.org/blog/the-root-of-all-eval
作者:Carl Mäsak 譯者:geekpi 校對:wxy
本文轉載來自 Linux 中國: https://github.com/Linux-CN/archive