2013-04-29 73 views
1

不得不爲一個項目學習javascript,千萬不要錯過! (雖然我認識到它的使用和規模影響,不僅在臺式機上,而且在服務器和移動空間中也是如此)。在許多文獻中重複的事情之一是「不污染全球namespace」和過多的reasonablereasonsScheme命名空間使用約定。與Javascript相比

據我瞭解,方案是lisp-1reason,像thismore

  1. 什麼是計劃中的全局變量約定?
  2. 在使用全局變量和局部變量時是否有任何缺陷需要注意? (特別是那些本身不會拋出錯誤但可能導致不可見錯誤的錯誤)。
+0

@ [Will Ness](http://stackoverflow.com/users/849891/willness )哈哈忘記了那些無言者?你有什麼經驗?我真的不想從一開始就弄錯我的代碼。 – usernvk 2013-04-29 18:28:07

+4

@WillNess:'* foo *'約定不適用於全局變量,它適用於特殊變量,因爲如果名稱用於某個地方的本地詞法作用域中,那麼特殊聲明對代碼可能是災難性的。一些Schemers也將它用於具有特定狀態的全局變量,如自定義全局變量。 – 2013-04-30 06:04:31

+0

@EliBarzilay感謝您的澄清。 :) – 2013-04-30 08:12:34

回答

3

關於第一個問題 - 有在計劃全局沒有單一的慣例。有些人使用*foo*(因爲與CL中的命名約定不同,正如我在上面的評論中所說的),有些人使用CAPITALS(在大小寫敏感的Schemes中),但都不夠流行以至於不被視爲慣例。

第二個問題更爲微妙。是的,有一個單一的全局命名空間的缺陷。這些錯誤與Javascript 中的錯誤相同,如Common Lisp中所述:加載隨機代碼可能會改變其他代碼的含義 - 因此,如果我要加載兩個庫,並且都定義了一些foo全局函數,那麼這些庫中的一個會打破另一個。這不是一個新問題,並且有各種方式來處理它。

最明顯的做法是避免使用不屬於公共接口的全局變量。因此,例如,而不是

(define helper ...) 
(define foo ...) 

你寫

(define foo 
    (let() 
    (define helper ...) 
    (define foo ...) 
    foo)) 

,如果你在你的界面具有多種功能,你做同樣的事情(例如,用球拍的define-values或使用功能的列表)。請注意,這具有雙重保護:helper之類的內部事物不會​​污染全局命名空間,因此它不會破壞其他代碼 - 而定義helper的其他代碼不會破壞此代碼。這也包括foo,以防遞歸調用。

當你想要快速編寫這樣的代碼時,一個相關的黑客就是編寫這樣的代碼:在第一個版本中,Scheme編譯器無法將foo編譯成快速循環,因爲綁定稍後可能會發生變化,但使用第二個版本優化是可能的。

當您沒有模塊系統時,另一種防禦性編程形式是獲取對您的代碼非常重要的值。例如,你可以這樣做:

(define foo 
    (let ([+ +] [- -] [* *] [/ /] ... more ...) 
    (define helper ...) 
    (define foo ...) 
    foo)) 

現在的代碼有自己的不可變綁定的算術運算,它保護它免受變化在未來這些操作,並允許算術的安全優化,在此代碼。

所有這些都是一種窮人模塊系統的約定,這與Javascript中常見的(function() { ... })()類似。但是,當然,一個合適的模塊系統使得這更方便,更好地運行。較新的Javascript版本和較新的Scheme版本都面臨着某種模塊系統的這個問題,而在Scheme中,趨勢是僅使用模塊並避免load爲不可靠的黑客攻擊。因爲你可能會覆蓋全局變量函數從其他文件覆蓋。解決方法是與CL的包系統,它可以採取行動作爲一種弱模塊系統,它的弱點在於它給你提供了單獨命名空間的便利,但是命名空間仍然是全局的,這意味着優化仍然非常困難。換句話說,這些命名空間不會給你傳統模塊系統具有「封閉的世界假設」,這意味着編譯器仍然不能假定綁定不會改變。)

+0

@ [EliBarzilay](http://stackoverflow.com/users/128595/eli-barzilay)我期待當我完成[簡單](http://www.eecs.berkeley.edu/~bh/ss -toc2.html)[Scheme](http://www.eecs.berkeley.edu/~bh/downloads/simply/)和[The Schemer](http://www.ccs.neu.edu/home/ matthias/BTLS /)我會理解更多,但是從我做的,我前兩天看到的一些代碼'(let([+ +] [ - - ] [* *] [/ /] ....'是有意義的現在,關於陷阱和解決方法的細節,簡直無價! – usernvk 2013-04-30 13:06:56

+0

是的,這種黑客往往會謎題新手...... – 2013-04-30 21:32:14

2

您可以在Scheme中使用'lisp-2';只需將所有功能與一組一致的字符配合使用即可。您可以首先重新綁定RnRS中定義的函數。就像這樣:

(define this-is-a-scheme-function-+ +) 
(define this-is-a-scheme-function-call-with-current-continuation call-with-current-continuation) 

不過,按照慣例,

(define tiasf-call/cc this-is-a-scheme-function-call-with-current-continuation) 
+0

謝謝!不止回答^^另外,不知道你剛剛說了什麼,也許再過幾個月,當我完成計劃的介紹時。 +1信息是黃金。 – usernvk 2013-04-30 05:07:47