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

Add definitions for == and != #21

Merged
merged 1 commit into from Feb 17, 2015
Merged

Add definitions for == and != #21

merged 1 commit into from Feb 17, 2015

Conversation

gfontenot
Copy link
Contributor

For Result types, equality should be defined based on the equality of the contained types. This adds the logic for == (flipped for !=) to allow you to compare two instances of Result.

I saw a mention from @rnapier on the mailing list about removing this operator implementation, but I don't fully understand why. I think this is a totally reasonable thing to have, and I was actually a little surprised when it didn't exist.

For Result types, equality should be defined based on the equality of
the contained types. This adds the logic for == (flipped for !=) to
allow you to compare two instances of Result.
@rnapier
Copy link
Contributor

rnapier commented Jan 22, 2015

Do you have a live example of where this has come up? I think the question
remains: are failures equal if they have different specifics of the error?
Consider two NSError objects with different userInfo dictionaries (or one
has a dictionary and the other doesn't). Should those be equal? Do I have
to have to make my error type Equatable in order to make Result Equatable?

So far result equality has never come in my code, so I'd like to see some
live problems that demonstrate which answer to that question makes sense.

@gfontenot
Copy link
Contributor Author

Do you have a live example of where this has come up?

Like you, I needed it in my tests. I haven't needed it in production yet, but I could see it potentially being useful in the future. I also think it's hard to say that it won't ever be useful. The implementation is light weight enough that it doesn't seem like it's worth avoiding.

I think the question remains: are failures equal if they have different specifics of the error? Consider two NSError objects with different userInfo dictionaries (or one has a dictionary and the other doesn't). Should those be equal?

I don't think that's LlamaKit's responsibility at all. NSError should be defining its own equality semantics. Result should just be passing the buck here.

Do I have to have to make my error type Equatable in order to make Result Equatable?

You would need to make your error type Equatable if you want to use it with == or !=, yes. But since we aren't forcing Equatable on Result itself, I don't see that as a huge deal. I think it's totally reasonable that if you try to compare two results for equality, the contents of the results should also be able to be compared for equality.

@rnapier
Copy link
Contributor

rnapier commented Jan 22, 2015

Once we set a semantic, it's very hard to change it later. I'd rather wait for a live need for the operator rather than forcing it upon people in a way that may be undesirable. I can imagine callers wanting all errors to be equal just as much as I can imagine they want them not to be equal. I can easily see bugs that would come about by callers not considering the error case in their equality checks or being surprised about the equality semantic.

Callers can always define their own if they want to. The fact that no one so far has come up with a non-test need for it is, I believe, a strong argument to leave it out for now. LlamaKit very intentionally has a minimal footprint. My criteria is "it's necessary for good code" rather than "it's easy to implement." If it's useful, I expect it to pop up in a framework as large as ReactiveCocoa or in Brad Larson's work. Even after writing significant production code with Result, his didn't wind up having an ==.

https://github.com/SonoPlot/SerialPortExample-Swift/blob/master/SerialPortExample-Swift/Result.swift

@jspahrsummers @BradLarson Any input from your use? It's never come up for me. Is its lack likely to cause confusion (people implementing it their own incompatible ways?) I find by the time I care about values, I'm always in a switch statement.

@BradLarson
Copy link

@rnapier - The only times that I can see needing an equality check for an entire Result type is in tests. In production code, you're going to be either operating against the encapsulated .Success value or handling the error case. You're going to know what half you want at a specific point in code.

In unit tests, you'll want different messages for the three possible cases of Success / Failure mismatch, right Success / Failure case but wrong encapsulated value, and complete match. A simple pass / fail on Result equality isn't that helpful in diagnosing test failures.

To that end, I created the assertResultsAreEqual() function for use in my XCTestCases:

https://github.com/SonoPlot/SerialPortExample-Swift/blob/master/SerialPortExample-SwiftTests/Result_Tests.swift

I've overloaded it to handle the various cases where the boxed success and error types themselves do or do not comply to the Equatable protocol (as well as a few specific cases for testing equality of byte arrays and Voids contained as values). This serves all my unit testing needs perfectly, and provides far more usable information in a test failure than a simple equality could. With one line, I can test and report on the various match / mismatches between two Results.

Again, beyond testing, I see little need in my production code for an equality operator on Results themselves.

@jspahrsummers
Copy link
Contributor

IMO any type that has map should also distribute equality. It's the same principle behind both.

rnapier added a commit that referenced this pull request Feb 17, 2015
Add definitions for == and !=
@rnapier rnapier merged commit c6e5b50 into LlamaKit:master Feb 17, 2015
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

Successfully merging this pull request may close these issues.

None yet

4 participants