2013-04-29 69 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