Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

breaks object equality #57

Open
gregwebs opened this issue Sep 23, 2012 · 6 comments
Open

breaks object equality #57

gregwebs opened this issue Sep 23, 2012 · 6 comments

Comments

@gregwebs
Copy link

This issue seems similar to: #54
An equality test broke for me on the same object but one was wrapped in a contract.

In Chrome, the object normally shows up as:

▶Object

When it has been placed under a contract, I don't see Object.

@disnet
Copy link
Owner

disnet commented Sep 24, 2012

This actually makes sense and is not a bug like #54 (though it might be annoying). If I have

f :: ({}) -> {}
f = (o) -> o

o1 = {}
o2 = f o1

assert (o1 !== o2)

A proxied/contracted object is not the same as the original object. That's just how the proxy system works, you are not allowed to override equality.

@gregwebs
Copy link
Author

So the proxy spec says that proxy objects have their own identity. That is fine, however proxies are an implementation detail of contracts.coffee. This is very annoying: I have code that works, but when I place a contract on a function it no longer works. If there is a way for contracts not to have side effects on the code, we should figure it out. Ideas:

  • integrate with the new coffeescript redux compiler (or sweet.js :)) to unwrap a proxy before equality checks, or otherwise change how == works
  • provide an alternative equality checking technique for contracts.coffee
  • weaken the capabilities of contracts just to assert when the function is invoked and exited

@disnet
Copy link
Owner

disnet commented Sep 24, 2012

Good point.

So probably the best bet is to weaken the kinds of checks that object contracts do. Humm...perhaps we could have two types of object contracts, one that just does flat checks and doesn't wrap its object and another that wraps its object breaking equality but protecting invariants. Perhaps by default obj contracts nested in fun contracts are the first order check and if you specifically wrap an object in a contract you get the wrapped version?

@gregwebs
Copy link
Author

I am not sure what the default should be. I lean towards no side effects by default, but I haven't noticed this before. I think this is because I hardly ever perform object equality. Instead, I normally check for equality of members of objects.

Your suggestion sounds appealing (if I understand it correctly), but risks inconsistent behavior that requires documentation and not being entirely satisfactory. I think we need to consider adding a syntax that lets the user control it at least when defining a named object contract.

@disnet
Copy link
Owner

disnet commented Sep 28, 2012

Yeah, I agree; we need distinct syntax for the different behaviors.

Some bikeshedding: have the current { ... } syntax mean don't break equality (first order checks, no wrapping) and add obj{ ... } mean wrap?

# only checks that the param has the id prop
f :: ({id: Str}) -> Str
f = ...

# wraps the param
f :: (obj{ id: Str }) -> Str
f = ...

# double curlies?
f :: ({{ id: Str }}) -> Str

# shorten obj to o?
f :: (o{ id: Str }) -> Str

@gregwebs
Copy link
Author

if I see obj I am just thinking that the contract is for an object. something that gets at the proxy meaning more might be nicer.

f :: (proxy{ id: Str }) -> Str
f :: ( P{ id: Str } ) -> Str

# a special symbol?
f :: ( ^{id: Str} ) -> Str

# like an array it just does simple checks
f :: ( [ id: Str ] ) -> Str

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants