假设我将银行账户信息存储在一个不可变的Map
:
val m = Map("Mark" -> 100, "Jonathan" -> 350, "Bob" -> 65)
Run Code Online (Sandbox Code Playgroud)
我想从马克的帐户中提取50美元.我可以这样做:
val m2 = m + ("Mark" -> (m("Mark") - 50))
Run Code Online (Sandbox Code Playgroud)
但这段代码对我来说似乎很难看.有没有更好的方法来写这个?
我正在学习scala,我正在寻找更新某个xml中的嵌套节点.我有一些工作,但我想知道它是否是最优雅的方式.
我有一些xml:
val InputXml : Node =
<root>
<subnode>
<version>1</version>
</subnode>
<contents>
<version>1</version>
</contents>
</root>
Run Code Online (Sandbox Code Playgroud)
我想更新版本的节点的子节点,而不是一个在内容.
这是我的功能:
def updateVersion( node : Node ) : Node =
{
def updateElements( seq : Seq[Node]) : Seq[Node] =
{
var subElements = for( subNode <- seq ) yield
{
updateVersion( subNode )
}
subElements
}
node match
{
case <root>{ ch @ _* }</root> =>
{
<root>{ updateElements( ch ) }</root>
}
case <subnode>{ ch @ _* …
Run Code Online (Sandbox Code Playgroud) 当我设计不可变对象时,由于自动生成的copy
方法,案例类非常方便.
但是案例类有它们自己的问题:它们不应该继承而且即使你不想要它们也会给你一个提取器.
所以有时我必须使用花园种类的Scala类.问题是,我必须编写自己的不可变API,这可能非常重复:
class Debt(principalBalance: Double, name: String, endDate: LocalDate) {
def withNewPrincipalBalance(bal: Double) = new Debt(bal, name, endDate)
}
Run Code Online (Sandbox Code Playgroud)
是否有更可扩展的方法来做到这一点?我可以使用编译器插件吗?
我想更新一个嵌套的,不可变的数据结构(我附上了一个假想游戏的一个小例子),我想知道,如果这可以做得更优雅一点.
每当地下城里的东西发生变化时,我们都需要一个新的地牢,所以我给了它一个普通的更新成员.对于一般情况,我可以提出的最佳使用方法是为每个嵌套指定处理函数,然后将组合函数传递给更新成员.
然后,对于非常常见的情况(比如将地图应用于特定级别的所有怪物),我提供了额外的成员(Dungeon.MapMonstersOnLevel).
整个事情都有效,我想知道,如果有人能想到更好的方法.
谢谢!
// types
type Monster(awake : bool) =
member this.Awake = awake
type Room(locked : bool, monsters : Monster list) =
member this.Locked = locked
member this.Monsters = monsters
type Level(illumination : int, rooms : Room list) =
member this.Illumination = illumination
member this.Rooms = rooms
type Dungeon(levels : Level list) =
member this.Levels = levels
member this.Update levelFunc =
new Dungeon(this.Levels |> levelFunc)
member this.MapMonstersOnLevel (f : Monster -> Monster) nLevel =
let monsterFunc = …
Run Code Online (Sandbox Code Playgroud) 在水星我可以使用:
A = B^some_field := SomeValue
Run Code Online (Sandbox Code Playgroud)
至A与B结合的副本,除了some_field
是SomeValue
不是不管它是B.我相信哈斯克尔相当于是一样的东西:
a = b { some_field = some_value }
Run Code Online (Sandbox Code Playgroud)
Scala是否有类似的东西用于"修改"不可变值.替代方案似乎是有一个构造函数直接设置实例中的每个字段,这并不总是理想的(如果构造函数应该保持不变).如果我必须明确地传递我想要修改副本的实例中的所有其他值,那么它会非常笨重而且更加脆弱.
我通过谷歌搜索,或者在语言参考手册或"Scala By Example"(我已经阅读了从头到尾,但尚未全部吸收,所以它可能好吧在那里).
我可以看到这个功能可能与Java风格的访问保护和子类有一些奇怪的交互,虽然......
我最近创建了一个支持+, - 等操作的不可变类,它在更改时返回该类的新实例.
我想创建该类的子类来添加一些状态和功能,但现在我遇到了一个问题,即所有原始类的方法都返回自身的实例而不是子类.
基于我目前对Scala的有限知识,我可以想出这个:
class Foo(val bar:Int) {
def copy(newBar:Int) = new Foo(newBar)
def + (other:Foo):This = copy(this.bar + other.bar)
}
class Subclass(barbar:Int) extends Foo(barbar) {
override def copy(newBar:Int) = new Subclass(newBar)
override def + (other:Subclass) = super.+(other).asInstanceOf[Subclass]
}
Run Code Online (Sandbox Code Playgroud)
这里的问题非常明显 - 返回新实例的超类的所有操作都必须在子类中使用强制转换重新定义.
起初"this.type"似乎很有希望,但"this.type"只包含"this"而不包含任何其他相同类型的对象.
是否存在使不可变类易于子类化的标准模式?就像是:
class Foo(val bar:Int) {
def copy(newBar:Int):SameType = new Foo(newBar)
def + (other:Foo) = copy(this.bar + other.bar)
}
class Subclass(barbar:Int) extends Foo(barbar) {
override def copy(newBar:Int):SameType = new Subclass(newBar)
override def + (other:Subclass) = super.+(other).asInstanceOf[Subclass]
} …
Run Code Online (Sandbox Code Playgroud) 我目前正在处理一个三级流程,我需要一些信息才能访问和更新.信息也是三级的,这样一个级别的过程可能需要在其级别和更高级别访问/更新信息.
type info_0 = { ... fields ... }
type info_1 = { ... fields ... }
type info_2 = { ... fields ... }
Run Code Online (Sandbox Code Playgroud)
fun0
会用a做一些东西info_0
,然后将它传递给fun1
a info_1
,然后返回结果info_0
并继续,fun1
用另一个调用另一个info_1
.同样的情况发生在较低级别.
我目前的代表有
type info_0 = { ... fields ... }
type info_1 = { i0: info_0; ... fields ... }
type info_2 = { i1: info_1; ... fields ... }
Run Code Online (Sandbox Code Playgroud)
在fun2
,更新info_0
变得非常混乱:
let fun2 (i2: info_2): info_2 =
{ …
Run Code Online (Sandbox Code Playgroud) 我如何State
用来模仿行为List.zipWithIndex
?到目前为止我提出的(不起作用)是:
def numberSA[A](list : List[A]) : State[Int, List[(A, Int)]] = list match {
case x :: xs => (init[Int] <* modify((_:Int) + 1)) map { s : Int => (x -> s) :: (numberSA(xs) ! s) }
case Nil => state( (i : Int) => i -> nil[(A, Int)] )
}
Run Code Online (Sandbox Code Playgroud)
这基于状态示例非常松散.正如我所说,它不起作用:
scala> res4
res5: List[java.lang.String] = List(one, two, three)
scala> numberSA(res4) ! 1
res6: List[(String, Int)] = List((one,1), (two,1), (three,1))
Run Code Online (Sandbox Code Playgroud)
我可以通过更改case语句的一行来使它工作:
case x …
Run Code Online (Sandbox Code Playgroud) 我正在尝试使用Scala以不可变的方式编写NSGA2中使用的Deb的快速非支配排序算法(NDS).
但问题似乎比我想象的要困难,所以我在这里简化了制作MWE的问题.
想象一下,一个群体Seq[A]
,每个A
元素decoratedA
都有一个列表,其中包含指向其他群体元素的指针Seq[A]
.
一个函数evalA(a:decoratedA)
取linkedA
它包含的列表,并减少每个的值.
接下来,我将获取decoratedAPopulation
人口A 的子集列表,并对evalA
每个人进行调用.我有一个问题,因为在这个子集列表上的元素的每次迭代之间decoratedAPopulation
,我需要A
用decoratedA
新的更新linkedA
它包含的新的更新它包含...
更有问题的是,每个人口元素都需要更新'linkedA'来替换链接元素,如果它发生变化......
你可以看到Hum,以这种方式保持所有链表同步似乎很复杂.我提出了另一个解决方案底部,可能需要递归才能在每个EvalA
替换元素的新种群后返回.
我怎样才能以不变的方式正确地做到这一点?
以可变的方式编码很容易,但我找不到以不可变的方式做到这一点的好方法,你有路径或想法吗?
object test extends App{
case class A(value:Int) {def decrement()= new A(value - 1)}
case class decoratedA(oneAdecorated:A, listOfLinkedA:Seq[A])
// We start algorithm loop with A element with value = 0
val population = Seq(new A(0), new A(0), new A(8), new A(1))
val decoratedApopulation = Seq(new …
Run Code Online (Sandbox Code Playgroud) scala ×8
immutability ×3
base-class ×1
f# ×1
inheritance ×1
list ×1
map ×1
nested ×1
ocaml ×1
records ×1
recursion ×1
scalaz ×1
sml ×1
state-monad ×1
xml ×1