-
Notifications
You must be signed in to change notification settings - Fork 238
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
Update behavior of augmented null coalescing operator #3614
Update behavior of augmented null coalescing operator #3614
Conversation
x ??= y now behaves like x ?? (x = y) rather than x = x ?? y These are equivalent when x is null. When x is non-null, we avoid an unnecessary re-assignment step, which also allows for the possibility of using this operator with immutable hash tables without raising errors when keys already exist. Closes: Macaulay2#3612
then ( | ||
e := tryEval(x.lhs); | ||
if tryEvalSuccess then lexpr = e) |
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'm a little confused. Where is the actual assignment to lexpr
happening now?
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 don't need it anymore when the left-hand side is non-null since we return right away. And when it's null, we've already assigned lexpr
as nullE
a couple lines earlier.
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'm still confused. Where does the x = y
in x ?? (x = y)
is happening? I thought here lexpr
was x
.
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 assignment happens in one of several places, depending on what the code looks like.
lexpr
is the evaluated left-hand side. But we still have the original unevaluated Code
object, which we need to figure out what type of assignment we'll end up doing (global, local, assigning an element of a list/hash table, etc.). Here's the basic gist:
- Go ahead and evaluate the left hand side (
lexpr
) and stuff it in anevaluatedCode
object (left
). We also check for errors here and whether someone has installed an augmented assignment method for this operator for the class oflexpr
. If so, call that and return the result. - Now go back and look at the original unevaluated
Code
object to figure out how to assign things. But instead of using thisCode
object, we swap it out withleft
to avoid re-evaluating the left-hand side.
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 see, that makes sense.
Unrelated to this PR, but I just noticed this: i1 : (a,b) ??= (1,2)
-*dummy position*- error: augmented assignment not implemented for this code |
Ok yeah -- at the very least we should fix the |
Yeah, I don't necessarily need that to work (at least it's not a priority), but the dummy position surprised me. |
x ??= y
now behaves likex ?? (x = y)
rather thanx = x ?? y
.These are equivalent when x is null.
When x is non-null, we avoid an unnecessary re-assignment step, which also allows for the possibility of using this operator with immutable hash tables without raising errors when keys already exist.
Closes: #3612