Pattern Matching on lists behaving weird? - scala

While practicing scala, I am trying to insertion-sort an integer list using pattern matching. Previously, the following code for printing the list worked absolutely fine:
object PrintList {
def iPrint(xs: List[Int]):Unit = xs match {
case x :: ys => {
print(x+" -> ")
iPrint(ys)
}
case _ => println("Nil")
}
def main(args: Array[String]) {
//val l = Nil.::(1).::(2).::(3).::(4)
val l = 4 :: 3 :: 2 :: 1 :: Nil
iPrint(l)
}
}
However, the following code to sort a list doesn't compile:
def insert(x : Int, l1 : List[Int]):List = {
//stubbed
List()
}
def iSort(l : List[Int]):List = l match {
case x :: ys => insert(x , iSort(ys))
case Nil => Nil
}
Am I missing something really trivial here??
EDIT:
Modified the code as below:
def insert(x : Int , l1 : List[Int]):List[Int] = {
//stubbed
List(0)
}
def iSort(l : List[Int]):List[Int] = l match {
case (x:Int) :: (ys:List[Int]) => insert(x , iSort(ys))
case _ => List(0)
}
Still getting error in the first case statement - Pattern type is incompatible with expected type. Found: ::[B], expected: List[Int]
Using Intellij Idea with scala plugin - 2.11.7.

Looking at your screenshot, you are defining your own List class in that same package Week04. It's visible in your project browser on the left-hand side. So in your code
def iSort(l: List[Int]) = ???
you have an argument of type Week04.List[Int]. You try to destructure that using the :: list-cons class. I presume you have not defined your version of ::, least I don't remember that this was defined the Coursera class. So you have a scala.:: here which is a sub-type of scala.List. So you are trying to pattern match against some completely different type. If you replaced every occurance of List with scala.List you would use Scala's standard list class instead and it should work. If you want that to work with your own list implementation, you need to define your own extractor.

Related

How to concatenate string in a scala.collection.mutable.WrappedArray using #tailrec?

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>

Unquote applied types in scala macros

In the scala console I can do the following without a problem :
scala> val tree = q"def f():MySuperType[(Char,Char)]"
tree: universe.DefDef = def f(): MySuperType[scala.Tuple2[Char, Char]]
scala> val q"def $f():$d" = tree
f: universe.TermName = f
d: universe.Tree = MySuperType[scala.Tuple2[Char, Char]]
scala> val tq"$a[$TheTypeThatIWant]" = d
a: universe.Tree = MySuperType
TheTypeThatIWant: universe.Tree = scala.Tuple2[Char, Char]
And I can get what I want : the content of TheTypeThatIWant
Now If I try to do that inside a quasiquote, I get a match exception and I didn't find a way to get the inner type of an applied type.
My code :
tree match {
case q"{..$body}" =>
body.foreach (_ match {
case q"def $functionName:$type = $osef" =>
val tq"$f[$typ]" = d //I want to get $typ !!
...
}
But all I get is :
exception during macro expansion:
exception during macro expansion:
scala.MatchError: MyMacro.MySuperType[(Char, Char)] (of class scala.reflect.internal.Trees$TypeTree)
at MyMacro$$anonfun$getBasicStructure$1$1.apply(MyMacro.scala:737)
at MyMacro$$anonfun$getBasicStructure$1$1.apply(MyMacro.scala:735)
at scala.collection.immutable.List.foreach(List.scala:383)
at MyMacro$.getBasicStructure$1(MyMacro.scala:735)
at MyMacro$.MyMacro_impl(MyMacro.scala:846)
How can I solve that ?
Thank you
Edit :
The problem is not only with quasiquotes, it bugs even when I work with Trees :
case Block(stats,expr) =>
stats.foreach(_ match {
case DefDef(_,_,_,_,typ,_) =>
typ match {
case AppliedTypeTree(t,args) => //doesnt go there
case TypeApply(t,args) => //doesnt go there
case x:TypeTree => //goes there but can't get any info about the applied type
case _ =>
}
})
Edit2 :
You have to do it that way :
case q"def $name:${d:TypeTree} = $b" =>
d.tpe match {
case TypeRef(x,y,z) => //z is the list of applied types, see scaladoc
case _ =>
}
Well, I guess that's because in the console, by the time you call val tq"$a[$TheTypeThatIWant]" = d , the type of d is actually known, but it's not the case in the macro.

Building variations of nested case classes

So I got something like this:
abstract class Term
case class App(f:Term,x:Term) extends Term
case class Var(s:String) extends Term
case class Amb(a:Term, b:Term) extends Term //ambiguity
And a Term may look like this:
App(Var(f),Amb(Var(x),Amb(Var(y),Var(z))))
So what I need is all variations that are indicated by the Amb class.
This is used to represent a ambiguous parse forest and I want to type check each possible variation and select the right one.
In this example I would need:
App(Var(f),Var(x))
App(Var(f),Var(y))
App(Var(f),Var(z))
Whats the best way to create these variations in scala?
Efficiency would be nice, but is not really requirement.
If possible I like to refrain from using reflection.
Scala provides pattern matching solve these kinds of problems. A solution would look like:
def matcher(term: Term): List[Term] = {
term match {
case Amb(a, b) => matcher(a) ++ matcher(b)
case App(a, b) => for { va <- matcher(a); vb <- matcher(b) } yield App(va, vb)
case v: Var => List(v)
}
}
You can do this pretty cleanly with a recursive function that traverses the tree and expands ambiguities:
sealed trait Term
case class App(f: Term, x: Term) extends Term
case class Var(s: String) extends Term
case class Amb(a: Term, b: Term) extends Term
def det(term: Term): Stream[Term] = term match {
case v: Var => Stream(v)
case App(f, x) => det(f).flatMap(detf => det(x).map(App(detf, _)))
case Amb(a, b) => det(a) ++ det(b)
}
Note that I'm using a sealed trait instead of an abstract class in order to take advantage of the compiler's ability to check exhaustivity.
It works as expected:
scala> val app = App(Var("f"), Amb(Var("x"), Amb(Var("y"), Var("z"))))
app: App = App(Var(f),Amb(Var(x),Amb(Var(y),Var(z))))
scala> det(app) foreach println
App(Var(f),Var(x))
App(Var(f),Var(y))
App(Var(f),Var(z))
If you can change the Term API, you could more or less equivalently add a def det: Stream[Term] method there.
Since my abstract syntax is fairly large (and I have multiple) and I tried my luck with Kiama.
So here is the version Travis Brown and Mark posted with Kiama.
Its not pretty, but I hope it works. Comments are welcome.
def disambiguateRule: Strategy = rule {
case Amb(a: Term, b: Term) =>
rewrite(disambiguateRule)(a).asInstanceOf[List[_]] ++
rewrite(disambiguateRule)(b).asInstanceOf[List[_]]
case x =>
val ch = getChildren(x)
if(ch.isEmpty) {
List(x)
}
else {
val chdis = ch.map({ rewrite(disambiguateRule)(_) }) // get all disambiguate children
//create all combinations of the disambiguated children
val p = combinations(chdis.asInstanceOf[List[List[AnyRef]]])
//use dup from Kiama to recreate the term with every combination
val xs = for { newchildren <- p } yield dup(x.asInstanceOf[Product], newchildren.toArray)
xs
}
}
def combinations(ll: List[List[AnyRef]]): List[List[AnyRef]] = ll match {
case Nil => Nil
case x :: Nil => x.map { List(_) }
case x :: xs => combinations(xs).flatMap({ ys => x.map({ xx => xx :: ys }) })
}
def getChildren(x: Any): List[Any] = {
val l = new ListBuffer[Any]()
all(queryf {
case a => l += a
})(x)
l.toList
}

Scala function transformation

Say I've got a function taking one argument
def fun(x: Int) = x
Based on that, I want to generate a new function with the same calling convention, but that'll apply some transformation to its arguments before delegating to the original function. For that, I could
def wrap_fun(f: (Int) => Int) = (x: Int) => f(x * 2)
wrap_fun(fun)(2) // 4
How might one go about doing the same thing, except to functions of any arity that only have the part of the arguments to apply the transformation to in common?
def fun1(x: Int, y: Int) = x
def fun2(x: Int, foo: Map[Int,Str], bar: Seq[Seq[Int]]) = x
wrap_fun(fun1)(2, 4) // 4
wrap_fun(fun2)(2, Map(), Seq()) // 4
How would a wrap_fun definition making the above invocations work look like?
This can be done in fairly straightforwardly using shapeless's facilities for abstracting over function arity,
import shapeless._
import HList._
import Functions._
def wrap_fun[F, T <: HList, R](f : F)
(implicit
hl : FnHListerAux[F, (Int :: T) => R],
unhl : FnUnHListerAux[(Int :: T) => R, F]) =
((x : Int :: T) => f.hlisted(x.head*2 :: x.tail)).unhlisted
val f1 = wrap_fun(fun _)
val f2 = wrap_fun(fun1 _)
val f3 = wrap_fun(fun2 _)
Sample REPL session,
scala> f1(2)
res0: Int = 4
scala> f2(2, 4)
res1: Int = 4
scala> f3(2, Map(), Seq())
res2: Int = 4
Note that you can't apply the wrapped function immediately (as in the question) rather than via an assigned val (as I've done above) because the explicit argument list of the wrapped function will be confused with the implicit argument list of wrap_fun. The closest we can get to the form in the question is to explicitly name the apply method as below,
scala> wrap_fun(fun _).apply(2)
res3: Int = 4
scala> wrap_fun(fun1 _).apply(2, 4)
res4: Int = 4
scala> wrap_fun(fun2 _).apply(2, Map(), Seq())
res5: Int = 4
Here the explicit mention of apply syntactically marks off the first application (of wrap_fun along with its implicit argument list) from the second application (of the transformed function with its explicit argument list).
As usual in Scala, there's yet another way to achieve what you want to do.
Here is a take based on currying of the first argument together with the compose of Function1:
def fun1(x : Int)(y : Int) = x
def fun2(x : Int)(foo : Map[Int, String], bar : Seq[Seq[Int]]) = x
def modify(x : Int) = 2*x
The resulting types as REPL shows you will be:
fun1: (x: Int)(y: Int)Int
fun2: (x: Int)(foo: Map[Int,String], bar: Seq[Seq[Int]])Int
modify: (x: Int)Int
And instead of wrapping the functions fun1 and fun2, you compose them, as technically, they are now both Function1 objects. This allows you to make calls like the following:
(fun1 _ compose modify)(2)(5)
(fun2 _ compose modify)(2)(Map(), Seq())
Both of which will return 4. Granted, the syntax is not that nice, given that you have to add the _ to distinguish fun1's application from the function object itself (on which you want to call the compose method in this case).
So Luigi's argument that it is impossible in general remains valid, but if you are free to curry your functions you can do it in this nice way.
Since functions taking different numbers of arguments are different, unrelated types, you cannot do this generically. trait Function1 [-T1, +R] extends AnyRef and nothing else. You will need a separate method for each arity.
While I voted for and agree with Luigi's answer–because, you know... he's right; Scala doesn't have direct, in-built support for such a thing–it's worth noting that what you're trying to do isn't impossible; it's just that it's a bit of a pain to pull off, and, often times, you're best off just implementing a separate method per desired arity.
That said, though... we can actually do this HLists. If you're interested in trying it out, naturally, you'll need to obtain an HList implementation. I recommend utilizing Miles Sabin's excellent shapeless project and its implementation of HLists. Anyway, here's an example of its use that accomplishes something akin to what you seem to be looking for:
import shapeless._
trait WrapperFunner[T] {
type Inputs <: HList
def wrapFun(inputs: Inputs) : T
}
class WrapsOne extends WrapperFunner[Int] {
type Inputs = Int :: HNil
def wrapFun(inputs: Inputs) : Int = {
inputs match {
case num :: HNil => num * 2
}
}
}
class WrapsThree extends WrapperFunner[String] {
type Inputs = Int :: Int :: String :: HNil
def wrapFun(inputs: Inputs) : String = {
inputs match {
case firstNum :: secondNum :: str :: HNil => str + (firstNum - secondNum)
}
}
}
object MyApp extends App {
val wo = new WrapsOne
println(wo.wrapFun(1 :: HNil))
println(wo.wrapFun(17 :: HNil))
//println(wo.wrapFun(18 :: 13 :: HNil)) // Would give type error
val wt = new WrapsThree
println(wt.wrapFun(5 :: 1 :: "your result is: " :: HNil))
val (first, second) = (60, 50)
println(wt.wrapFun(first :: second :: "%s minus %s is: ".format(first, second) :: HNil))
//println(wt.wrapFun(1 :: HNil)) // Would give type error
}
Running MyApp results in:
2
34
your result is: 4
60 minus 50 is: 10
Or, extended closer to your particular case:
import shapeless._
trait WrapperFunner[T] {
type Inputs <: HList
def wrapFun(inputs: Inputs) : T
}
trait WrapperFunnerBase extends WrapperFunner[Int] {
// Does not override `Inputs`
def wrapFun(inputs: Inputs) : Int = {
inputs match {
case (num: Int) :: remainder => num
}
}
}
class IgnoresNothing extends WrapperFunnerBase {
type Inputs = Int :: HNil
}
class IgnoresLastTwo extends WrapperFunnerBase {
type Inputs = Int :: Int :: String :: HNil
}
object MyApp extends App {
val in = new IgnoresNothing
println(in.wrapFun(1 :: HNil))
println(in.wrapFun(2 :: HNil))
//println(in.wrapFun(3 :: 4 :: HNil)) // Would give type error
val ilt = new IgnoresLastTwo
println(ilt.wrapFun(60 :: 13 :: "stupid string" :: HNil))
println(ilt.wrapFun(43 :: 7 :: "man, that string was stupid..." :: HNil))
//println(ilt.wrapFun(1 :: HNil)) // Would give type error
}
results in:
1
2
60
43

Ternary Operator Similar To ?:

I am trying to avoid constructs like this:
val result = this.getClass.getSimpleName
if (result.endsWith("$")) result.init else result
Ok, in this example the then and else branch are simple, but you can image complex ones.
I built the following:
object TernaryOp {
class Ternary[T](t: T) {
def is[R](bte: BranchThenElse[T,R]) = if (bte.branch(t)) bte.then(t) else bte.elze(t)
}
class Branch[T](branch: T => Boolean) {
def ?[R] (then: T => R) = new BranchThen(branch,then)
}
class BranchThen[T,R](val branch: T => Boolean, val then: T => R)
class Elze[T,R](elze: T => R) {
def :: (bt: BranchThen[T,R]) = new BranchThenElse(bt.branch,bt.then,elze)
}
class BranchThenElse[T,R](val branch: T => Boolean, val then: T => R, val elze: T => R)
implicit def any2Ternary[T](t: T) = new Ternary(t)
implicit def fct2Branch[T](branch: T => Boolean) = new Branch(branch)
implicit def fct2Elze[T,R](elze: T => R) = new Elze(elze)
}
Defined that, I can replace the above simple example with:
this.getClass.getSimpleName is {s: String => s.endsWith("$")} ? {s: String => s.init} :: {s: String => s}
But how can I get rid of the s: String =>? I want something like that:
this.getClass.getSimpleName is {_.endsWith("$")} ? {_.init} :: {identity}
I guess the compiler needs the extra stuff to infer types.
From Tony Morris' Lambda Blog:
I hear this question a lot. Yes it does. Instead of c ? p : q, it is
written if(c) p else q.
This may not be preferable. Perhaps you’d like to write it using the
same syntax as Java. Sadly, you can’t. This is because : is not a
valid identifier. Fear not, | is! Would you settle for this?
c ? p | q
Then you’ll need the following code. Notice the call-by-name (=>)
annotations on the arguments. This evaluation strategy is required to
correctly rewrite Java’s ternary operator. This cannot be done in Java
itself.
case class Bool(b: Boolean) {
def ?[X](t: => X) = new {
def |(f: => X) = if(b) t else f
}
}
object Bool {
implicit def BooleanBool(b: Boolean) = Bool(b)
}
Here is an example using the new operator that we just defined:
object T { val condition = true
import Bool._
// yay!
val x = condition ? "yes" | "no"
}
Have fun ;)
We can combine How to define a ternary operator in Scala which preserves leading tokens? with the answer to Is Option wrapping a value a good pattern? to get
scala> "Hi".getClass.getSimpleName |> {x => x.endsWith("$") ? x.init | x}
res0: String = String
scala> List.getClass.getSimpleName |> {x => x.endsWith("$") ? x.init | x}
res1: String = List
Is this adequate for your needs?
Rex Kerr’s answer expressed in basic Scala:
"Hi".getClass.getSimpleName match {
case x if x.endsWith("$") => x.init
case x => x
}
although I’m not sure what part of the if–else construct you want to optimise.
Since if-else constructions in Scala return a value, you can use this
val a = if (1 < 0) 1 else 2
More info: https://alvinalexander.com/scala/scala-if-then-ternary-operator-cookbook-examples
Since : by itself won't be a valid operator unless you are ok with always escaping it with back ticks :, you could go with another character, e.g. "|" as in one of the answers above. But how about elvis with a goatee ?::
implicit class Question[T](predicate: => Boolean) {
def ?(left: => T) = predicate -> left
}
implicit class Colon[R](right: => R) {
def ::[L <% R](pair: (Boolean, L)): R = if (q._1) q._2 else right
}
val x = (5 % 2 == 0) ? 5 :: 4.5
Of course this again won't work if you values are lists, since they have :: operator themselves.