什么是Scala等同于Clojure的Atom? [英] What is the Scala equivalent of Clojure's Atom?
问题描述
Clojure 有一个Atom ,用于更改线程之间的状态同步和独立方式,不是STM的一部分。您使用此类:
user => (def my-atom(atom 0))
#'user / my-atom
user => @ my-atom
0
user => (swap!my-atom inc)
1
user => @ my-atom
1
user => (swap!my-atom(fn [n](*(+ nn)2)))
4
我的问题是: Scala等同于Clojure的Atom?
正如@Shepmaster和@ om-nom-nom所说,它是一个包装器 java.util.concurrent.atomic.Atomic ...
。
等效包装器可能如下所示:
import java。 util.concurrent.atomic._
/ pre>
import scala.annotation.tailrec
对象Atom {
def apply [A](init:A):Atom [A] = new Impl (new AtomicReference(init))
私有类Impl [A](state:AtomicReference [A])extends Atom [A] {
def apply():A = state.get )
def update(value:A):Unit = state.set(value)
def transformAndGet(f:A => A):A = transformImpl(f)
$ b b @tailrec private final def transformImpl(fun:A => A):A = {
val v = state.get()
val newv = fun(v)
if .compareAndSet(v,newv))newv
else transformImpl(fun)
}
}
}
trait Atom [A] {
def apply ):A
def update(value:A):Unit
def transformAndGet(f:A => A):A
}
例如:
val myAtom = Atom
myAtom()// - > 0
myAtom.transformAndGet(_ + 1)// - > 1
myAtom()// - > 1
myAtom.transformAndGet(_ * 4)// - > 4
如果使用 Scala-STM ,该功能内置于STM引用中,通过使用
.single
视图:scala> import scala.concurrent.stm._
import scala.concurrent.stm._
scala> val myAtom = Ref(0).single
myAtom:scala.concurrent.stm.Ref.View [Int] =
scala.concurrent.stm.ccstm.CCSTMRefs$IntRef@52f463b0
scala> myAtom()
res0:Int = 0
scala> myAtom.transformAndGet(_ + 1)
res1:Int = 1
scala> myAtom()
res2:Int = 1
scala> myAtom.transformAndGet(_ * 4)
res3:Int = 4
Ref.apply
将为您提供原始类型的专用单元格,例如Int
而不是AnyRef
(盒装)。Clojure has an Atom for changing state between threads in a synchronous and independent manner, that is not part of the STM. You use it like this:
user=> (def my-atom (atom 0)) #'user/my-atom user=> @my-atom 0 user=> (swap! my-atom inc) 1 user=> @my-atom 1 user=> (swap! my-atom (fn [n] (* (+ n n) 2))) 4
My question is: What is the Scala equivalent of Clojure's Atom?
解决方案As @Shepmaster and @om-nom-nom said, it's a wrapper around
java.util.concurrent.atomic.Atomic...
.An equivalent wrapper could look like this:
import java.util.concurrent.atomic._ import scala.annotation.tailrec object Atom { def apply[A](init: A): Atom[A] = new Impl(new AtomicReference(init)) private class Impl[A](state: AtomicReference[A]) extends Atom[A] { def apply(): A = state.get() def update(value: A): Unit = state.set(value) def transformAndGet(f: A => A): A = transformImpl(f) @tailrec private final def transformImpl(fun: A => A): A = { val v = state.get() val newv = fun(v) if (state.compareAndSet(v, newv)) newv else transformImpl(fun) } } } trait Atom[A] { def apply(): A def update(value: A): Unit def transformAndGet(f: A => A): A }
Ex:
val myAtom = Atom(0) myAtom() // --> 0 myAtom.transformAndGet(_ + 1) // --> 1 myAtom() // --> 1 myAtom.transformAndGet(_ * 4) // --> 4
If you use Scala-STM, that functionality is built into STM references, by using the
.single
view:scala> import scala.concurrent.stm._ import scala.concurrent.stm._ scala> val myAtom = Ref(0).single myAtom: scala.concurrent.stm.Ref.View[Int] = scala.concurrent.stm.ccstm.CCSTMRefs$IntRef@52f463b0 scala> myAtom() res0: Int = 0 scala> myAtom.transformAndGet(_ + 1) res1: Int = 1 scala> myAtom() res2: Int = 1 scala> myAtom.transformAndGet(_ * 4) res3: Int = 4
The advantage is that
Ref.apply
will already give you specialised cells for the primitive types, e.g.Int
instead ofAnyRef
(boxed).这篇关于什么是Scala等同于Clojure的Atom?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!