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(),?))) (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |