-
-
Notifications
You must be signed in to change notification settings - Fork 79
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
Sequence equality #249
base: main
Are you sure you want to change the base?
Sequence equality #249
Conversation
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.
Lots of good fixes in here. I think there are some introduced bugs though. I tried to pick them out.
return !lhs; | ||
return false; |
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.
Why change this? Right now, it would treat two null object ptrs as equal. This would also carry over to us removing nullptr
support for boxes, such that two nils would be equal.
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.
Thanks, I missed that box overloaded !
.
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.
Actually, could you look at this again? At this point we already know !lhs
is false
, so I think returning either is equivalent.
Would this be another way of writing the test?
if(!lhs != !rhs) return false
EDIT: No, because that is false when both are null.
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.
Added assertions to point out my reasoning.
return true; | ||
return seq == nullptr; |
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 don't think this is correct. In the case where this
is a shorter seq than o
, we would finish our for
loop and then need to check if there is some seq
left over.
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 case where this is a shorter seq than o, we would finish our for loop and then need to check if there is some seq left over.
This is my attempt at adding that check. At this point, we've already called next_in_place(seq)
, and seq
will be nullptr
if there's none left over.
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.
We're talking about the same diff, right?
- return true;
+ return seq == nullptr;
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 I saw the opposite diff. 🤷 My mistake!
@@ -77,12 +77,12 @@ namespace jank::runtime::obj | |||
for(auto it(fresh_seq()); it != nullptr; | |||
it = runtime::next_in_place(it), seq = runtime::next_in_place(seq)) | |||
{ | |||
if(seq == nullptr || !runtime::equal(it, seq->first())) | |||
if(seq == nullptr || !runtime::equal(it->first(), seq->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.
This seems like a good fix. We'd need the same thing for chunked_cons
above, though. I wonder where else this cropped up. I have a TODO for sequence equality having a lot of copy pasta.
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.
We'd need the same thing for chunked_cons above, though.
Done.
I wonder where else this cropped up.
Several places. I think I reverted some of them accidentally when experimenting with replace nullptr
with nil_const()
, I'll have another look.
I have a TODO for sequence equality having a lot of copy pasta.
I wasn't sure how to tackle it, but I can at least write more tests so then the abstraction can be validated easily.
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.
Don't worry about removing support for nullptr
yet. Certainly not in this PR, which already has a lot going on.
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 wasn't sure how to tackle it, but I can at least write more tests so then the abstraction can be validated easily.
I have some ideas for how to do it. The tests are very welcome, though.
Found and fixed a couple more issues while I scanned everything. Lmk if I should pull them out.
|
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.
Mostly a rehash of our slack discussion, but also called out some other concerns.
@@ -878,88 +878,88 @@ namespace jank::runtime | |||
case 1: | |||
return dynamic_call(source, s->first()); | |||
case 2: | |||
return dynamic_call(source, s->first(), s->next_in_place()->first()); | |||
return dynamic_call(source, s->first(), (s = s->next_in_place())->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.
I have a local TODO that notes that persistent_list_sequence
shouldn't exist, since persistent_list
itself is a sequence.
This change is a big red flag, since this is an extremely hot code path. I don't want to impact its perf for this one case which needs to change anyway.
If you want to add a comment here noting that it doesn't work for persistent_list
, that's ok. If you want to remove persistent_list_sequence
, that's also ok, but let's do it in a separate PR.
Either way, let's please undo this file's changes.
{ | ||
return !lhs; | ||
assert(lhs); |
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 we discussed in slack, none of these assertions on native boxes are needed. It has its own.
else if(!rhs) | ||
if(!rhs) |
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.
Why remove the else
? I find it helps with the logical flow. Also, by having the else if
, your assertion is proven by the compiler to be redundant.
assert(it != nil::nil_const()); | ||
assert(seq != nil::nil_const()); |
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.
It's impossible for these assertions to be false, proven by the type system. I think you're concerned about the next_in_place(it)
call somehow returning an object_ptr
. But it could never do that, since it would result in a compiler error.
Now, the history is that next_in_place
has been in flux for a year or so and I was making some changes which would allow for it to be optional. That never happened, but it's why we're not using it->next_in_place()
here. Ultimately, it's doing the same thing and all of these can be changed back. I just haven't done that yet, since it's a perf change and I haven't been focusing on perf.
Either way, your concerns about this being nil should not be keeping you up. auto it(fresh_seq());
means that we'll have a fully typed it
for the currently visited object. We cannot assign an object_ptr
to it. C++ won't allow it.
@@ -16,6 +16,7 @@ namespace jank::runtime::obj | |||
: value{ value } | |||
, count{ count } | |||
{ | |||
assert(0 < to_int(count)); |
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.
Feels like this could be an exception, rather than assertion, since someone embedding jank may create it a repeat with 0
and we don't need to kill the whole program.
Closes #243
Closes #250
Closes #251
Closes #274
It would be nice to replace
nullptr
returns withnil
insequenceable
but it enables important optimizations for calls tosequenceable
member functions. I did not investigate returningoption
types.