在使用Java或C ++进行编程时,有很多次我遇到了一个简单的模式,自定义控件结构可以减少代码中的样板。它类似于:
if( Predicate ){
Action
return Value
}
即“return if”类型语句。我尝试使用foo[A,B]( pred:((A,A)=>Boolean), value:Option[B] )
这样的签名来创建函数,但最后我会检查是否已经返回Some或None。我被return
声明绊倒了。
是否有继承方式在函数式语言或更具体的Scala中创建这样的控制结构?
修改
我的描述并不那么明确,而且那些试图帮助我的人感到困惑。我的foo
不起作用的关键原因是它不能使包含函数的评估短路。那是
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
内的尾递归。
答案 0 :(得分: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> 1。 y或y> x来自元组。
如果whatevs功能不是你所说的那么我建议使用原始模式匹配。
答案 1 :(得分: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
}
但是你也可能以不同的方式思考你的问题,以便这些谓词变得不那么有用。 (不知道更多细节,我无法提出建议。)
答案 2 :(得分:2)
嗯,据我所知,你希望控制结构中的返回退出它所嵌入的函数。
所以在你的例子中它应该退出方法相交?
我不确定这是否可能。因为return_if中的返回总是会退出return_if并且我认为没有办法告诉scala,返回应该退出函数return_if嵌入。
我希望我明白你想做什么:)
答案 3 :(得分: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
}
对我而言,“普通”版本看起来更清晰。一方面,它非常清楚返回的是什么。它甚至不是更冗长。我怀疑你有一个更复杂的用例。如果您告诉我们,也许我们可以指导您更合适的模式。