3

在使用 Java 或 C++ 编程时,我多次遇到一个简单的模式,自定义控制结构可以减少我代码中的样板。它类似于:

 if( Predicate ){
     Action

     return Value
 }

也就是说,一个“return if”类型的语句。我尝试过使用类似签名的函数创建函数,foo[A,B]( pred:((A,A)=>Boolean), value:Option[B] )但最后我检查是否返回了 Some 或 None。我被return声明绊倒了。

是否有一种在函数式语言或更具体地说是 Scala 中制作此类控制结构的继承方式?

编辑:

我的描述不是很清楚,这让试图帮助我的人感到困惑。myfoo不起作用的关键原因是它不能使包含函数的评估短路。那是

def intersect( geometry:Geometry, reference:Geometry ):Geometry = {
    return_if( withinBounds( geometry, projection ), logToString( logger, "Geometry outside " + projection.toString ), EmptyGeometry() )
    return_if( topologicallyCorrect( geometry ), intersect( correct( geometry ), reference )
    //rest of the function
}

并且仍然允许在return_if.

4

4 回答 4

7

我会使用部分函数:

def whatevs[A, B](options : PartialFunction[(A,A), B]) : Option[B] = {
  val myInput = generateInput
  if(options.isDefined(myInput)) {
    Some(options(myInput))
  } else None
}

那么您的用法可能如下所示:

whateves {
   case (x,y) if x > y =>   "Biggerz"
   case (x,y) if y > x =>   "Tiny!"
}

通常,您不需要 return 语句。if-expression 将评估为每个块中使用的最后一个表达式。您可能需要帮助编译器找出 if 表达式的类型结果,但不需要返回。

部分函数是一种在某些条件成立时执行操作的机制。在上面,两个条件是元组中的 x > y 或 y > x。

如果 whatevs 函数不是你所说的,我建议使用原始模式匹配。

于 2010-08-26T14:30:11.650 回答
2

嗯,据我了解,您希望控制结构中的 return 退出它嵌入的函数。

所以在你的例子中它应该退出方法相交?

我不确定那是否可能。因为 return_if 内的 return 将始终退出 return_if 并且我认为没有办法告诉 scala,return 应该退出嵌入的函数 return_if。

我希望我明白你想做什么:)

于 2010-08-26T19:43:58.250 回答
2

看起来您正在使用它作为代码控制流的条件转义

如果它真的是解决问题的最优雅的解决方案,你也可以在 Scala 中执行此操作(只需使用要返回的类型注释方法)。有时代码需要像多级过滤器一样工作,这种模式很适合。

当然,你总是可以嵌套 if 语句,但这会变得很尴尬。

然而,在 Scala 中还有一些其他的事情需要考虑。一罐

methodReturningOption.getOrElse(
  // All the code for the None case goes in here
)

在存在合理默认值的情况下,这通常可以很好地整合不同的分支(或者如果没有默认值,您最终会抛出异常)。

或者,您可以为此滥用模式匹配:

None match {  // Could use a real variable instead of None if it helped
  case _ if (Predicate1) => Action1; Value1
  case _ if (Predicate2) => Action2; Value2
  . . .
  case _ => ErrorHandlingPerhaps
}

但是你也可以用不同的方式来思考你的问题,这样这些谓词就变得不那么有用了。(在不知道更多细节的情况下,我无法提出建议。)

于 2010-08-26T14:22:02.627 回答
1

我不明白你为什么想要这个。这是您要编写的代码:

def intersect( geometry:Geometry, reference:Geometry ):Geometry = {

  return_if( withinBounds( geometry, projection ), 
    logToString( logger, "Geometry outside " + projection.toString ), 
    EmptyGeometry() )

  return_if( topologicallyCorrect( geometry ), 
    intersect( correct( geometry )), 
    reference )

    // rest of the function
}

而这是“普通” Scala 中的样子:

def intersect( geometry:Geometry, reference:Geometry ):Geometry = {

  if (withinBounds( geometry, projection )) {
    logToString( logger, "Geometry outside " + projection.toString )
    return EmptyGeometry() }

  if( topologicallyCorrect( geometry )) {
    intersect( correct( geometry ))
    return reference }

  //rest of the function
}

对我来说,“普通”版本看起来更清晰。一方面,它非常清楚地返回了什么。它甚至更冗长。我怀疑你有一个更复杂的用例。如果您向我们展示这一点,也许我们将能够指导您使用更合适的模式。

于 2010-08-26T23:14:56.270 回答