我正在阅读Functional and Reactive Domain Modeling
。在第1.5节第30页中,有一个例子:
credit(a, 100).flatMap(debit(_, 100))
=> Success(a.copy(balance = Balance(0 + 100))).flatMap(debit(_, 100))
=> debit(Account("a1", "John", .., Balance(100)), 100)
=> Success(a.copy(balance = Balance(100 - 100)))
=> Success(Account("a1", "John", .., Balance(0)))
我一般都理解,我们在这里做的是:我们用credit
和debit
操作替换函数及其实现。为了最终获得原始结果。但确切的例子不起作用。
例如,通过单元测试,我们使用断言来确保它有效。结果,为了验证代码,我可以编写表达式并进行比较。这是一个奇怪的语法。什么" =>"意思?没有任何比较。你如何验证正确性
以下是此验证之前的代码的完整示例,以便能够运行它:
import java.util.{ Date, Calendar }
import scala.util.{ Try, Success, Failure }
def today = Calendar.getInstance.getTime
type Amount = BigDecimal
case class Balance(amount: Amount = 0)
case class Account(no: String, name: String,
dateOfOpening: Date, balance: Balance = Balance())
trait AccountService {
def debit(a: Account, amount: Amount): Try[Account] = {
if (a.balance.amount < amount)
Failure(new Exception("Insufficient balance in account"))
else Success(a.copy(balance = Balance(a.balance.amount – amount)))
}
def credit(a: Account, amount: Amount): Try[Account] =
Success(a.copy(balance = Balance(a.balance.amount + amount)))
}
object AccountService extends AccountService
import AccountService._
val t = today
val a = Account("a1", "John", t)
答案 0 :(得分:1)
您可能知道Scala中=>
类型使用了Function
:A => B
是Function[A, B]
的别名。
但是在非Scala语境中,它有时会出现在例如在打印表达结果之前进行REPL。我想这正是我们在这里所拥有的,除了它还显示了部分结果(这本身很奇怪,因为我没有看到任何REPL这样做。)
credit(a, 100).flatMap(debit(_, 100))
=> Success(a.copy(balance = Balance(0 + 100))).flatMap(debit(_, 100))
// credit substituted with its result
=> debit(Account("a1", "John", .., Balance(100)), 100)
=> Success(a.copy(balance = Balance(100 - 100)))
// debit substitutes with its result
=> Success(Account("a1", "John", .., Balance(0)))
// final result
对我而言,解释参考透明度和/或我们如何得出最终结果有点不一致/令人困惑的符号。
至于用断言测试结果,最后得到Try[Account]
。即使没有任何测试框架匹配,您也可以将其检查为:
// given
val credit = credit(a, 100)
// when
val result = credit.flatMap(debit(_, 100))
// then
assert( result == Success(Account("a1", "John", .., Balance(0))) )
例如ScalaTest断言看起来像
result shouldBe Success(Account("a1", "John", .., Balance(0)))
虽然Specs2有更具体的东西
result must beSuccessfulTry.withValue( Account("a1", "John", .., Balance(0)) )
(他们都检查基本相同的东西,差异将是测试失败时的报告格式。)