The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
Uncover and score the usages of the underscore
1. Uncover and Score
the Usages
of the Underscore
Rhein-Main Scala Meetup 02/02/16
Franck Valentin
2. var initialization to default value = _
class Foo
class DefaultValue[T] {
// 1. Declare instance vars with default values:
// -----------------------------------------------------------
var int:Int = _ // 0
var double: Double = _ // 0.0
var boolean: Boolean = _ // false
var foo: Foo = _ // null
// 2. It works also for type parameters:
// -----------------------------------------------------------
var t:T = _ // new DefaultValue[String].t == null
// new DefaultValue[Long].t == 0
// 3. Not allowed in methods
// -----------------------------------------------------------
def f() {
// Doesn't compile. "Local variables must be initialized"
// var x:Int = _ e
}
...
3. var initialization to default value = _
...
// 4. Note also:
// -----------------------------------------------------------
var any:Any = _ // null
var anyRef:AnyRef = _ // null
var anyVal:AnyVal = _ // null
var n:Null = _ // null
// Should the following compile as ‘Nothing’ doesn’t have any value?
// Instead, there is a java.lang.NullPointerException at runtime
// when trying to use it.
var nothing:Nothing = _
}
4. Tuples ._1
case class Bar(v:Int)
class Tuples {
// _ is a part of the name of tuple getters (_1, _2, ...)
// -----------------------------------------------------------
val myTuple = ("a", 3.141, Bar(0)) // An instance of Tuple3[String, Double, Foo]
val anotherTuple = Tuple2("b", 2.718)
}
// new Tuples().myTuple._1 == "a"
// new Tuples().myTuple._2 == 3.141
// new Tuples().myTuple._3 == Foo(0)
- _ can be part of a method name (more about that later)
- _1, _2, … _22 for Tuple
5. Unused variables _ =
case class Bar(par1: Int, par2: Int, par3: Int)
class UnusedVariables(bar: Bar) {
// 1. Unused variable (no real practical usage here!)
// -----------------------------------------------------
var _ = "whatever"
// 2. Unused variables in extractors
// -----------------------------------------------------
val myTuple = ("a", 3.141, "b")
val (_, pi, myString) = myTuple
// Not only for tuples:
val Bar(barP1, _, barP3) = bar
}
val uv = new UnusedVariables(Bar(10, 20, 30))
// uv.pi == 3.14
// uv.myString == "b"
// uv.barP1 == 10
// uv.barP3 30
6. Unused variables _ =
object UnusedVariables2 extends App {
val prefixes = List("p1", "p2")
val strings = List("aa", "bb", "cc")
val suffixes = List("s1", "s2")
// 3. Unused variables can be useful to debug for comprehensions.
// ----------------------------------------------------------------
val stringsWithPrefixesAndSuffixes = for {
prefix <- prefixes
string <- strings
stringWithPrefix = prefix + ">" + string
//println(stringWithPrefix) // This doesn't compile!
_ = println(stringWithPrefix)
suffix <- suffixes
stringWithPrefixAndsuffix= stringWithPrefix + "<" + suffix
} yield stringWithPrefixAndsuffix
// Because of the way Scala translates for comprehensions to foreach/map/flatMap/filter/withFilter
// http://docs.scala-lang.org/tutorials/FAQ/yield.html
// scalac -Xprint:parser UnusedVariables2.scala
}
8. Imports: wildcards and Hiding => _
object Imports1 {
// 1. _ Similar to * in Java
// ------------------------------------------------------------------
import java.util._
val uuid = UUID.randomUUID()
val date = new Date()
}
object Imports2 {
// 2. Add an exception (everything from java.util but Date and Calendar)
// ------------------------------------------------------------------
import java.util.{Date => _, Calendar => _, _}
val uuid = UUID.randomUUID()
// val date = new Date() // Doesn't compile.
}
...
9. Imports: wildcards and Hiding => _
...
object Imports3 {
// 3. Import all the members of an object (works with exceptions too)
// ------------------------------------------------------------------
object MyObj {
val m1: Int = 1
val m2: String = "a"
val m3: Double = 1.0
}
import MyObj.{m3 => _, _}
println(m1) // Instead of MyObj.m1
println(m2) // Instead of MyObj.m2
// println(MyObj.m3) // Doesn't compile.
}
10. Varargs (splat operator) _*
// 1. _* passes a sequence as multiple parameters
// -------------------------------------------------------------
def processParams(params: String*) = params.mkString(",")
processParams("p1", "p2") // == "p1,p2"
val parameters = List("param1", "param2", "param3")
//processParams(parameters) // Error: Type mismatch. expected:String, actual:Seq[String]
processParams(parameters: _*) // == param1,param2,param3
// 2. _* works in pattern matching too
// -------------------------------------------------------------
val res = parameters match {
case Seq(p1) =>
s"Only one element $p1"
case Seq(p1, seqOfStrings @ _*) =>
s"First elt is '$p1' and the rest is the sequence '${seqOfStrings}'"
}
println(res) // == First elt is 'param1' and the rest is the sequence List(param2, param3)'
11. Anonymous Function Placeholder _ + _
// 1. A placeholder for the parameters in an anonymous function
// -------------------------------------------------------------
val list = List(1, 2, 3, 4)
val by2 = list map (x => x * 2)
val alsoBy2 = list map (_ * 2)
// 2. It works for several parameters as well
// -------------------------------------------------------------
val sum = list reduceLeft ((a, b) => a + b)
val alsoSum = list reduceLeft (_ + _)
def printFctResult(tuple:(Int, String, Double), fct:(Int, String, Double) => String) = {
println(fct(tuple._1, tuple._2, tuple._3))
}
printFctResult((2, "a", 3.0), (i,s,d) => i + s + d) // == "2a3.0"
printFctResult((2, "a", 3.0), _ + _ + _) // It begins to be obscure!
def fct(i: Int, s: String, d: Double): String = s"${i * d} $s"
printFctResult((2, "a", 3.0), (i,s,d) => fct(i,s,d)) // == "6.0 a"
printFctResult((2, "a", 3.0), fct(_,_,_))
12. Pattern Matching case _
case class MyClass(nameOpt: Option[String], ints: List[Int])
def showMatch(c: Any) {
c match {
// Wilcard in a class parameter
case MyClass(None, _) => println("MyClass without any name.")
// Wilcard in a nested class
case MyClass(_, List(_)) => println("MyClass with only one element.")
// Wilcard in a nested class and splat operator
case MyClass(_, List(_, _*)) => println("MyClass with more than one element.")
// Wildcard on the type
case l:List[_] => println("It's a list !")
// Matches everything else
case _ => println("Matches everything else.")
}
}
showMatch(MyClass(None, List(1,2))) // == "MyClass without any name."
showMatch(MyClass(Some("c1"), List(1))) // == "MyClass with only one element."
showMatch(MyClass(Some("c2"), List(1,2,3))) // == "MyClass with more than one element."
showMatch(List("a", "b", "c")) // == "It's a list !"
showMatch(Set("a", "b", "c")) // == "Matches everything else."
13. Partially Applied Functions g = f(_,_)
// Partially applied function: function where only a few
// arguments are set during its invocation.
def sendMessage(priority: Int, recipient: String, msg: String) {
println(s"$priority: send '$recipient' the message $msg.'")
}
// sendMessageToFred == (Int, String) => Unit
def sendMessageToFred = sendMessage(_: Int, "Fred", _: String)
sendMessageToFred(1, "Hi Bro!")
// sendImportantMsgToFred == (String) => Unit
def sendImportantMsgToFred = sendMessage(0, "Fred", _: String)
sendImportantMsgToFred("An important message.")
14. Eta Expansion v = f _
// "Eta-expansion converts an expression of method type to an equivalent expression
// of function type."
// method: a member of the type the class represents.
// function: value of a Function[] type.
// Assign a method to a variable:
// ----------------------------------------------------------------------------
case class MyClass() {
def f1(int: Int):Unit = println(int)
val constant = 35
def f2(int1: Int, int2: Int):String = (int1 + int2 + constant).toString
}
// valF1: Int => Unit = <function1> (Function1[Int, Unit])
val valF1 = MyClass().f1 _
valF1(1)
// valF2: (Int, Int) => String = <function2> (Function2[Int, Int, String)
val valF2 = MyClass().f2 _
valF2(5, 2)
...
15. Eta Expansion v = f _
…
case class MyOtherClass() {
def f(g: () => Int):Int = 1
def f(i:Int):Int = 2
}
def g() = 3
MyOtherClass().f(g) // == 2
// You have to write the _ whenever the compiler is not explicitly expecting
// a Function object.
MyOtherClass().f(g _) // == 1. _ 'asks' the compiler to treat g a a Function object.
16. Existential Types
// Existential type: express that you have a type (e.g. List, Array) with an unknown
// element type (an unknown "type parameter") : List[<I don't know>].
// "List[<I don't know>]" could be rephrased as "List[T] forSome {type T}"
//
def count1(l: List[T] forSome {type T}) = l.size
count1(List(1, 2, 3))
count1(List("a", "b"))
// Equivalent to:
def count2(l: List[_]) = l.size
count2(List(1, 2, 3))
count2(List("a", "b"))
// It works for higher kinded types as well.
// Higher kinded type : A type constructor that takes type constructor(s)
// Higher kinded type 'Iterable' has the type constructor 'Container'.
trait Iterable[A, Container[_]] {
def map[B](f: A => B): Container[B]
def filter(p: A => Boolean): Container[A]
}
17. Identifier Names Ending with an operator _!
// 1. alphanumeric + _ + operator identifier (+, ++, :, ?, ~, # :> ...)
// ----------------------------------------------------------------------------
trait WhatATrait_! {
def isItUsefult_?()
// 2. _ followed by a letter(s), digit(s), or underscore(s).
// --------------------------------------------------------------------------
def _abc()
def _123()
def __()
}
18. Assignment Operator def f_=( )
// Special case for an identifier name ending with _=
// A way to define getters and setters.
// ------------------------------------------------------------------
class MyClass {
private var myInt0:Int = _
// Getter:
def myInt:Int = myInt0
// Setter:
def myInt_=(i:Int) {
require(i>0)
println(s"I'm setting myInt = $i")
myInt0 = i
}
}
val myClass = new MyClass
myClass.myInt = 5 // Setter: Desugared into myClass.myInt_=(5)
println(myClass.myInt) // Getter
myClass.myInt = -1 // java.lang.IllegalArgumentException: requirement failed