Related
I've taken a look at the list of surveys taken on scala-lang.org and noticed a curious question: "Can you name all the uses of “_”?". Can you? If yes, please do so here. Explanatory examples are appreciated.
The ones I can think of are
Existential types
def foo(l: List[Option[_]]) = ...
Higher kinded type parameters
case class A[K[_],T](a: K[T])
Ignored variables
val _ = 5
Ignored parameters
List(1, 2, 3) foreach { _ => println("Hi") }
Ignored names of self types
trait MySeq { _: Seq[_] => }
Wildcard patterns
Some(5) match { case Some(_) => println("Yes") }
Wildcard patterns in interpolations
"abc" match { case s"a$_c" => }
Sequence wildcard in patterns
C(1, 2, 3) match { case C(vs # _*) => vs.foreach(f(_)) }
Wildcard imports
import java.util._
Hiding imports
import java.util.{ArrayList => _, _}
Joining letters to operators
def bang_!(x: Int) = 5
Assignment operators
def foo_=(x: Int) { ... }
Placeholder syntax
List(1, 2, 3) map (_ + 2)
Method values
List(1, 2, 3) foreach println _
Converting call-by-name parameters to functions
def toFunction(callByName: => Int): () => Int = callByName _
Default initializer
var x: String = _ // unloved syntax may be eliminated
There may be others I have forgotten!
Example showing why foo(_) and foo _ are different:
This example comes from 0__:
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.
Note that this example compiles in 2.13. Ignore it like it was assigned to underscore.
From (my entry) in the FAQ, which I certainly do not guarantee to be complete (I added two entries just two days ago):
import scala._ // Wild card -- all of Scala is imported
import scala.{ Predef => _, _ } // Exception, everything except Predef
def f[M[_]] // Higher kinded type parameter
def f(m: M[_]) // Existential type
_ + _ // Anonymous function placeholder parameter
m _ // Eta expansion of method into method value
m(_) // Partial function application
_ => 5 // Discarded parameter
case _ => // Wild card pattern -- matches anything
val (a, _) = (1, 2) // same thing
for (_ <- 1 to 10) // same thing
f(xs: _*) // Sequence xs is passed as multiple parameters to f(ys: T*)
case Seq(xs # _*) // Identifier xs is bound to the whole matched sequence
var i: Int = _ // Initialization to the default value
def abc_<>! // An underscore must separate alphanumerics from symbols on identifiers
t._2 // Part of a method name, such as tuple getters
1_000_000 // Numeric literal separator (Scala 2.13+)
This is also part of this question.
An excellent explanation of the uses of the underscore is Scala _ [underscore] magic.
Examples:
def matchTest(x: Int): String = x match {
case 1 => "one"
case 2 => "two"
case _ => "anything other than one and two"
}
expr 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 _ =>
}
List(1,2,3,4,5).foreach(print(_))
// Doing the same without underscore:
List(1,2,3,4,5).foreach( a => print(a))
In Scala, _ acts similar to * in Java while importing packages.
// Imports all the classes in the package matching
import scala.util.matching._
// Imports all the members of the object Fun (static import in Java).
import com.test.Fun._
// 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 => _ , _ }
In Scala, a getter and setter will be implicitly defined for all non-private vars in a object. The getter name is same as the variable name and _= is added for the setter name.
class Test {
private var a = 0
def age = a
def age_=(n:Int) = {
require(n>0)
a = n
}
}
Usage:
val t = new Test
t.age = 5
println(t.age)
If you try to assign a function to a new variable, the function will be invoked and the result will be assigned to the variable. This confusion occurs due to the optional braces for method invocation. We should use _ after the function name to assign it to another variable.
class Test {
def fun = {
// Some code
}
val funLike = fun _
}
There is one usage I can see everyone here seems to have forgotten to list...
Rather than doing this:
List("foo", "bar", "baz").map(n => n.toUpperCase())
You could can simply do this:
List("foo", "bar", "baz").map(_.toUpperCase())
Here are some more examples where _ is used:
val nums = List(1,2,3,4,5,6,7,8,9,10)
nums filter (_ % 2 == 0)
nums reduce (_ + _)
nums.exists(_ > 5)
nums.takeWhile(_ < 8)
In all above examples one underscore represents an element in the list (for reduce the first underscore represents the accumulator)
Besides the usages that JAiro mentioned, I like this one:
def getConnectionProps = {
( Config.getHost, Config.getPort, Config.getSommElse, Config.getSommElsePartTwo )
}
If someone needs all connection properties, he can do:
val ( host, port, sommEsle, someElsePartTwo ) = getConnectionProps
If you need just a host and a port, you can do:
val ( host, port, _, _ ) = getConnectionProps
There is a specific example that "_" be used:
type StringMatcher = String => (String => Boolean)
def starts: StringMatcher = (prefix:String) => _ startsWith prefix
may be equal to :
def starts: StringMatcher = (prefix:String) => (s)=>s startsWith prefix
Applying “_” in some scenarios will automatically convert to “(x$n) => x$n ”
In the following example using Scala 2.13.3 the 1st pattern matches, but the 2nd does not.
The 3rd pattern again matches, while the 4th does not (note that separator in the 4th match expression is enclosed in backticks, thus referencing the value defined before).
trait A
case object A extends A {
def unapply(a: String): Option[A] = if (a == "my_a") Some(A) else None
}
trait B
case object B extends B {
def unapply(b: String): Option[B] = if (b == "myB") Some(B) else None
}
val match1 = "myB_my_a" match {
case s"${B(b)}_${A(a)}" => Some((a,b))
case _ => None
} // Some((A,B))
val match2 = "my_a_myB" match {
case s"${A(a)}_${B(b)}" => Some((a,b))
case _ => None
} // None
val match3 = "my_a__myB" match {
case s"${A(a)}__${B(b)}" => Some((a,b))
case _ => None
} // Some((A,B))
val separator = "__"
val match4 = s"my_a${separator}myB" match {
case s"${A(a)}${`separator`}${B(b)}" => Some((a,b))
case _ => None
} // None
Why do only the 1st and the 3rd pattern match?
Is there a good matching alternative to the 2nd pattern that a) is using the unapply methods of A and B and where b) we don't know what strings these methods are accepting?
Edit 1: Added case object B and another matching example.
Edit 2: Another example to illustrate jwvh's answer:
val (a, b) = ("my_a", "myB")
val match5 = s"${a}_${b}" match {
case s"${`a`}_${`b`}" => Some((a, b)) // does not match
case s"${x}_${y}" => Some((x, y)) // matches: Some(("my", "a_myB"))
}
Edit 3: To illustrate how, unlike case class construction and extraction with apply and unapply, the construction and extraction of strings using similar string interpolation are not (and cannot be) inverse functions:
case class AB(a: String, b: String)
val id = (AB.apply _ tupled) andThen AB.unapply andThen (_.get)
val compare = id(("my_a", "myB")) == ("my_a", "myB") // true
val construct: (String, String) => String = (a,b) => s"${a}_${b}"
val extract: String => (String, String) = { case s"${a}_${b}" => (a,b) }
val id2 = (construct tupled) andThen extract
val compare2 = id2(("my_a","myB")) == ("my_a","myB") // false
As your own test (mentioned in the comments) demonstrates, the interpolator recognizes that the match pattern "${A(a)}_${B(b)}" is made up of 2 parts separated by an underscore _. So a best-guess effort is made to split the target string accordingly.
The 1st part, "my", is sent to the A.unapply() where it fails. The 2nd part, "a_myB", is not even attempted.
Something similar happens in match4. The pattern "${A(a)}${'separator'}${B(b)}" has 3 dollar signs and thus 3 parts. But, without any explicit characters to anchor the pattern, the target string is split into these 3 parts.
""
""
"my_a__myB"
Again, the 1st part fails the unapply() and the other parts are never attempted.
While your Edit 3 code is technically correct, I don't find it terribly convincing. You've simply demonstrated that (String,String)=>AB(String,String)=>(String,String) is (or can be) a lossless data transition. The same cannot be said of (String,String)=>String which introduces some ambiguity, i.e. the loss of information sufficient to guarantee restoration of the original data. That loss is inherent in the transformation itself, not the tools (interpolation) used to achieve it.
The fact that case class and String interpolation both use apply()/unapply() under the hood strikes me as inconsequential.
I need to concatenate strings present inside a WrappedArray in Scala. I am able to do it with the help of List but that is not what I have to do. I want a solution specifically designed for WrappedArray and with scope of adding/deleting elements while concatenating. I have to use this function as a udf for transforming data via Spark SQL collect_list. That is why I am forced to use WrappedArray.
For e.g ->
WrappedArray("I","love","coding")
Output : String = I : love : coding
This is just an example like adding a colon. I am facing various type issues while matching in case of Wrapped Array.
import scala.annotation.tailrec
object tailRecursionString {
def getString(ints :scala.collection.mutable.WrappedArray[String]): String = {
#tailrec
def sumAccumulator(ints: scala.collection.mutable.WrappedArray[String], accum: String): String = {
ints match {
case Nil : => accum
case x :: tail => sumAccumulator(tail, accum + x)
}
}
sumAccumulator(ints, "[") + "]"
}
def main(args: Array[String]): Unit = {
val list : scala.collection.mutable.WrappedArray[String] = Array("kumar","sambhav","is","a","good","boy")
val sum = getString(list)
println(sum)
}
}
The reason of your problems is using WrappedArray which hasn't unapply method. Pattern matching works using unapply method, you can read more about this in scala documentation. Just replace WrappedArray to Array and matching expressions then it should works:
#tailrec
def sumAccumulator(ints: Array[String], accum: String): String = {
ints match {
case Array() => accum
case _ => sumAccumulator(ints.tail, accum + ints.head)
}
}
List has subtypes :: and Nil. They are case classes and case classes have unapply method generated by compiler.
Shortly, I try to describe how it works:
When compiler looking for extracting (in pattern matching) it looks at ::, sees that it's a subtype of List and has unapply method, and if unapply returns correct result it's choose this branch. The same way for Nil.
You could write it for Seq in general :
import scala.annotation.tailrec
def getString(ints :Seq[String]): String = {
#tailrec
def sumAccumulator(ints: Seq[String], accum: String): String = {
ints match {
case Seq(x) => accum
case Seq(x, xs#_*) => sumAccumulator(xs, accum + x)
}
}
sumAccumulator(ints, "[") + "]"
}
As WrappedArray is also a Seq, this will work
val seperator = " "
s"[${scala.collection.mutable.WrappedArray("I", "love", "coding").mkString(seperator)}]"
In case if you want to apply a filter, you can still use filter, and achieve the same.
<script src="https://scastie.scala-lang.org/lttp77S4Sout7VWkOXTEhQ.js"></script>
I've taken a look at the list of surveys taken on scala-lang.org and noticed a curious question: "Can you name all the uses of “_”?". Can you? If yes, please do so here. Explanatory examples are appreciated.
The ones I can think of are
Existential types
def foo(l: List[Option[_]]) = ...
Higher kinded type parameters
case class A[K[_],T](a: K[T])
Ignored variables
val _ = 5
Ignored parameters
List(1, 2, 3) foreach { _ => println("Hi") }
Ignored names of self types
trait MySeq { _: Seq[_] => }
Wildcard patterns
Some(5) match { case Some(_) => println("Yes") }
Wildcard patterns in interpolations
"abc" match { case s"a$_c" => }
Sequence wildcard in patterns
C(1, 2, 3) match { case C(vs # _*) => vs.foreach(f(_)) }
Wildcard imports
import java.util._
Hiding imports
import java.util.{ArrayList => _, _}
Joining letters to operators
def bang_!(x: Int) = 5
Assignment operators
def foo_=(x: Int) { ... }
Placeholder syntax
List(1, 2, 3) map (_ + 2)
Method values
List(1, 2, 3) foreach println _
Converting call-by-name parameters to functions
def toFunction(callByName: => Int): () => Int = callByName _
Default initializer
var x: String = _ // unloved syntax may be eliminated
There may be others I have forgotten!
Example showing why foo(_) and foo _ are different:
This example comes from 0__:
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.
Note that this example compiles in 2.13. Ignore it like it was assigned to underscore.
From (my entry) in the FAQ, which I certainly do not guarantee to be complete (I added two entries just two days ago):
import scala._ // Wild card -- all of Scala is imported
import scala.{ Predef => _, _ } // Exception, everything except Predef
def f[M[_]] // Higher kinded type parameter
def f(m: M[_]) // Existential type
_ + _ // Anonymous function placeholder parameter
m _ // Eta expansion of method into method value
m(_) // Partial function application
_ => 5 // Discarded parameter
case _ => // Wild card pattern -- matches anything
val (a, _) = (1, 2) // same thing
for (_ <- 1 to 10) // same thing
f(xs: _*) // Sequence xs is passed as multiple parameters to f(ys: T*)
case Seq(xs # _*) // Identifier xs is bound to the whole matched sequence
var i: Int = _ // Initialization to the default value
def abc_<>! // An underscore must separate alphanumerics from symbols on identifiers
t._2 // Part of a method name, such as tuple getters
1_000_000 // Numeric literal separator (Scala 2.13+)
This is also part of this question.
An excellent explanation of the uses of the underscore is Scala _ [underscore] magic.
Examples:
def matchTest(x: Int): String = x match {
case 1 => "one"
case 2 => "two"
case _ => "anything other than one and two"
}
expr 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 _ =>
}
List(1,2,3,4,5).foreach(print(_))
// Doing the same without underscore:
List(1,2,3,4,5).foreach( a => print(a))
In Scala, _ acts similar to * in Java while importing packages.
// Imports all the classes in the package matching
import scala.util.matching._
// Imports all the members of the object Fun (static import in Java).
import com.test.Fun._
// 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 => _ , _ }
In Scala, a getter and setter will be implicitly defined for all non-private vars in a object. The getter name is same as the variable name and _= is added for the setter name.
class Test {
private var a = 0
def age = a
def age_=(n:Int) = {
require(n>0)
a = n
}
}
Usage:
val t = new Test
t.age = 5
println(t.age)
If you try to assign a function to a new variable, the function will be invoked and the result will be assigned to the variable. This confusion occurs due to the optional braces for method invocation. We should use _ after the function name to assign it to another variable.
class Test {
def fun = {
// Some code
}
val funLike = fun _
}
There is one usage I can see everyone here seems to have forgotten to list...
Rather than doing this:
List("foo", "bar", "baz").map(n => n.toUpperCase())
You could can simply do this:
List("foo", "bar", "baz").map(_.toUpperCase())
Here are some more examples where _ is used:
val nums = List(1,2,3,4,5,6,7,8,9,10)
nums filter (_ % 2 == 0)
nums reduce (_ + _)
nums.exists(_ > 5)
nums.takeWhile(_ < 8)
In all above examples one underscore represents an element in the list (for reduce the first underscore represents the accumulator)
Besides the usages that JAiro mentioned, I like this one:
def getConnectionProps = {
( Config.getHost, Config.getPort, Config.getSommElse, Config.getSommElsePartTwo )
}
If someone needs all connection properties, he can do:
val ( host, port, sommEsle, someElsePartTwo ) = getConnectionProps
If you need just a host and a port, you can do:
val ( host, port, _, _ ) = getConnectionProps
There is a specific example that "_" be used:
type StringMatcher = String => (String => Boolean)
def starts: StringMatcher = (prefix:String) => _ startsWith prefix
may be equal to :
def starts: StringMatcher = (prefix:String) => (s)=>s startsWith prefix
Applying “_” in some scenarios will automatically convert to “(x$n) => x$n ”
I've taken a look at the list of surveys taken on scala-lang.org and noticed a curious question: "Can you name all the uses of “_”?". Can you? If yes, please do so here. Explanatory examples are appreciated.
The ones I can think of are
Existential types
def foo(l: List[Option[_]]) = ...
Higher kinded type parameters
case class A[K[_],T](a: K[T])
Ignored variables
val _ = 5
Ignored parameters
List(1, 2, 3) foreach { _ => println("Hi") }
Ignored names of self types
trait MySeq { _: Seq[_] => }
Wildcard patterns
Some(5) match { case Some(_) => println("Yes") }
Wildcard patterns in interpolations
"abc" match { case s"a$_c" => }
Sequence wildcard in patterns
C(1, 2, 3) match { case C(vs # _*) => vs.foreach(f(_)) }
Wildcard imports
import java.util._
Hiding imports
import java.util.{ArrayList => _, _}
Joining letters to operators
def bang_!(x: Int) = 5
Assignment operators
def foo_=(x: Int) { ... }
Placeholder syntax
List(1, 2, 3) map (_ + 2)
Method values
List(1, 2, 3) foreach println _
Converting call-by-name parameters to functions
def toFunction(callByName: => Int): () => Int = callByName _
Default initializer
var x: String = _ // unloved syntax may be eliminated
There may be others I have forgotten!
Example showing why foo(_) and foo _ are different:
This example comes from 0__:
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.
Note that this example compiles in 2.13. Ignore it like it was assigned to underscore.
From (my entry) in the FAQ, which I certainly do not guarantee to be complete (I added two entries just two days ago):
import scala._ // Wild card -- all of Scala is imported
import scala.{ Predef => _, _ } // Exception, everything except Predef
def f[M[_]] // Higher kinded type parameter
def f(m: M[_]) // Existential type
_ + _ // Anonymous function placeholder parameter
m _ // Eta expansion of method into method value
m(_) // Partial function application
_ => 5 // Discarded parameter
case _ => // Wild card pattern -- matches anything
val (a, _) = (1, 2) // same thing
for (_ <- 1 to 10) // same thing
f(xs: _*) // Sequence xs is passed as multiple parameters to f(ys: T*)
case Seq(xs # _*) // Identifier xs is bound to the whole matched sequence
var i: Int = _ // Initialization to the default value
def abc_<>! // An underscore must separate alphanumerics from symbols on identifiers
t._2 // Part of a method name, such as tuple getters
1_000_000 // Numeric literal separator (Scala 2.13+)
This is also part of this question.
An excellent explanation of the uses of the underscore is Scala _ [underscore] magic.
Examples:
def matchTest(x: Int): String = x match {
case 1 => "one"
case 2 => "two"
case _ => "anything other than one and two"
}
expr 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 _ =>
}
List(1,2,3,4,5).foreach(print(_))
// Doing the same without underscore:
List(1,2,3,4,5).foreach( a => print(a))
In Scala, _ acts similar to * in Java while importing packages.
// Imports all the classes in the package matching
import scala.util.matching._
// Imports all the members of the object Fun (static import in Java).
import com.test.Fun._
// 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 => _ , _ }
In Scala, a getter and setter will be implicitly defined for all non-private vars in a object. The getter name is same as the variable name and _= is added for the setter name.
class Test {
private var a = 0
def age = a
def age_=(n:Int) = {
require(n>0)
a = n
}
}
Usage:
val t = new Test
t.age = 5
println(t.age)
If you try to assign a function to a new variable, the function will be invoked and the result will be assigned to the variable. This confusion occurs due to the optional braces for method invocation. We should use _ after the function name to assign it to another variable.
class Test {
def fun = {
// Some code
}
val funLike = fun _
}
There is one usage I can see everyone here seems to have forgotten to list...
Rather than doing this:
List("foo", "bar", "baz").map(n => n.toUpperCase())
You could can simply do this:
List("foo", "bar", "baz").map(_.toUpperCase())
Here are some more examples where _ is used:
val nums = List(1,2,3,4,5,6,7,8,9,10)
nums filter (_ % 2 == 0)
nums reduce (_ + _)
nums.exists(_ > 5)
nums.takeWhile(_ < 8)
In all above examples one underscore represents an element in the list (for reduce the first underscore represents the accumulator)
Besides the usages that JAiro mentioned, I like this one:
def getConnectionProps = {
( Config.getHost, Config.getPort, Config.getSommElse, Config.getSommElsePartTwo )
}
If someone needs all connection properties, he can do:
val ( host, port, sommEsle, someElsePartTwo ) = getConnectionProps
If you need just a host and a port, you can do:
val ( host, port, _, _ ) = getConnectionProps
There is a specific example that "_" be used:
type StringMatcher = String => (String => Boolean)
def starts: StringMatcher = (prefix:String) => _ startsWith prefix
may be equal to :
def starts: StringMatcher = (prefix:String) => (s)=>s startsWith prefix
Applying “_” in some scenarios will automatically convert to “(x$n) => x$n ”