2

首先是问题:箭头反模式是Scala中的做事方式吗?

我已经从 Java 过渡到 Scala 大约 3 个月了。我开始将反箭头模式视为 Scala 中的一种标准。

例如,在 Java 中,我喜欢尽快从方法中返回。我们不喜欢很多内部嵌套。如果你有很多,它被称为箭头反模式。你可以在这里阅读:http ://c2.com/cgi/wiki?ArrowAntiPattern

Java 示例:

boolean isValid(String input){
  if (input.trim().length() <1) return false //return early
  if (input.substring(0,3).equals("sth")) return false;

  //do some more checks for validity then return true

  return true
}

如果我在 Scala 中编写此代码,我将不得不使用匹配大小写语句,这会导致大量缩进。请记住,这只是一个虚拟示例,我尝试仅传达 Scala 的嵌套和缩进。

def isValid(input:String):  Boolean = {
  (input.trim.length < 1) match {
    case true => 
      input.substring(0,3) match {
        case sthCase if(sthCase=="sth") =>
          //do some more checks etc

          //eventually arrive at the "true" branch
               ... case valid => true

        case sthElse if (sthCase=="bla") => //some more code etc
        case _ => false
      }
    case _ => false
  }
}

我知道这个例子的编写方式可能与我编写 Java 的方式相同,但是如果我不想返回 true 或 false 我想将该值分配给一个变量,即:val valid = (input.trim.length < 1) match ...那么这是唯一的方法,因为你不能重新分配给 val。我可以使用var而不是val,但我会使用 Java 而不是 Scala。

问题,重申: 所以问题是,箭头反模式是在 Scala 中做事的方式还是我错过了什么?在 Scala 中是否有更好的方法来完成我刚刚编写的内容(请记住,我希望将匹配语句结果分配给val变量)。

4

4 回答 4

4

请注意,只要代码的所有部分都是单入口/单出口,您始终可以在 Scala 中使用分解。这是因为 Scala 中的嵌套函数可以访问外部函数的局部变量。例如:

def isValid(input: String): Boolean = {
  def testLength = input.trim.length >= 1
  def testSomething = input.substring(0, 3) == "sth"

  return testLength && testSomething
}

因此,您可以根据需要将任何类似箭头的结构分解为其子组件。

另请注意,使用 match 测试布尔值或比较某些东西是否相等是多余的。

于 2013-06-05T15:45:41.437 回答
3

return如果函数中的 s太多,则缺少函数:

def isValid(s: String): Boolean = {
  def isLengthValid = s.trim().length() > 0
  def shouldNotContainsSomething = s.substring(0, 3) != "sth"

  isLengthValid && shouldNotContainsSomething
}
于 2013-06-05T15:47:01.833 回答
3

您的 java 示例可以轻松转换为if/elsein scala,无需显式返回,也无需任何额外的嵌套级别。

def isValid(input: String) = {
  if (input.trim().length() <1) false
  else if (input.substring(0,3).equals("sth")) false
  else true
}

if/else就像 scala 中的一切都是一个表达式并且有一个返回值,所以你不妨将它用于赋值:

val isValid =
  if (input.trim().length() <1) false
  else if (input.substring(0,3).equals("sth")) false
  else true

或者在这种情况下你也可以简单地写

val isValid = (input.trim().length() >= 1) && (!input.substring(0,3).equals("sth"))
于 2013-06-05T15:06:43.870 回答
2

不要仅仅因为某些规则这么说就去做货物崇拜。Scala 的好处是你可以两全其美——例如,有时以可变风格编写的算法比不可变风格更清晰。

顺便说一句,还有一种require方法,通常用于验证失败(但它会出现异常)。

于 2013-06-05T15:09:06.817 回答