-
Notifications
You must be signed in to change notification settings - Fork 10.4k
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
Implement tuple comparison operators #408
Conversation
Proposal has not been accepted yet, so this should be marked as pending. I'm just submitting it now to make it available if anyone wants to look at it. |
Thanks @kballard ! Marked pending as requested. |
// all the tuple types use the same basic implementation for the operators | ||
// so testing any arity tests them all | ||
|
||
func testEquality<A: Equatable, B: Equatable, C: Equatable>( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the standard library code, we put spaces on both sides of the colon when it represents an 'is-a' relationship (in generic constraints, in inheritance and protocol implementation clauses etc.)
I would recommend that you do try calling every function at least once. There are a lot of components that can break in the compiler when using unusual types (e.g., name mangling, debug information, optimizer, IR generation, LLVM etc.) |
% for i in range(arity-1): | ||
if lhs.${i} != rhs.${i} { return lhs.${i} ${op} rhs.${i} } | ||
% end | ||
return lhs.${arity-1} ${op}${opeq} rhs.${arity-1} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As a code size optimization, you could try defining one operators in terms of others.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried defining !=
in terms of =
and it actually increased code size. I didn't do any further investigation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's unfortunate. Thanks for checking!
I'll update it based on feedback later today (calling each function once, adding spaces). |
Incidentally, I ran
It appears to be testing code completion for tuple types. After checking the code completion suggestions in the swift REPL, I'm assuming that it's erroring because completion now suggests the 6 comparison operators in addition to the Should I just update this to expect 8 items instead of 2, with relevant patterns? Or is the test explicitly trying to check tuples that have no other members, which would require altering the tuple to include a non- |
@kballard I think updating the test with new patterns is the right thing. Operator + tuple combination is a rare one that I don't think we have covered in our code completion tests. |
41bd040
to
5e62134
Compare
Updated PR for feedback. Still need to update the code completion tests though. |
Updated code completion tests. I do have a question about it though which I will put as a file comment. |
// TUPLE_NO_DOT_1-NEXT: Decl[InfixOperatorFunction]/OtherModule[Swift]: >= {#(Int, Double)#}[#Bool#]{{; name=.+$}} | ||
// TUPLE_NO_DOT_1-NEXT: Decl[InfixOperatorFunction]/OtherModule[Swift]: < {#(Int, Double)#}[#Bool#]{{; name=.+$}} | ||
// TUPLE_NO_DOT_1-NEXT: Decl[InfixOperatorFunction]/OtherModule[Swift]: != {#(Int, Double)#}[#Bool#]{{; name=.+$}} | ||
// TUPLE_NO_DOT_1-NEXT: Decl[InfixOperatorFunction]/OtherModule[Swift]: > {#(Int, Double)#}[#Bool#]{{; name=.+$}} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How are code completions sorted? I tried looking through the code but it's not immediately obvious. I did find code that appears to sort them based on some definition of a name (which I'd assume is like "=="
but I don't actually know), but the output here doesn't appear to be sorted in any way I can figure out. If it was sorted by name I'd expect to see the ordering be !=
, <
, <=
, ==
, >
, >=
, and it's not. Heck, !=
should show up before .0
then (and in fact when tab-completing in the integrated REPL it does sort it like that). So the ordering here must be based on something else, and I'm worried that this "something else" might not be stable.
I'm also not sure if we really want to match the full Decl[...]/OtherModule[..] prefix, but I'm not as concerned about that.
Ideally I'd actually switch to using -DAG
patterns to make it unordered, but that loses the property of ensuring there's no lines before the End completions
that don't match one of the expected completions. I don't know how important that is.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The completions are ordered in name lookup order (i.e., unpredictable).
You should switch to using -DAG
. The extra completions issue is handled by checking the number of completions in the Begin completions
line.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok. Should I switch them all to -DAG
, under the assumption that they may plausibly show up before the tuple fields? The existing tests were already relying on the order of the tuple fields, and I don't know if that's something they need to preserve (but preserving that requires assuming they show up first).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, the order does not matter for compiler correctness.
Updated again to use |
What if there was a new syntax added to make checking each member of type quicker to write? That would be useful for structs, enums with associated values, and tuples? Either a new syntax for repeating an operator on multiple members, or auto completion, or both? |
Sounds like you're proposing an extremely specific ad-hoc macro. And I don't know how you can automate this in the general case anyway, because I don't think it's true that arbitrary operations that you want to implement on tuples would all have the form of In any case, if you want to think about adding a macro system to Swift, feel free to discuss it on swift-evolution. This PR doesn't really seem like the appropriate place for that, since a macro system is something that would take a while to develop and implement and there's no point in blocking this PR on it. |
Could you add doc comments to the new APIs? |
@gribozavr AFAIK the only existing implementation of |
case .GreaterThan: return .LessThan | ||
case .UnorderedWith: return .UnorderedWith | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this function is not used.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're right. I created it because I was using existing floating-point tests as inspiration, but didn't end up using it because there was no reason to do so.
Yes, it is worth explaining the semantics of these operations. |
The patch LGTM otherwise. |
I'm tempted to just document the |
I would defer reviewing the documentation to @dabrahams. |
55d4094
to
20e214d
Compare
Rebased, squshed tests into initial commit, and updated based on feedback. |
Kevin, this is great, but I’d like to see a little more in the doc comments. In particular, explain (in English) when two tuples are considered equal. Also, please do the same for the ordering comparisons (or provide examples) so that users who don’t know what lexicographical ordering is don’t have to look up and understand the definition just to get an idea of what this means. Thanks! |
Ok, I can do that. I was using the existing documentation of Comparable as an example, where it links to the wikipedia page for "strict total order". I also skipped Do you want me to add a doc string to every single operator, or is it sufficient to have just the docstring on |
Heh, the sins of the past (ours) don’t justify those of the future ;-) I’m afraid they should all be documented. Fortunately you have gyb to cut the repetition in source. |
Fair enough. |
Implement == and != for tuples up to arity 6 where each component type is Equatable. Implement <, <=, >, and >= for tuples up to arity 6 where each component type is Comparable.
20e214d
to
b61c7a5
Compare
@dabrahams PR updated with docstrings for every operator. |
Nice, thanks! |
Implement tuple comparison operators
Nice one! |
tests: fall back to fork() if posix_spawnp() is not available
[pull] swiftwasm from master
Add flag to xcodebuild to disable manifest sandbox
This is an implementation of SE-0015 for tuples of arities 2–6.