“a”怎么说;案例;匿名函数在Scala中真的有效吗?
德斯卡拉“a”怎么说;案例;匿名函数在Scala中真的有效吗?,scala,pattern-matching,Scala,Pattern Matching,德斯卡拉 scala> val f1: ((Int, Int)) => Int = { case (a, b) => a + b } f1: ((Int, Int)) => Int = <function1> scala> val f2: (Int, Int) => Int = { case (a, b) => a + b } f2: (Int, Int) => Int = <function2> 好的 scala>de
scala> val f1: ((Int, Int)) => Int = { case (a, b) => a + b }
f1: ((Int, Int)) => Int = <function1>
scala> val f2: (Int, Int) => Int = { case (a, b) => a + b }
f2: (Int, Int) => Int = <function2>
好的
scala>def takesIntInt2Int(fun:(Int,Int)=>Int)=fun(100200)
takesintin2int:(乐趣:(Int,Int)=>Int)Int
scala>deftakestuple2int(fun:((Int,Int))=>Int=fun(100200)
takesTuple2Int:(乐趣:((Int,Int))=>Int)Int
scala>TakesInt2Int(f2)
res4:Int=300
scala>TakesInt2Int(f1)
:10:错误:类型不匹配;
找到:((Int,Int))=>Int
必需:(Int,Int)=>Int
TakesInt2Int(f1)
^
scala>takesTuple2Int(f1)
res6:Int=300
scala>takesTuple2Int(f2)
:10:错误:类型不匹配;
发现:(Int,Int)=>Int
必需:((Int,Int))=>Int
takesTuple2Int(f2)
对。现在,看看这个
scala> takesTuple2Int { case (a, b, c) => a + b + c }
<console>:9: error: constructor cannot be instantiated to expected type;
found : (T1, T2, T3)
required: (Int, Int)
takesTuple2Int { case (a, b, c) => a + b + c }
^
scala> takesIntInt2Int { case (a, b, c) => a + b + c }
<console>:9: error: constructor cannot be instantiated to expected type;
found : (T1, T2, T3)
required: (Int, Int)
takesIntInt2Int { case (a, b, c) => a + b + c }
scala>takesTuple2Int{case(a,b,c)=>a+b+c}
:9:错误:无法将构造函数实例化为预期类型;
发现:(T1、T2、T3)
必需:(Int,Int)
takesTuple2Int{case(a,b,c)=>a+b+c}
^
scala>takesIntInt2Int{case(a,b,c)=>a+b+c}
:9:错误:无法将构造函数实例化为预期类型;
发现:(T1、T2、T3)
必需:(Int,Int)
takesIntInt2Int{case(a,b,c)=>a+b+c}
比如,srsly?o_o这两个都会导致必需:(Int,Int)
错误
那么为什么要在这种匿名函数中使用
case
?请参见Scala参考()的第8.5节。表达式{case(a,b)=>a+b}
根据预期的类型进行不同的解释。在您对f1
的定义中,它创建了一个PartialFunction[(Int,Int),Int]
,该函数被转换为Function1[(Int,Int),Int]
,即((Int,Int))=>Int
而在f2
的定义中,它创建了Function2[Int,Int,Int]
,即(Int,Int)=>Int
这两种解释与在匿名函数中通常使用case的两种情况有关
一种是编写接受元组并处理其组件的匿名函数,就像您在f1
中所做的那样。例如,在map
上传递给foreach
或map
方法的函数,例如map(1->2,3->4)map{case(k,v)=>k+v}
第二种方法是编写一个匿名函数,该函数对其唯一参数进行匹配。您的f2
正在这样做,但不是以任何有用的方式。例如,传递给collect
的匿名函数,例如列表(1,-2,3)collect{case x if x>0=>-x}
请注意,这两者可以结合使用,也就是说像f1
这样的函数也可以进行复杂的匹配。例如,Map(1->2,3->4)收集{case(k,v),如果k<2=>v}
编辑:res2
由于元组化而工作。如果应用程序没有进行类型检查,编译器将在失败之前尝试将参数包装在元组中
但这仅仅是为了应用而尝试的;正如你所发现的,这不是一般的转换。它不会尝试将一个值Function2[a,B,C]
升级到Function1[(a,B,C)
如果不使用case
关键字就可以完成所有这一切,那就太好了。从普通开发人员的角度来看,为什么函数和部分函数在语法上存在差异?@MichałRus说实话,这总是让我有点困扰。Haskell和Clojure具有更简单的语法,用于直接在函数参数上表示模式匹配。
scala> def takesIntInt2Int(fun: (Int, Int) => Int) = fun(100, 200)
takesIntInt2Int: (fun: (Int, Int) => Int)Int
scala> def takesTuple2Int(fun: ((Int, Int)) => Int) = fun(100, 200)
takesTuple2Int: (fun: ((Int, Int)) => Int)Int
scala> takesIntInt2Int(f2)
res4: Int = 300
scala> takesIntInt2Int(f1)
<console>:10: error: type mismatch;
found : ((Int, Int)) => Int
required: (Int, Int) => Int
takesIntInt2Int(f1)
^
scala> takesTuple2Int(f1)
res6: Int = 300
scala> takesTuple2Int(f2)
<console>:10: error: type mismatch;
found : (Int, Int) => Int
required: ((Int, Int)) => Int
takesTuple2Int(f2)
scala> takesTuple2Int { case (a, b, c) => a + b + c }
<console>:9: error: constructor cannot be instantiated to expected type;
found : (T1, T2, T3)
required: (Int, Int)
takesTuple2Int { case (a, b, c) => a + b + c }
^
scala> takesIntInt2Int { case (a, b, c) => a + b + c }
<console>:9: error: constructor cannot be instantiated to expected type;
found : (T1, T2, T3)
required: (Int, Int)
takesIntInt2Int { case (a, b, c) => a + b + c }