Scala:正确性代码示例的验证不起作用

Scala: the verification of correctness code example not working

我正在读书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)))

我大体上理解我们在这里所做的事情:我们将函数替换为其实现,用于 creditdebit 操作。为了最终得到原来的结果。但确切的例子是行不通的。

例如,对于单元测试,我们使用断言来确保它有效。因此,为了验证代码,我可以编写表达式并进行比较。这是一个奇怪的语法。 “=>”是什么意思?没有任何可比性。你会如何验证正确性

这里是验证之前的完整代码示例运行:

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)

您可能知道 => 在 Scala 中用于 Function 类型:A => BFunction[A, B].

的别名

但在 non-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

对我来说,它有点 inconsistent/confusing 解释引用透明度的符号 and/or 我们是如何得出最终结果的。

至于断言测试结果,最后得到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)) )

(他们检查的东西基本一样,区别在于测试失败的报告格式。)