标签:
Scala 作为一门函数式编程语言,对习惯了指令式编程语言的同学来说,会不大习惯,这里除了思维方式之外,还有语法层面的,比如 underscore(下划线)就会出现在多种场合,令初学者相当疑惑,今天就来总结下 Scala 中下划线的用法。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
|
1 、存在性类型:Existential types def foo(l : List[Option[ _ ]]) = ... 2 、高阶类型参数:Higher kinded type parameters case class A[K[ _ ],T](a : K[T]) 3 、临时变量:Ignored variables val _ = 5 4 、临时参数:Ignored parameters List( 1 , 2 , 3 ) foreach { _ = > println( "Hi" ) } 5 、通配模式:Wildcard patterns Some( 5 ) match { case Some( _ ) = > println( "Yes" ) } match { case List( 1 , _ , _ ) = > " a list with three element and the first element is 1" case List( _ *) = > " a list with zero or more elements " case Map[ _ , _ ] = > " matches a map with any key type and any value type " case _ = > } val (a, _ ) = ( 1 , 2 ) for ( _ <- 1 to 10 ) 6 、通配导入:Wildcard imports import java.util. _ 7 、隐藏导入:Hiding imports // Imports all the members of the object Fun but renames Foo to Bar import com.test.Fun.{ Foo = > Bar , _ } // Imports all the members except Foo. To exclude a member rename it to _ import com.test.Fun.{ Foo = > _ , _ } 8 、连接字母和标点符号:Joining letters to punctuation def bang _ !(x : Int) = 5 9 、占位符语法:Placeholder syntax List( 1 , 2 , 3 ) map ( _ + 2 ) _ + _ ( ( _: Int) + ( _: Int) )( 2 , 3 ) val nums = List( 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 ) nums map ( _ + 2 ) nums sortWith( _ > _ ) nums filter ( _ % 2 == 0 ) nums reduceLeft( _ + _ ) nums reduce ( _ + _ ) nums reduceLeft( _ max _ ) nums.exists( _ > 5 ) nums.takeWhile( _ < 8 ) 10 、偏应用函数:Partially applied functions def fun = { // Some code } val funLike = fun _ List( 1 , 2 , 3 ) foreach println _ 1 to 5 map ( 10 * _ ) //List("foo", "bar", "baz").map(_.toUpperCase()) List( "foo" , "bar" , "baz" ).map(n = > n.toUpperCase()) 11 、初始化默认值:default value var i : Int = _ 12 、作为参数名: //访问map var m 3 = Map(( 1 , 100 ), ( 2 , 200 )) for (e<-m 3 ) println(e. _ 1 + ": " + e. _ 2 ) m 3 filter (e = >e. _ 1 > 1 ) m 3 filterKeys ( _ > 1 ) m 3 .map(e = >(e. _ 1 * 10 , e. _ 2 )) m 3 map (e = >e. _ 2 ) //访问元组:tuple getters ( 1 , 2 ). _ 2 13 、参数序列:parameters Sequence _ *作为一个整体,告诉编译器你希望将某个参数当作参数序列处理。例如 val s = sum( 1 to 5 :_ *)就是将 1 to 5 当作参数序列处理。 //Range转换为List List( 1 to 5 :_ *) //Range转换为Vector Vector( 1 to 5 : _ *) //可变参数中 def capitalizeAll(args : String*) = { args.map { arg = > arg.capitalize } } val arr = Array( "what‘s" , "up" , "doc?" ) capitalizeAll(arr : _ *) |
这里需要注意的是,以下两种写法实现的是完全不一样的功能:
1
2
3
|
foo _ // Eta expansion of method into method value foo( _ ) // Partial function application |
Example showing why foo(_) and foo _ are different:
1
2
3
4
5
6
7
8
|
trait PlaceholderExample { def process[A](f : A = > Unit) val set : Set[ _ = > Unit] set.foreach(process _ ) // Error set.foreach(process( _ )) // No Error } |
In the first case, process _ represents a method; Scala takes the polymorphic method and attempts to make it monomorphic by filling in the type parameter, but realizes that there is no type that can be filled in for A that will give the type (_ => Unit) => ? (Existential _ is not a type).
In the second case, process(_) is a lambda; when writing a lambda with no explicit argument type, Scala infers the type from the argument that foreach expects, and _ => Unit is a type (whereas just plain _ isn‘t), so it can be substituted and inferred.
This may well be the trickiest gotcha in Scala I have ever encountered.
Refer:
[1] What are all the uses of an underscore in Scala?
http://stackoverflow.com/questions/8000903/what-are-all-the-uses-of-an-underscore-in-scala
[2] Scala punctuation (AKA symbols and operators)
[3] Scala中的下划线到底有多少种应用场景?
http://www.zhihu.com/question/21622725
[4] Strange type mismatch when using member access instead of extractor
[5] Scala简明教程
http://colobu.com/2015/01/14/Scala-Quick-Start-for-Java-Programmers/
标签:
原文地址:http://www.cnblogs.com/shexinwei/p/4649745.html