-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Bring Ref on par with AtomicInteger #9340
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
Conversation
This change brings `Ref`s on par with `AtomicInteger` and `AtomicLong` by implementing methods like `getAndIncrement` and `incrementAndGet` directly on Ref. By using the `Numeric` type class, the new methods are actually supported for all numeric types.
I suspect these are better fitting as extension methods for specific types... Using these methods will introduce interface dispatch through |
@hearnadam I agree although I think that it might be better to do what you're proposing as a separate piece of work. It will actually be really good to have concrete classes that utilize AFAICT the changes in this PR should be backwards compatible, where we can simply ignore the implicit |
Can these be extension methods instead? |
If we have them as extension methods we won't be able to override them when we end up implementing via concrete classes. Or maybe I'm missing something? |
* Atomically increments the current value of the `Ref` by 1, returning the | ||
* value immediately before modification. | ||
*/ | ||
final def getAndIncrement(implicit num: math.Numeric[A], trace: Trace): UIO[A] = |
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.
Is it wise to mark them as final? I suppose a specialized version won't have the implicit argument anyway, so maybe.
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.
Making them non-final is fully backwards compatible, so maybe we can start with having them as final and we can change them when needed
Is there anything I can do? |
I was just waiting to see if there are any more comments before merging. @hearnadam do you have anything to add to this comment? |
I don't think it's possible to avoid the boxing without deferred in-lining which I was unable to make work even in Scala 3 only. The concrete class can at least override those methods, so you're correct that's a better approach. |
@hearnadam I think there are patterns in Scala 3 that could avoid the boxing, e.g.,: extension (ref: Ref[Int]) {
@targetName("getAndIncrementInt")
def getAndIncrement: UIO[Int] = ref.getAndUpdate(_ + 1)
}
extension (ref: Ref[Long]) {
@targetName("getAndIncrementLong")
def getAndIncrement: UIO[Long] = ref.getAndUpdate(_ + 1)
} But yeah can't think of a way to make this cross-compile to Scala 2 since we're lacking the |
This change brings
Ref
s on par withAtomicInteger
andAtomicLong
by implementing methods likegetAndIncrement
andincrementAndGet
directly on Ref.By using the
Numeric
type class, the new methods are actually supported for all numeric types.