Scala 声明空模式匹配函数
如何声明空/无大小写模式匹配函数以满足类型定义?我很高兴函数在调用时抛出运行时异常 我正在处理,其中有一个工作函数,它对给定Scala 声明空模式匹配函数,scala,Scala,如何声明空/无大小写模式匹配函数以满足类型定义?我很高兴函数在调用时抛出运行时异常 我正在处理,其中有一个工作函数,它对给定String=>Intmap的树表示的数学表达式执行变量替换。我想调用相同的代码路径,即使在不应该存在变量的情况下(在本例中是在对表达式求导之后),但我找不到一种简洁的方法来满足类型要求。以下是我的完整代码,它可以工作,但感觉不正确: 抽象类树 case类Sum(l:Tree,r:Tree)扩展了Tree case类Var(n:String)扩展了树 case类Const(
String=>Int
map的树表示的数学表达式执行变量替换。我想调用相同的代码路径,即使在不应该存在变量的情况下(在本例中是在对表达式求导之后),但我找不到一种简洁的方法来满足类型要求。以下是我的完整代码,它可以工作,但感觉不正确:
抽象类树
case类Sum(l:Tree,r:Tree)扩展了Tree
case类Var(n:String)扩展了树
case类Const(v:Int)扩展了树
对象计算器模式SPRIME{
def eval(tree:tree,env:String=>Int):Int=树匹配{
案例总和(l,r)=>评估(l,环境)+评估(r,环境)
案例变量(n)=>环境变量(n)
案例常数(v)=>v
}
def eval(tree:tree):Int=eval(tree,{case“ignore”=>-1})
def派生(tree:tree,v:String):tree=树匹配{
案例和(l,r)=>和(推导(l,v),推导(r,v))
案例变量(n)如果(n==v)=>Const(1)
大小写=>Const(0)
}
def main(参数:数组[字符串]):单位={
val env:String=>Int={case“x”=>5 case“y”=>7}
瓦尔树=总和(
总和(常数(7),变量(“y”),
总和(Var(“x”)、Var(“x”))
)
println(评估(树木、环境))
println(派生(树,“x”))
println(eval(派生(树,“x”)))
}
}
正如您所看到的,我有一个虚拟的{case“ignore”=>-1}
来让类型系统满意,代码工作得很好,但我觉得一定有更好的方法来做到这一点。以下是我考虑过的两个备选方案:
eval(tree:tree)
写出一个完整的方法体,而不是尝试调用eval(tree:tree,env:String=>Int)
,但这会重复处理Sum
和Const
案例的代码env
成为可选/联合类型,并允许它抛出NPE这里的惯用方法是什么?有几种方法: 首先,正如jwvh所指出的,您可以通过为两个参数
eval
中的第二个参数使用默认参数来消除单参数eval
接下来的问题是,默认参数应该是什么
env
是一个String=>Int
,它是Function1[-a,+R]
的缩写:参数类型为逆变型,结果类型为协变型。就我们的目的而言,这意味着任何接受超类型String
(包括String
)并导致子类型Int
(包括Int
)的函数都可以工作
既然你说你可以投掷,这是一个合理的默认函数:
{ a: Any => throw new AssertionError(s"shouldn't have looked up $a in the environment") }
假设系统的某些其他组件正在确保,如果在传递给eval
的树中有Var
表达式,则环境中总是有一个适当的条目,这可能是最诚实的做法:系统中重要的事情不是保持不变,因此,试图在你的系统中对此进行推理可能只会让事情变得更糟
该函数之所以有效,是因为它的类型为Any=>Nothing
,它是String=>Int
的子类型:您可以向它传递String
(String
是Any
的子类型),并且它永远不会产生不是Int
或Int
的子类型的结果(它没有结果)
或者,您也可以使用PartialFunction.empty
作为默认值,如果调用它,它将抛出MatchError
。这适用于使用部分函数文字(这就是裸{case…}
块)
所以我会选择其中一个(都有类型Env=String=>Int
)
或
然后将eval
定义为:
def eval(tree: Tree, env: Env = emptyEnv): Int
作为旁注,我强烈建议将树
密封
:
sealed abstract class Tree
这限制了可以定义扩展
树的类的位置,并为执行树的不变量提供了更有力的保证。我将删除第二个eval()
,只需给env
一个默认值\u=>-1
。感谢您分享这些示例!
def eval(tree: Tree, env: Env = emptyEnv): Int
sealed abstract class Tree