News for hackers. Stuff that matters.
Re:Contracts For CoffeeScript by mobileman on Monday August 29, 2011 @08:42PM (#2939633)
This is just static types
Re:Contracts For CoffeeScript by jashkenas on Monday August 29, 2011 @08:44PM (#2939638)
Not quite.

    isEven = (x) -> 
      x % 2 is 0

    f :: (!isOdd) -> !isEven
    f = (x) -> ...
Re:Contracts For CoffeeScript by jvoorhis on Monday August 29, 2011 @08:47PM (#2939646)
Not hardly. The runtime can detect that a function invocation violates a post-condition only after all of that function's side-effects have been run.
Re:Contracts For CoffeeScript by bitsai on Monday August 29, 2011 @09:48PM (#2939785)
I believe jashkenas' example defines both a pre-condition and a post-condition, specifying that f accepts only odd numbers and returns only even numbers ('!' here is the operator for new contract, rather than logical negation). If f is called with anything other than an odd number, an error will be thrown right away, before the body of the function is run.
Re:Contracts For CoffeeScript by 6ren on Tuesday August 30, 2011 @12:28AM (#2940110)
Those '!'s are really confusing. From the example in the submission:

  isEven = (x) -> x % 2 is 0
  isOdd = (x) -> x % 2 isnt 0

  addEvens :: (!isEven) -> !isOdd
  addEvens = (x) -> x + 1
I am guessing that both '!'s define a new contract - and also guessing that coffeescript does not actually have a '!' operator for logical negation. So that addEvens simply takes an even number and returns an odd number.

I find it confusing that the different syntax highlighting of the two '!' suggests (wrongly) that they have different meanings. Also, logical negation is something often used with isOdd/isEven functions.

Re:Contracts For CoffeeScript by chc on Tuesday August 30, 2011 @12:52AM (#2940163)
CoffeeScript does allow ! for negation, but contracts have their own syntax and semantics separate from the rest of the language. It's a little confusing initially, but I suppose there aren't a lot of good operators left. There are a lot of similar convenient inconsistencies that people hardly notice once they sink in:

• Indentation shifts mean different things depending on context (could mean we're doing an object literal, could mean we're defining a function, could mean we're entering a loop, etc.)

• Looping through arrays uses "in" while looping through everything else uses "of"

• Array and object literal syntax might create arrays and objects or define variables depending on which side of the equals sign you're reading

Re:Contracts For CoffeeScript by rbranson on Tuesday August 30, 2011 @10:45AM (#2941640)
How is this different than creating an OddNumber and EvenNumber type that check their input in the constructor at run-time? That is the point of a type system.

Scala can make this really transparent and concise using an abstract class to implement most of the plumbing and implicit type conversion to automatically convert the contract enforcement types to and from the native types.

   case class EvenNumber(val x: Int) extends Contract[Int] {
      require(x % 2 != 0)
   }
Re:Contracts For CoffeeScript by gfodor on Monday August 29, 2011 @09:01PM (#2939682)
What's your point?
Re:Contracts For CoffeeScript by jvoorhis on Monday August 29, 2011 @09:38PM (#2939768)
That while this looks like a good extension to CoffeeScript, it's unfortunate that Haskell's type syntax was appropriated when the relationship between contracts and types is tenuous at best.

There are good uses for static type checkers and design by contract, but neither one is a good substitute for the other.

Re:Contracts For CoffeeScript by disnet on Monday August 29, 2011 @11:45PM (#2940031)
I'm not sure that the relationship between types and contracts is all that tenuous.

They both work to enforce program invariants and there's a large overlap in the invariants they can express. Usually contracts are checked dynamically (as in contracts.coffee) but this is not a hard requirement (for example .net's code contracts can be statically checked [1]).

http://msdn.microsoft.com/en-us/devlabs/dd491992

Re:Contracts For CoffeeScript by gfodor on Monday August 29, 2011 @10:50PM (#2939924)
So you're upset about the syntax? Seems like an odd complaint.
Re:Contracts For CoffeeScript by bilalhusain on Monday August 29, 2011 @09:33PM (#2939755)
it doesn't conflict with the prototype operator?
Re:Contracts For CoffeeScript by dherman on Tuesday August 30, 2011 @12:57AM (#2940178)
It's a grammar hack, but IMO an intuitive one: if you have whitespace around the ::, it's a contract annotation; otherwise it's the prototype operator.

To quote Jeremy Ashkenas's JSConf talk on forking CoffeeScript: "when in doubt, cheat." ;-P

Re:Contracts For CoffeeScript by chucknthem on Monday August 29, 2011 @08:47PM (#2939645)
No, if you read the article, contracts are enforced at runtime!
Re:Contracts For CoffeeScript by irrelative on Tuesday August 30, 2011 @01:17AM (#2940215)
I feel a little bit crazy because no one else has brought this up yet, but what's the point of declaring types if your errors don't get caught at compile time? If they're going to throw errors at runtime, how is that an improvement over not checking the types?
Re:Contracts For CoffeeScript by disnet on Tuesday August 30, 2011 @01:25AM (#2940233)
Well, CoffeeScript/JavaScript doesn't have a static type system. And to add one would be...hard.

But we would still like to express and enforce some invariants about our code. And we'd like to do it in a more elegant way than constantly writing "if(argument === ...) then ... else ..."

Contracts also allow us to check invariants that might not result in a run-time exception but could lead to the code just being subtly wrong.

Re:Contracts For CoffeeScript by irrelative on Tuesday August 30, 2011 @02:07AM (#2940321)
> Well, CoffeeScript/JavaScript doesn't have a static type system. And to add one would be...hard.

Indeed it would be. That said, CoffeeScript is a compiler of sorts.

> And we'd like to do it in a more elegant way than constantly writing "if(argument === ...) then ... else ..."

This doesn't really seem to solve that problem. It just throws consistent errors if the types don't match. Your code would likely throw its own error if you didn't check the type manually. In my experience, native js errors are as easy or easier to track down that throwing errors yourself.

> Contracts also allow us to check invariants that might not result in a run-time exception but could lead to the code just being subtly wrong.

Ah, ok. That makes more sense. They're like python decorators, only single purpose.

Re:Contracts For CoffeeScript by disnet on Tuesday August 30, 2011 @02:30AM (#2940366)
> Indeed it would be. That said, CoffeeScript is a compiler of sorts.

The fact that we have a compiler doesn't give us all that much. Adding types to a dynamic language (where things can be monkey patched, evaled, and just generally mutated willy-nilly) is a hard problem (not impossible but definitely research [1 and 2 to start, but much more]).

>> And we'd like to do it in a more elegant way than constantly writing "if(argument === ...) then ... else ..."

> This doesn't really seem to solve that problem.

It solves the problem of elegance :)

> It just throws consistent errors if the types don't match. Your code would likely throw its own error if you didn't check the type manually. In my experience, native js errors are as easy or easier to track down that throwing errors yourself.

Key word there is likely. Like I mentioned, there are some errors that don't result in a run-time error and we might like to check for those too. As a silly example, consider a binary search tree [3] that you want to keep balanced. If you get the balance wrong, there's no immediate fault (no TypeError/NPE).

> Ah, ok. That makes more sense. They're like python decorators, only single purpose.

I guess you could say that. If we had an expressive enough decorator-like system for CoffeeScript we could probably implement contracts with it. CS doesn't have one of course so path of least resistance is to add the contract language extension directly.

[1] http://ecee.colorado.edu/~siek/blame-forall-2011.pdf

[2] http://dl.acm.org/citation.cfm?id=1863561

[3] https://github.com/disnet/contracts.coffee/blob/master/test/...