箭头反模式是Scala中的标准

时间:2013-06-05 14:54:47

标签: scala coding-style nested standards anti-patterns

问题首先:箭头反模式是否是在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,我想将该值赋给变量ie:val valid = (input.trim.length < 1) match ...那么这是唯一的方法这样做,因为你无法重新分配给val。我可以使用var代替val,但之后我会使用Java而不是Scala。

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

4 个答案:

答案 0 :(得分:4)

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

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

  return testLength && testSomething
}

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

另请注意,使用匹配来测试布尔值或比较某些内容是否过分是显而易见的。

答案 1 :(得分:3)

您可以轻松地将您的Java示例转换为scala中的if/else,而无需显式返回,也无需任何其他嵌套级别。

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"))

答案 2 :(得分:3)

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

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

  isLengthValid && shouldNotContainsSomething
}

答案 3 :(得分:2)

不要做货物崇拜just because some rule says so。 Scala的好处是你可以从两个世界中做到最好 - 例如有时用可变风格写的算法比不可变的风格要清晰得多。

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