我在理解函数文字中的下划线时遇到了麻烦.
val l = List(1,2,3,4,5)
l.filter(_ > 0)
Run Code Online (Sandbox Code Playgroud)
工作良好
l.filter({_ > 0})
Run Code Online (Sandbox Code Playgroud)
工作良好
l.filter({val x=1; 1+_+3 > 0}) // ie you can have multiple statements in your function literal and use the underscore not just in the first statement.
Run Code Online (Sandbox Code Playgroud)
工作良好
但是:
l.filter({val x=_; x > 0})
e>:1: error: unbound placeholder parameter
l.filter({val x=_; x > 0})
Run Code Online (Sandbox Code Playgroud)
我无法将_变量分配给变量,即使以下是合法函数文字:
l.filter(y => {val x=y; x > 0})
Run Code Online (Sandbox Code Playgroud)
工作良好.
是什么赋予了?我的'val x = _'被解释为别的吗?谢谢!
实际上,你必须备份一步.
你误解了牙箍是如何工作的.
scala> val is = (1 to 5).toList
is: List[Int] = List(1, 2, 3, 4, 5)
scala> is map ({ println("hi") ; 2 * _ })
hi
res2: List[Int] = List(2, 4, 6, 8, 10)
Run Code Online (Sandbox Code Playgroud)
如果println传递给函数的一部分map,你会看到更多的问候.
scala> is map (i => { println("hi") ; 2 * i })
hi
hi
hi
hi
hi
res3: List[Int] = List(2, 4, 6, 8, 10)
Run Code Online (Sandbox Code Playgroud)
你的额外大括号是一个块,这是一些语句后跟一个结果表达式.结果expr是函数.
一旦你意识到只有结果expr具有预期的函数类型map,你就不会想到在前面的语句中使用下划线,因为裸下划线需要预期的类型来确定下划线的含义.
这是类型系统告诉你,你的下划线不在正确的位置.
附录:在评论中你问:
如何使用下划线语法将函数文字的参数绑定到变量
这是一个"愚蠢"的问题,请原谅这个表达方式?
下划线是这样你不必为参数命名,然后你说你想要命名它.
一个用例可能是:传入参数很少,但我只想命名其中一个参数.
scala>(0 /:is)(_ + _)res10:Int = 15
scala>(0 /:is){case(acc,i)=> acc + 2*i} res11:Int = 30
这不起作用,但人们可能想知道为什么.也就是说,我们知道折叠需要什么,我们想用arg来应用.哪个arg?无论在部分应用的部分功能之后剩下什么.
scala>(0 /:is)(({case(_,i)=> _ + 2*i})(_))
要么
scala>(0 /:is)(({case(_,i)=> val d = 2*i; _ + 2*d})(_))
SLS 6.23"匿名函数的占位符语法"提到"expr"边界,当你必须知道下划线代表什么时 - 它本身不是范围.如果您提供下划线的类型归属,它仍会抱怨预期的类型,可能是因为类型推断从左到右.
| 归档时间: |
|
| 查看次数: |
1394 次 |
| 最近记录: |