Ani*_*nil 7 functional-programming scala
我在Scala中发现了这句话,解释了它的功能行为.
程序的操作应该将值的输入映射到输出值,而不是在适当的位置改变数据
有人可以用一个很好的例子来解释它吗?
编辑: 请在上下文中解释或举例说明上述句子,请不要让它变得更加混乱
oxb*_*kes 14
这是指最明显的模式,即与Scala相比,编写使用Java集合的代码的方式之间存在差异.如果您正在编写scala但是在Java的习惯用法中,那么您将通过适当地改变数据来处理集合.的惯用 Scala代码做同样的将有利于输入值到输出值的映射.
让我们来看看你可能想要对集合做的一些事情:
在Java中,如果我有一个List<Trade>并且我只对那些用德意志银行执行的交易感兴趣,我可能会这样做:
for (Iterator<Trade> it = trades.iterator(); it.hasNext();) {
Trade t = it.next();
if (t.getCounterparty() != DEUTSCHE_BANK) it.remove(); // MUTATION
}
Run Code Online (Sandbox Code Playgroud)
在此循环之后,我的trades集合仅包含相关交易.但是,我已经使用变异实现了这一点- 粗心的程序员可能很容易错过这trades是一个输入参数,一个实例变量,或者在方法的其他地方使用.因此,很可能他们的代码现在已被破坏.此外,由于同样的原因,这样的代码对于重构非常脆弱 ; 一个希望重构一段代码的程序员必须非常小心,不要让变异的集合逃避它们打算使用的范围,反之亦然,它们不会意外地使用未变异的集合,它们应该在使用过变异的.
与Scala比较:
val db = trades filter (_.counterparty == DeutscheBank) //MAPPING INPUT TO OUTPUT
Run Code Online (Sandbox Code Playgroud)
这创造了一个新的集合!它不会影响任何正在观察trades并且本质上更安全的人.
假设我有一个List<Trade>,我想得到一个Set<Stock>我一直在交易的独特股票.同样,Java中的习语是创建一个集合并对其进行变异.
Set<Stock> stocks = new HashSet<Stock>();
for (Trade t : trades) stocks.add(t.getStock()); //MUTATION
Run Code Online (Sandbox Code Playgroud)
使用scala正确的做法是映射输入集合,然后转换为集合:
val stocks = (trades map (_.stock)).toSet //MAPPING INPUT TO OUTPUT
Run Code Online (Sandbox Code Playgroud)
或者,如果我们关注性能:
(trades.view map (_.stock)).toSet
(trades.iterator map (_.stock)).toSet
Run Code Online (Sandbox Code Playgroud)
这有什么好处?好:
A => B到Coll[A]获得Coll[B]更清晰.同样,在Java中,成语必须是变异.假设我们试图将我们所做交易的十进制数量相加:
BigDecimal sum = BigDecimal.ZERO
for (Trade t : trades) {
sum.add(t.getQuantity()); //MUTATION
}
Run Code Online (Sandbox Code Playgroud)
同样,我们必须非常小心,不要意外地观察到部分构造的结果!在scala中,我们可以在一个表达式中执行此操作:
val sum = (0 /: trades)(_ + _.quantity) //MAPPING INTO TO OUTPUT
Run Code Online (Sandbox Code Playgroud)
或其他各种形式:
(trades.foldLeft(0)(_ + _.quantity)
(trades.iterator map (_.quantity)).sum
(trades.view map (_.quantity)).sum
Run Code Online (Sandbox Code Playgroud)
哦,顺便说一句,Java实现中有一个错误! 你发现了吗?
我想说的是:
var counter = 0
def updateCounter(toAdd: Int): Unit = {
counter += toAdd
}
updateCounter(8)
println(counter)
Run Code Online (Sandbox Code Playgroud)
和:
val originalValue = 0
def addToValue(value: Int, toAdd: Int): Int = value + toAdd
val firstNewResult = addToValue(originalValue, 8)
println(firstNewResult)
Run Code Online (Sandbox Code Playgroud)
这是一个严重的过度简化,但更完整的例子是使用 FoldLeft 来构建结果,而不是自己做艰苦的工作:foldLeft 示例