随着动态类型语言的增长,因为它们为我们提供了更大的灵活性,人们很可能会编写超出规范允许范围的程序。
当我通过bobince阅读答案时,我的想法受到了这个问题的影响: A question about JavaScript's slice and splice methods
基本思想是Javascript中的splice
被指定仅在某些情况下使用,但是,它可以在其他情况下使用,并且语言无法阻止它,如该语言设计非常灵活。
除非有人阅读规范并决定遵守规范,否则我相当确定存在许多此类违规行为。
这是一个问题,还是编写这种灵活语言的自然延伸?或者我们是否应该期望像JSLint这样的工具帮助成为规范警察?
我在这个问题中喜欢一个答案,即python的实现是规范。我很好奇,如果这实际上更接近这些类型的语言的真相,基本上,如果语言允许你做某事,那么它在规范中。 Is there a Python language specification?
更新:
在阅读了几条评论之后,我想我会检查规范中的拼接方法,这就是我在pg 104底部http://www.mozilla.org/js/language/E262-3.pdf找到的,所以看来我可以使用拼接一系列没有违反规范的孩子。我只是不希望人们在我的例子中陷入困境,但希望能够考虑这个问题。
The splice function is intentionally generic; it does not require that its this value be an Array object.
Therefore it can be transferred to other kinds of objects for use as a method. Whether the splice function
can be applied successfully to a host object is implementation-dependent.
更新2: 我对这个关于javascript,但语言灵活性和规格不感兴趣。例如,我希望Java规范指定您不能将代码放入接口,但使用AspectJ我经常这样做。这可能是违规行为,但是作者并没有预测AOP,而且该工具非常灵活,可以适应这种用途,就像JVM对Scala和Clojure一样灵活。
答案 0 :(得分:1)
语言是静态还是动态输入实际上只是问题的一小部分:静态类型的语言可能会使代码更容易执行其规范,但略微是关键词这里。只有“按合同设计” - 一种让你明确说明前置条件,后置条件和不变量,以及强制执行的语言 - 可以帮助你防止图书馆的用户凭经验发现图书馆会让他们到底是什么侥幸逃脱,利用这些发现超越了你的设计意图(可能限制你未来改变设计或实施的自由)。主流语言并不支持“按合同设计” - 埃菲尔是最接近它的,现在很少有人称之为“主流” - 大概是因为它的成本(大多数,不可避免地,在运行时)似乎不是以其优势为理由。 “参数x必须是素数”,“方法A必须先调用才能调用方法B”,“方法C一旦调用方法D就不能再调用”,依此类推 - 典型的种类你强烈要求喜欢的约束(并且已经隐式执行,而不必花费大量的编程时间和自己的能量检查)只是不适合在什么背景下构建框架很少有静态类型语言的编译器可以强制执行。
答案 1 :(得分:0)
我认为只要您的方法是围绕定义良好的接口设计而不是某些人为的外部“类型”元数据,这种灵活性就是一种优势。大多数数组函数只期望具有length属性的对象。事实上,它们都可以一般地应用于许多不同类型的对象,这对于代码重用是一个福音。
任何高级语言设计的目标应该是减少需要编写的代码量以完成工作 - 而不会过多地损害可读性。必须编写的代码越多,引入的错误就越多。限制型系统可以(如果设计不当),在最坏情况下普遍存在,最好是过早优化。我不认为过度限制型系统有助于编写正确的程序。原因是该类型仅仅是一种断言,不一定基于证据。
相比之下,数组方法检查它们的输入值,以确定它们是否具有执行其功能所需的功能。这是鸭子打字,我相信这更科学和“正确”,它会产生更多可重复使用的代码,这就是你想要的。您不希望方法拒绝您的输入,因为他们没有按顺序排列论文。这是共产主义。
答案 2 :(得分:0)
在我看来,原来的问题有点像非选票。如果规范明确允许特定行为(如MUST,MAY,SHALL或SHOULD),那么根据定义,允许/实现该行为的任何编译器/解释器都符合该语言。这似乎是OP在评论部分提出的情况 - 据说JavaScript规范*表示有问题的函数可以在不同的情况下使用,因此明确允许。
另一方面,如果编译器/解释器实现或允许规范明确禁止的行为,那么根据定义,编译器/解释器在规范之外运行。
还有第三种情况,以及相关的,定义明确的术语,用于规范未定义行为的情况:未定义。如果规范实际上没有指定给定特定情况的行为,则行为是未定义的,并且可以由编译器/解释器有意或无意地处理。然后,开发人员有责任认识到该行为不是规范的一部分,并且,如果他/她选择利用该行为,则开发人员的应用程序因此依赖于特定的实现。提供该实现的解释器/编译器没有义务维持正式未定义的行为,超出向后兼容性以及生产者可能作出的任何承诺。此外,语言规范的后续迭代可以定义先前未定义的行为,使得编译器/解释器(a)不符合新的迭代,或者(b)出现新的补丁/版本以变得顺从,从而打破旧版本。
*“应该”因为我自己没有看过规格。我按照上面的陈述进行讨论。
答案 3 :(得分:0)
我不认为你的问题与动态与静态类型有很大关系。真的,我可以看到两个案例:一方面,有像马丁克莱顿提到的达夫设备;第一次看到它时,这种用法非常令人惊讶,但语言的语义明确允许它。如果有标准,那么这种习语可能会出现在标准的后续版本中作为一个具体的例子。这些都没有错;事实上,他们可以(除非过度使用)提高生产力。
另一种情况是对实现进行编程。这样的情况将实际上是滥用,来自对标准的无知,或缺乏标准,或具有单个实现,或具有不同语义的多个实现。问题是以这种方式编写的代码在实现之间最多是不可移植的,并且最坏的限制了语言的未来发展,因为担心添加优化或功能会破坏主要应用程序。