谈谈side-effect
在读《Functional Programming in Scala》一书,
关于移除副作用带来的好处,可以用一个简单的场景来模拟。
场景:咖啡店买咖啡
- 场景构成
- 信用卡
- 咖啡店
- 咖啡
- 外部API(支付时调用)
一个有副作用的函数
class Cafe:
def buyCoffee(cc: CreditCard):Coffee =
val cup = new Coffee()
cc.charge(cup.price)
cup
class CreditCard:
def charge(price: Double): UInt =
println('charging: '+price)
class Coffee:
val price : Double = 2.0
一个没有副作用的函数
√ 单元测试可行
class Cafe:
def buyCoffee(cc: CreditCard): (Coffee, Charge) =
val cup = new Coffee()
(cup, Charge(cc, cup.price)
case Class Charge(cc: CreditCard, amount: Double):
def combine(other: Charge): Charge =
if cc = other.cc then
Charge(cc, amount + other.amount)
else
throw new Exception("Can't combine with different card")
√ 可复用、可组合
class Cafe:
def buyCoffee(cc: CreditCard): (Coffee, Charge) =
val cup = new Coffee()
(cup, Charge(cc, cup.price)
def buyCoffees(cc: CreditCard, n: Int): (List[Coffee], Charge) =
val purchases: List[(Coffee, Charge)] = List.fill(n)(buyCoffee(cc))
val (coffees, charges) = purchases.unzip
val reduced = charges.reduce((c1, c2)=>c1.combine(c2))
(coffees, reduced)