per*_*i4n 19 functional-programming scala immutability data-structures
我正在学习斯卡拉,作为一名优秀的学生,我试图遵守我发现的所有规则.
一条规则是:不可靠性!
所以我试图使用不可变数据结构和val来编写所有代码,有时候这很难.
但今天我想到了自己:唯一重要的是对象/类应该没有可变状态.我不是被迫以不可变的样式编写所有方法,因为这些方法不会相互影响.
我的问题:我是否正确或有任何问题/缺点我看不到?
编辑:
aishwarya的代码示例:
def logLikelihood(seq: Iterator[T]): Double = {
val sequence = seq.toList
val stateSequence = (0 to order).toList.padTo(sequence.length,order)
val seqPos = sequence.zipWithIndex
def probOfSymbAtPos(symb: T, pos: Int) : Double = {
val state = states(stateSequence(pos))
M.log(state( seqPos.map( _._1 ).slice(0, pos).takeRight(order), symb))
}
val probs = seqPos.map( i => probOfSymbAtPos(i._1,i._2) )
probs.sum
}
Run Code Online (Sandbox Code Playgroud)
说明:这是一种计算变量阶齐次马尔可夫模型的对数似然的方法.state的apply方法获取所有先前的符号和即将到来的符号,并返回这样做的概率.
正如您所看到的:整个方法只是增加了一些使用变量更容易的概率.
Apo*_*isp 47
规则不是真正的不变性,而是参考透明度.使用本地声明的可变变量和数组是完全可以的,因为没有任何效果可以观察到整个程序的任何其他部分.
引用透明度(RT)的原则是这样的:
如果对于所有程序,每个出现的in 都可以用求值结果替换,而不影响可观察的结果,则表达式e是引用透明的.pepep
请注意,如果e创建并改变某些本地状态,则不会违反RT,因为没有人能够观察到这种情况.
也就是说,我非常怀疑你的实现对于vars来说更直接.
函数式编程的一个例子就是在代码中简洁并引入更多数学方法.它可以减少错误的可能性,使您的代码更小,更易读.至于更容易与否,它确实需要您以不同的方式思考您的问题.但是一旦你习惯于使用功能模式进行思考,那么更具势在意的风格可能会变得更容易.
它很难完美地运行并且具有零可变状态但是对于具有最小可变状态非常有益.要记住的是,一切都需要平衡而不是极端.通过减少可变状态的数量,您最终会更难以编写具有意外后果的代码.一个常见的模式是拥有一个可变变量,其值是不可变的.这种方式标识(命名变量)和值(可以分配变量的不可变对象)是分开的.
var acc: List[Int] = Nil
// lots of complex stuff that adds values
acc ::= 1
acc ::= 2
acc ::= 3
// do loop current list
acc foreach { i => /* do stuff that mutates acc */ acc ::= i * 10 }
println( acc ) // List( 1, 2, 3, 10, 20, 30 )
Run Code Online (Sandbox Code Playgroud)
在我们开始foreach的时候,foreach正在循环acc的值.任何acc的突变都不会影响循环.这比java中的典型迭代器更安全,其中列表可以在迭代中更改.
还存在并发问题.不可变对象很有用,因为JSR-133内存模型规范声称对象最终成员的初始化将在任何线程可以看到这些成员之前发生,期间!如果它们不是最终的那么它们是"可变的"并且不能保证正确的初始化.
演员是放置可变状态的理想场所.表示数据的对象应该是不可变的.以下面的例子为例.
object MyActor extends Actor {
var acc: List[Int] = Nil
def act() {
loop {
react {
case i: Int => acc ::= i
case "what is your current value" => reply( acc )
case _ => // ignore all other messages
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,我们可以发送acc的值(这是一个List)而不用担心同步,因为List是不可变的,也就是List对象的所有成员都是final.同样由于不变性,我们知道没有其他演员可以改变发送的底层数据结构,因此没有其他演员可以改变这个演员的可变状态.