[英]In Scala, why can't I partially apply a function without explicitly specifying its argument types?
如您所願,這將產生一個匿名函數(f是具有三個參數的函數):
f(_, _, _)
我不明白的是為什么它不能編譯,而是給出“缺少參數類型”錯誤:
f(_, _, 27)
相反,我需要明確指定下划線的類型。 考慮到函數f的參數類型是什么,Scala是否應該能夠推斷出它們?
以下參考是Scala語言規范
請考慮以下方法:
def foo(a: Int, b: Int) = 0
Eta Expansion可以將其轉換為(Int, Int) => Int
類型的值。 在以下情況下調用此擴展:
a) _
代替參數列表(方法值(第6.7節))
val f = foo _
b)省略參數列表,表達式的期望類型為函數類型(第6.25.2節):
val f: (Int, Int) => Int = foo
c)每個參數都是_
(“匿名函數的占位符語法”的特殊情況 (第6.23節))
val f = foo(_, _)
表達式foo(_, 1)
不符合Eta擴展要求; 它只是擴展為(a) => foo(a, 1)
(第6.23節)。 常規類型推斷不會嘗試找出a: Int
。
如果您正在考慮部分應用程序,我認為這只能通過多個參數列表來實現 (而您只有一個):
def plus(x: Int)(y: Int) = x + y //x and y in different parameter lists
val plus10 = plus(10) _ //_ indicates partial application
println(plus10(2)) //prints 12
雖然我完全不了解您描述的語法,但是您的示例很有趣,而且看來您可以使用單個參數列表來部分應用程序:
scala> def plus2(x: Int, y: Int) = x + y
plus2: (x: Int,y: Int)Int
scala> val anon = plus2(_,_)
anon: (Int, Int) => Int = <function2>
scala> anon(3, 4)
res1: Int = 7
因此,編譯器可以清楚地推斷出Int
類型!
scala> val anon2 = plus2(20,_)
<console>:5: error: missing parameter type for expanded function ((x$1) => plus2(20, x$1))
val anon2 = plus2(20,_)
^
嗯,奇怪! 我似乎無法使用單個參數列表進行部分應用。 但是,如果我聲明第二個參數的類型,則可以有部分應用!
scala> val anon2 = plus2(20,_: Int)
anon2: (Int) => Int = <function1>
scala> anon2(24)
res2: Int = 44
編輯 -我會觀察到的一件事是,似乎以下兩個縮寫是等效的,在這種情況下,這顯然不是“部分應用程序”,而更像是“函數指針”
val anon1 = plus2(_,_)
val anon2 = plus2 _
我認為這是因為重載使編譯器無法推斷類型:
scala> object Ashkan { def f(a:Int,b:Int) = a; def f(a:Int,b:String) = b; }
defined object Ashkan
scala> Ashkan.f(1,2)
res45: Int = 1
scala> Ashkan.f(1,"Ashkan")
res46: String = Ashkan
scala> val x= Ashkan.f _
<console>:11: error: ambiguous reference to overloaded definition,
both method f in object Ashkan of type (a: Int, b: String)String
and method f in object Ashkan of type (a: Int, b: Int)Int
match expected type ?
val x= Ashkan.f _
^
scala> val x= Ashkan.f(_,_)
<console>:11: error: missing parameter type for expanded function ((x$1, x$2) => Ashkan.f(x$1, x$2))
val x= Ashkan.f(_,_)
^
<console>:11: error: missing parameter type for expanded function ((x$1: <error>, x$2) => Ashkan.f(x$1, x$2))
val x= Ashkan.f(_,_)
^
scala> val x= Ashkan.f(_,"Akbar")
<console>:11: error: missing parameter type for expanded function ((x$1) => Ashkan.f(x$1, "Akbar"))
val x= Ashkan.f(_,"Akbar")
^
scala> val x= Ashkan.f(1,_)
<console>:11: error: missing parameter type for expanded function ((x$1) => Ashkan.f(1, x$1))
val x= Ashkan.f(1,_)
^
scala> val x= Ashkan.f(1,_:String)
x: String => String = <function1>
我認為這是所有代碼轉換引起的邊界情況之一,因為這涉及創建匿名函數,該函數將調用定向到原始方法。 類型用於外部匿名函數的參數。 實際上,您可以指定任何子類型,即
val f = foo(_: Nothing, 1)
即使這樣會編譯
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.