views:

123

answers:

5

With the growth of dynamically typed languages, as they give us more flexibility, there is the very likely probability that people will write programs that go beyond what the specification allows.

My thinking was influenced by this question, when I read the answer by bobince: http://stackoverflow.com/questions/1777705/a-question-about-javascripts-slice-and-splice-methods/1777773#1777773

The basic thought is that splice, in Javascript, is specified to be used in only certain situations, but, it can be used in others, and there is nothing that the language can do to stop it, as the language is designed to be extremely flexible.

Unless someone reads through the specification, and decides to adhere to it, I am fairly certain that there are many such violations occuring.

Is this a problem, or a natural extension of writing such flexible languages? Or should we expect tools like JSLint to help be the specification police?

I liked one answer in this question, that the implementation of python is the specification. I am curious if that is actually closer to the truth for these types of languages, that basically, if the language allows you to do something then it is in the specification. http://stackoverflow.com/questions/1094961/is-there-a-python-language-specification

UPDATE:

After reading a couple of comments, I thought I would check the splice method in the spec and this is what I found, at the bottom of pg 104, http://www.mozilla.org/js/language/E262-3.pdf, so it appears that I can use splice on the array of children without violating the spec. I just don't want people to get bogged down in my example, but hopefully to consider the question.

    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.

UPDATE 2: I am not interested in this being about javascript, but language flexibility and specs. For example, I expect that the Java spec specifies you can't put code into an interface, but using AspectJ I do that frequently. This is probably a violation, but the writers didn't predict AOP and the tool was flexible enough to be bent for this use, just as the JVM is also flexible enough for Scala and Clojure.

A: 

I think that this sort of flexibility is an advantage as long as your methods are designed around well defined interfaces rather than some artificial external "type" metadata. Most of the array functions only expect an object with a length property. The fact that they can all be applied generically to lots of different kinds of objects is a boon for code reuse.

The goal of any high level language design should be to reduce the amount of code that needs to be written in order to get stuff done- without harming readability too much. The more code that has to be written, the more bugs get introduced. Restrictive type systems can be, (if not well designed), a pervasive lie at worst, a premature optimisation at best. I don't think overly restrictive type systems aid in writing correct programs. The reason being that the type is merely an assertion, not necessarily based on evidence.

By contrast, the array methods examine their input values to determine whether they have what they need to perform their function. This is duck typing, and I believe that this is more scientific and "correct", and it results in more reusable code, which is what you want. You don't want a method rejecting your inputs because they don't have their papers in order. That's communism.

Breton
A: 

I'm not sure to what degree this kind of thing is due to the dynamic nature of the language, as opposed to a loosely-defined spec. A classic example of something similar, but for a non-dynamic, is Duff's device, which when it first emerged appeared to defy the language specification, prompting tests to see whether it really worked in all the C compilers that could be found.

martin clayton
A: 

It seems to me that the original question is a bit of a non-sequitor. If the specification explicitly allows a particular behavior (as MUST, MAY, SHALL or SHOULD) then anything compiler/interpreter that allows/implements the behavior is, by definition, compliant with the language. This would seem to be the situation proposed by the OP in the comments section - the JavaScript specification supposedly* says that the function in question MAY be used in different situations, and thus it is explicitly allowed.

If, on the other hand, a compiler/interpreter implements or allows behavior that is expressly forbidden by a specification, then the compiler/interpreter is, by definition, operating outside the specification.

There is yet a third scenario, and an associated, well defined, term for those situations where the specification does not define a behavior: undefined. If the specification does not actually specify a behavior given a particular situation, then the behavior is undefined, and may be handled either intentionally or unintentionally by the compiler/interpreter. It is then the responsibility of the developer to realize that the behavior is not part of the specification, and, should s/he choose to leverage the behavior, the developer's application is thereby dependent upon the particular implementation. The interpreter/compiler providing that implementation is under no obligation to maintain the officially undefined behavior beyond backwards compatibility and whatever commitments the producer may make. Furthermore, a later iteration of the language specification may define the previously undefined behavior, making the compiler/interpreter either (a) non-compliant with the new iteration, or (b) come out with a new patch/version to become compliant, thereby breaking older versions.

* "supposedly" because I have not seen the spec, myself. I go by the statements made, above.

atk
The OP did not mention Java.
Nosredna
In Java, code cannot be in an interface. But, using AspectJ I often put code into interfaces, which violates the spec, but this is due to the flexibility of Java and not to a weakness in the specification or compiler, as the writers didn't predict AOP, so the tool was bent to support AOP.
James Black
@Nosredna: Apologies for the typo - he said "JavaScript" not "Java". I'll correct my answer, momentarially.
atk
@James Black: Based on your updates, I suspect my interpretation of the original question was off. I had originally thought that you were claiming that a spec-compliant implementation could be non-compliant. Now I think think that you're asking if it's a good or a bad thing. I don't believe that there's anything inherently good or bad about being in violation of the specification, or that a compiler or interpreter allowing violations of a spec is necessarily bad. One must simply be very careful when violating a spec, and be aware of the risks one accepts.
atk
+1  A: 

Whether a language is statically or dynamically typed is really a tiny part of the issue here: a statically typed one may make it marginally easier for code to enforce its specs, but marginally is the key word here. Only "design by contract" -- a language letting you explicitly state preconditions, postconditions and invariants, and enforcing them -- can help ward you against users of your libraries empirically discovering what exactly the library will let them get away with, and taking advantage of those discoveries to go beyond your design intentions (possibly constraining your future freedom in changing the design or its implementation). And "design by contract" is not supported in mainstream languages -- Eiffel is the closest to that, and few would call it "mainstream" nowadays -- presumably because its costs (mostly, inevitably, at runtime) don't appear to be justified by its advantages. "Argument x must be a prime number", "method A must have been previously called before method B can be called", "method C cannot be called any more once method D has been called", and so on -- the typical kinds of constraints you'd like to state (and have enforced implicitly, without having to spend substantial programming time and energy checking for them yourself) just don't lend themselves well to be framed in the context of what little a statically typed language's compiler can enforce.

Alex Martelli
Design by contract (preconditions and postconditions with inheritance, including on interfaces; class invariants; and exceptional postconditions) will be supported in .NET 4 on all languages that can handle lambdas. Syntax is verbose and far from perfect, but it's a good start.
Pavel Minaev
@Pavel, good to hear about this, tx, but it remains to be seen: how costly will all those extra checks be, wrt the advantage of strongly constraining users of your library to do things per specs and not per a given implementation? Time will tell! But -- dynamically vs statically typed languages is the least of the issues (several dynamically typed .NET languages, such as IronPython, **do** support `lambda` -- so, Msft willing, they could play at DbC too;-).
Alex Martelli
A: 

I do not think your question really has much to do with dynamic vs. static typing. Really, I can see two cases: on one hand, there are things like Duff's device that martin clayton mentioned; that usage is extremely surprising the first time you see it, but it is explicitly allowed by the semantics of the language. If there is a standard, that kind of idiom may appear in later editions of the standard as a specific example. There is nothing wrong with these; in fact, they can (unless overused) be a great productivity boost.

The other case is that of programming to the implementation. Such a case would be an actual abuse, coming from either ignorance of a standard, or lack of a standard, or having a single implementation, or multiple implementations that have varying semantics. The problem is that code written in this way is at best non-portable between implementations and at worst limits the future development of the language, for fear that adding an optimization or feature would break a major application.

Tommy McGuire
I actually didn't think about the fact that pushing the limits may limit the future growth of a language.
James Black