【问题标题】:Scala ZIO Ref datatypeScala ZIO Ref 数据类型
【发布时间】:2023-04-07 11:31:02
【问题描述】:

我在 Scala 中有一个类,有四个参数,其中 2 个是变量,我想在 Zio 中使用 Ref 数据类型来控制对这些变量的访问,这是我的代码:


import zio._

class Rectangle(val width: Int,val height: Int) {

  val x: UIO[Ref[Int]] = Ref.make(0)
  val y: UIO[Ref[Int]] = Ref.make(0)

  def this(x1: Int, y1: Int, width: Int, height: Int) {
    this(width, height)

    for {
      ref <- this.x
      _ <- ref.set(x1)
    } yield ()

    for {
      ref <- this.y
      _ <- ref.set(y1)
    } yield ()
  }

}

为了访问 Ref 我写了这个:

import zio.console._
import zio._

object AccessRef extends App {
  val myRec = new Rectangle(1, 2, 3, 4)

  override def run(args: List[String]) =
    for {
      rec <- IO.succeed(myRec)
      x <- rec.x
      x1 <- x.get
      _ <- putStrLn(x1.toString)
      _ <-putStrLn(rec.height.toString)
    } yield (0)
}

输出:

0
4

我想知道为什么 ref 的值不能更新为 1 而不是 0 ?

【问题讨论】:

    标签: scala zio


    【解决方案1】:

    val x: UIO[Ref[Int]] = Ref.make(0) 不是参考。它是对返回引用的操作的描述。

    这段代码

    for {
          ref <- this.x
          _ <- ref.set(x1)
        } yield ()
    

    创建一个引用,为其设置一个值并立即丢弃该引用。您很可能希望xy 的类型为Ref[Int]

    例子:

    import zio.console._
    import zio._
    
    class Rectangle(val width: Ref[Int], val height: Ref[Int])
    
    object AccessRef extends App {
    
      override def run(args: List[String]) =
        for {
          recW <- Ref.make(3)
          recH <- Ref.make(5)
          rectangle = new Rectangle(recW, recH)
          oldHeight <- rectangle.height.get
          _ <- putStrLn(s"old value: $oldHeight") //5
          _ <- rectangle.height.set(30)
          newHeight <- rectangle.height.get
          _ <- putStrLn(s"new value: $newHeight") //30
        } yield (0)
    }
    

    【讨论】:

    • 如果我声明xy 类型为Ref[Int] 我不能将值设置为x1y1 !!您对我如何更新他们的价值观有任何想法吗?
    • 拥有两个 Ref 的替代方法可能是拥有一个常规的不可变 Rectangle(x,y,w,h) 并将整个内容放入 Ref[Rectacle]。更少的移动部件、原子更新等等。
    • 你可以。但是修改 Ref 会引入 IO 效果。我用一个例子更新了我的答案。
    • @simpadjo 谢谢它的工作。最后一件对我来说仍然很模糊的事情是我如何在构造函数中给Ref一个初始值假设我想在类定义中将高度设置为0怎么做?
    • 分配Ref 并设置值是有效的操作。一旦你这样做了,你就在IO。所以不可能在构造函数中创建Ref。尽管您可以改为编写工厂方法:def createRect(w: Int, h: Int): UIO[Rectangle] = for {recW &lt;- Ref.make(h) ; recH &lt;- Ref.make(w)} yield new Rectangle(recW, recH)
    猜你喜欢
    • 2020-03-01
    • 1970-01-01
    • 2019-06-16
    • 1970-01-01
    • 2021-07-17
    • 1970-01-01
    • 2020-10-22
    • 2021-08-03
    • 2022-12-01
    相关资源
    最近更新 更多