暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Scala: Underscore

楠爸自习室 2020-01-02
609

In this small blog, we will try to summarize the usage of underscore in Scala.

Function

Convert method to function

Sometimes we want to assign a method of class/object to a function variable, then we can use underscore to do it.

object Sum {
def sum(x: Int, y: Int) = x + y
}

val f:(Int, Int) => Int = Sum.sum // error
val f:(Int, Int) => Int = (Sum.sum _) // (Int, Int) => Int

Inline function(Lambda)

Lambda is an important feature in Scala, it can make our code short and clean, let's see how we can use it.

(Some(1), Some(2)).mapN(_+_) //_ + _ equals to  (a,b) => a + b
List(1, 2, 3).map(_+1) // _ + 1 equals to (a) => a + 1

def PlusOne(x:Int) = x + 1
List(1, 2, 3).map(PlusOne(_)) // PlusOne(_) equals to (a) => PlusOne(a)
List(1, 2, 3).map(PlusOne) // For the function with same signature, you can just type the name

def Add(x:Int, y:Int) = x + y
List(1,2,3).map(Add(_, 1)) // Add(_, 1) equals to (a) => Add(a, 1)
List(x:Int => x+1, x:Int => x+2).map(_(1)) // _(1) equals to (f) => f(1)

Ok, it's just a simple replacement game. The number of underscore means the number of function parameter, then compiler just use the parameter to replace the underscore with the same index.

Ignore input

Sometimes we don't use some input parameter, but the compiler will give a warning which say some variable has not been used. To eliminate the warning and reduce the likelihood of error, we can use underscore to ignore the input parameter.

List(1,2,3).map(_ => 0)

for {
_ <- List(1, 2, 3)
} yield 0

Ignore output

This is a very edge case. When we don't care about the result of last expression, we can use underscore to ignore it.

def dummyAdd(x: Int, y: Int): Unit = {
val _ = x + y
}

Pattern matching

Sometimes we don't care about the value of matching variable and also don't want compiler to raise warning, then we can use underscore to match any value.

case class User(name:String)
val user1 = User("Bob")

user1 match {
case User(_) => println("I don't care about what's the name")
case _ => println("But it must be a user")
}

Type parameter

We know higher kind type(such as Option, Either, List...) can't be instanced directly. It looks like a function of type which accepts another type as parameter and then returns a new type which can be instanced.

Sometimes we need to use the higher kind type as type parameter, to separate them from normal type, we need to tell compiler how many types they need to create a new type which can be instanced. Then we can use underscore to do it, the number of underscores means the number of type they need.

def process[M[_], A](v:M[A]):Unit =
println(
"""
I only accept a value whose type is composed by M and A,
and M must have a hole which mean it can accept another type parameter"

"""
)


文章转载自楠爸自习室,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论