“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 }