加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

scala – 在保留不变性的同时分配值时如何引用变量?

发布时间:2020-12-16 09:42:14 所属栏目:安全 来源:网络整理
导读:我星期天下午正在闲逛,试图创造一个“房间”的结构。基本上,Room对象有多个出口,每个出口都指向其他房间。现在,我想要创建的第一件事是两个房间相互连接,最好在一个赋值语句中。喜欢这个: case class Room(title: String,exits: Map[Direction.Directi
我星期天下午正在闲逛,试图创造一个“房间”的结构。基本上,Room对象有多个出口,每个出口都指向其他房间。现在,我想要创建的第一件事是两个房间相互连接,最好在一个赋值语句中。喜欢这个:

case class Room(title: String,exits: Map[Direction.Direction,Room])

val firstRoom = Room("A room",Map(North -> Room("Another room",Map(South -> firstRoom))))

埃尔戈:房间一个有一个出口北到房间二,房间二有一个出口南回到房间一。

但是,您可以想像,这是错误的:在创建它时没有定义firstRoom值,所以在分配过程中尝试引用它将不起作用。

我很确定这对大多数(如果不是全部)编程语言都是如此。我的问题:如何解决这个问题,而不会使我的Room对象变得不可靠?我可以简单地创建几个Room对象,然后将它们添加到它们中,但是这样可以使房间变得可变,作为个人练习,我尽量避免。

解决方法

非递归

我认为你最好的选择是做这样的事情

object Rooms {
  case class Room(title: String) {
    def exits = exitMap(this)
  }
  val first:Room = Room("first")
  val second:Room = Room("second")

  private val exitMap = Map(first -> Map("S" -> second),second -> Map("N" -> first))
}

scala> Rooms.first.title
res: String = first

scala> Rooms.first.exits
res: scala.collection.immutable.Map[java.lang.String,Rooms.Room] = Map(S -> Room(second))

这是完全不变的,你避免讨厌的递归。

递归

构造递归结构需要更多的关心,因为Scala默认情况下不会懒惰。具体来说,不可能创建一个lazy或call-by-name case类参数。因此,我们必须为此采取专门的数据结构。

一个选择可能是使用Streams:

case class LazyRoom(title: String,exits: Stream[LazyRoom])

object LazyRooms {
  lazy val nullRoom: LazyRoom = LazyRoom("nullRoom",Stream.empty)
  lazy val first: LazyRoom = LazyRoom("first",nullRoom #:: second #:: Stream.empty)
  lazy val second: LazyRoom = LazyRoom("second",nullRoom #:: first #:: Stream.empty)
}

scala> LazyRooms.first.exits(1).title
res> String: second

为了节省开支,我在每个Stream之前设置一个虚拟的房间,以避免过早访问。 (A Stream只在尾部懒惰,但不在其头部。)专用的数据结构可能能够避免这种情况。

清理版本

我们可以通过调用名称帮助函数做更好的做肮脏的工作:

case class LazyRoom(title: String,exitMap: Stream[Map[String,LazyRoom]]) {
  def exits = exitMap(1) // skip the Streams empty head
}

def _exitMap(mappedItems: => Map[String,LazyRoom]) = {
  Map[String,LazyRoom]() #::
  mappedItems #::
  Stream.empty
}

object LazyRooms {
  lazy val first: LazyRoom = LazyRoom("first",_exitMap(Map("South" -> second)))
  lazy val second: LazyRoom = LazyRoom("second",_exitMap(Map("North" -> first)))
}

scala> LazyRooms.first.exits
res: Map[String,LazyRoom] = Map(South -> LazyRoom(second,Stream(Map(),?)))

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读