This question already has answers here:
Understanding type Parameters in Scala
(1 answer)
Scala type parameters in various places
(2 answers)
Closed 4 years ago.
I am newly learning Scala. below code has [A] multiple times. Please, someone, explain me in layman terms. I am unable to understand(tried google and read StackOverflow and others answers but I don't get it. The code below is to find kth element from the list.
def findKth[A](k:Int, l:List[A]):A = k match {
case 0 => l.head
case k if k > 0 => findKth(k - 1, l.tail)
case _ => throw new NoSuchElementException
}
def findKth[A](k:Int, l:List[A]):A = k match {
case 0 => l.head
case k if k > 0 => findKth(k - 1, l.tail)
case _ => throw new NoSuchElementException
}
Here [A] is the type parameter for function findKth. Now what does type parameter mean?
Type parameter tells the compiler that method findKth can take parameter of type A. Which is the generic type here because A can be anything. For example A can be Int, Double, another List -- anything.
For more information I would suggest you to go through these links:
https://docs.scala-lang.org/tour/polymorphic-methods.html
https://docs.scala-lang.org/tour/generic-classes.html
It is for declaring generic parameters in Scala, You can call your method with a list of different types (Double, Int, Dogs ... )
If you want to learn more, this post: https://apiumhub.com/tech-blog-barcelona/scala-type-bounds/
For example:
def findKth[A](k:Int, l:List[A]):A = k match {
case 0 => l.head
case k if k > 0 => findKth(k - 1, l.tail)
case _ => throw new NoSuchElementException
}
val intList = 1 :: 2::3::4::5::6::7::8::9::10::Nil
val strList = intList.map(_.toString)
println(findKth(9, intList))
println(findKth(3, strList))
As you can see, you can pass to your function a List[Int], or a List[String], it is a way to parametrize functions to accept generics arguments.
You can see it working in here: https://scalafiddle.io/sf/XwaALIk/0
Related
I'm doing an assignment for a class where my function should return a fibonacci sequence up until a given position. I'm trying to reduce my code in the third case of this code.
object FibonacciSeries{
def fibrec(pos: Int, list: List[Int] = List() ):List[Int] = pos match {
case 0 => List(0)
case 1 => List(0,1)
case _ => {
var seq= fibrec(pos - 1 , list)
seq :+ seq.takeRight(2).sum
}
}
}
I want to do it in such a way that only calls the recursive function once, and also fits into one line. I was hoping to do something like.
fibrec(pos -1, list).takeRight(2).sum.append
but I know that won't do. Any help is appreciated
The link that #Aivean has given offers a few good ways to achieve a Fibonacci stream. This one, however, is the most concise I've encountered.
val fib: Stream[Int] = 0 #:: fib.scan(1)(_+_)
I have a configuration value that matches to one of the values in a map and depending on to which it matches i take an action. Here is some sample code of what i am trying to do
val x = 1 // or 2 or 3
val config = Map("c1"-> 1, "c2"-> 2, "c3"-> 3)
x match {
case config("c1") =>
println("1")
case config("c2") =>
println("2")
case config("c3") =>
println("3")
}
Now this should print 1 because config("c1") evaluates to 1 but it gives error
error: value config is not a case class, nor does it have an unapply/unapplySeq member
case config("c1") =>
Similarly for the other 2 cases. Why should i have an unapply here? Any pointers?
An expression like that looks like an extractor, hence the message about unapply/unapplySeq methods. If you don't want to use an extractor but just want to match against a plain value, you need to store that value in a stable identifier - you can't use an arbitrary expression as a match case:
val case1 = config("c1")
x match {
case case1 => println("1")
...
}
To the best of my knowledge, in Scala, x match {case config("c1") gets translated to config.unapply(x) with the branching dependent on the result of the unapply method. As Imm already mentioned in his answer, this isn't the case for stable identifiers (literals and val), and I'd encourage you to use his solution.
Nevertheless, to show you how you could solve the problem using extractors, I'd like to post a different solution:
def main(args: Array[String]): Unit = {
object config {
val configData = Map("c1" -> 1, "c2" -> 2, "c3" -> 3)
def unapply(value: Int): Option[String] = configData find (_._2 == value) map (_._1)
}
1 to 4 foreach {
case config("c1") => println("1")
case config("c2") => println("2")
case config("c3") => println("3")
case _ => println("no match")
}
}
I changed the match for a foreach to show the different results, but this has no effect on the implementation. This would print:
1
2
3
no match
As you can see, case config("c1") now calls the unapply method and checks whether the result is Some("c1"). Note that this is inverse to how you'd use a map: The key is searched according to the value. However, this makes sense: If in the map, "c1" and "c2" both map to 1, then 1 matches both, the same way _ matches everything, in our case even 4 which is not configured.
Here's also a very brief tutorial on extractors. I don't find it particularly good, because both, the returned type and the argument type are Int, but it might help you understand what's going on.
As others have stated, with x match { case config("c1") => ..., scala looks for an extractor by the name of config (something with an unapply method that takes a single value and returns an Optional value); Making pattern matching work this way seems like an abuse of the pattern, and I would not use an extractor for this.
Personally, I would recommend one of the following:
if (x == config("c1"))
println("1")
else if (x == config("c2"))
println("2")
else ...
Or, if you're set on using a match statement, you can use conditionals like this:
x match {
case _ if x == config("c1") =>
println("1")
case _ if x == config("c2") =>
println("2")
case _ if x == config("c3") =>
println("3")
}
Not as clean; unfortunately, there isn't a way to invoke a method call literally where the extractor goes. You can use back-ticks to tell scala "match against the value of this variable" (rather than default behavior, which would yield the value named as that variable):
val (c1,c2,c3) = (config("c1"), config("c2"), config("c3"))
x match {
case `c1` =>
println("1")
case `c2` =>
println("2")
case `c3` =>
println("3")
}
Finally, if your goal is to reverse-apply a map, maybe try this instead?
scala> Map("a" -> 1).map { case (k,v) => (v,k) }
res0: scala.collection.immutable.Map[Int,String] = Map(1 -> a)
Got java.util.NoSuchElementException: head of empty list so I tried to check for that. But now I get [info] - max of a few numbers *** FAILED ***
[info] 0 did not equal 7 (ListsSuite.scala:128)
def max(xs: List[Int]): Int = {
if xs.isEmpty 0 // What can I do?
else if (xs.head > max(xs.tail)) max(xs.tail)
else max(xs.tail)
}
edit:
The test case failed because my test was wrong.
For my classmates, a reminder of the Coursera honor code:
I will register for only one account. My answers to homework, quizzes
and exams will be my own work (except for assignments that explicitly
permit collaboration).
I will not make solutions to homework, quizzes
or exams available to anyone else. This includes both solutions
written by me, as well as any official solutions provided by the
course staff.
I will not engage in any other activities that will
dishonestly improve my results or dishonestly improve/hurt the
results of others.
In the general case, you can't return anything but None because an empty sequence in general has no meaningful default max value. That, however, is not necessarily the case all the time; for example you might want to find the maximum salary in a list of people, in which case it would make sense to say it's 0 if the list is empty; however, there is no trivial way to implement such default value logic generically (you'd have to use stuff like type classes and wrapped values); your best bet now is to simply use Option[Int]:
def max(xs: List[Int]): Option[Int] = xs match {
case Nil => None
case x :: Nil => Some(x)
case x :: xs => Some(x max max(xs))
}
Then, you can easily fall back to a default value at the call site:
val posOrNeg = List(-5, -2, 1, 4, 10)
max(posOrNeg) // => Some(10)
val posOrNeg = List.empty[Int]
max(posOrNeg) // => None
val onlyPos = List(1, 2, 3)
max(onlyPos).getOrElse(0) // => 3
val onlyPos = List.empty[Int]
max(onlyPos).getOrElse(0) // => 0
Bonus: Also, you can make your max work on any list of numeric values:
def max[T: Numeric](xs: List[T]): Option[T] = xs match {
case Nil => None
case x :: Nil => Some(x)
case x :: xs => Some(x max max(xs))
}
or in fact any suitable data structure made up of numeric values by using a type more general than List, but I'll leave that up to you.
But keep in mind: no matter which solution you opt for, always try to avoid try and exceptions in general — exceptions are not in the spirit of idiomatic functional programming (even though even some library functions use them occasionally for various reasons).
I'd go with Option.
def max(xs: List[Int]) =
if xs.isEmpty None
else if (xs.head > max(xs.tail)) Some( max(xs.tail) )
else Some( max(xs.tail))
The Option-Monad can either be Some( result ), meaning there is a result or None, meaning there is no result. If you wrap something in Some you say it's is a result and everything is fine.
As an alternative you solution you could wrap everything in a Try which would be the best because an empty list has no max and it's the right thing to get an error for that but now you can handle it in a functional way.
def max(xs: List[Int]) = Try( if (xs.head > max(xs.tail)) max(xs.tail) else xs.tail )
It doesn't make sense to define a max element for an empty collection, so you should either return a sentinel value, or throw an exception (e.g. IllegalArgumentException).
Also, you should make a few changes to your code (if you want to implement it yourself, and not use the built-in stuff):
def max(list: List[Int]): Option[Int] = {
list match {
// List has no elements, so we return None
case Nil => None
// Only one element, that is the maximum
case x :: Nil => Some(x)
// Compute max(list.tail).
// If defined, it will return the greater of list.tail and list.head
case head :: tail => max(tail).map(_ max head)
}
}
This question already has answers here:
Generic Programming in Scala
(2 answers)
Closed 8 years ago.
I am writing a parameterized merge sort functionality and passing the less checker as a function.
However, the compiler is throwing following error.
type mismatch;
found : y.type (with underlying type T)
required: T
Here is my full code
def mergeSort[T] (list:List[T], pred:(T,T) =>Boolean):List[T]={
def merge[T](left:List[T], right:List[T], acc:List[T]):List[T] = (left,right) match{
case (Nil,_) => acc ++ right
case (_,Nil) => acc ++ left
case (x::xs, y::ys) => if(pred(y,x)) merge(left,ys,acc :+ y) else merge(xs,right,acc :+ x)
}
val m = list.length/2
if (m == 0) list
else {
val (l,r) = list splitAt m
merge(mergeSort(l,pred), mergeSort(r,pred), List())
}
}
The problem is at line
if(pred(y,x))
Everything seems logically correct, can't figure out why this is happening?
help appreciated.
This happens because in your inner function merge you define a type T, it's like you're redefining the one you created in mergeSort. Just change def merge[T] to def merge and keep using T to parameterized your lists left, right, etc. That way you are telling the compiler "This is the same T I defined above in mergeSort".
I am going through a book Lift in action and I encountered something I don't quite understand: _ ::
object permanent_link extends MappedString(this, 150){
override def validations =
valMinLen(3, "Link URL must be at least 5 characters") _ ::
super.validations
}
I can't find any hint so I would be grateful if anyone could help me out..
I don't know Lift, but this is a general question. First of all, the :: is a Scala cons operator:
scala> 1 :: 2 :: List(3, 4)
res0: List[Int] = List(1, 2, 3, 4)
This means that super.validations is some sort of a sequence and valMinLen(3, "Link URL must be at least 5 characters") _ is a single value in that list.
From the context it looks obvious that in overridden validations method they are calling super version and prepend some extra validation at the beginning.
This extra validation is created by a call to valMinLen(). However this extra call does not return an element matching the type of validations list - but a function. Instead of prepending the function value we are explicitly saying (by adding _ suffix`) that we want to prepend a function itself, not a return value of that function.
Code snippet is worth a thousand words:
scala> def f = 3
f: Int
scala> def g = 4
g: Int
scala> val listOfInts = List(f, g)
listOfInts: List[Int] = List(3, 4)
scala> val listOfFunctions = List(f _, g _)
listOfFunctions: List[() => Int] = List(<function0>, <function0>)
Compare the type of listOfInts and listOfFunctions. I believe the f _ syntax is called partially applied function in Scala world.
The underscore ignifies that valMinLen isn't to be called but be used as a function "pointer".
The :: operator concatenates lists.
It would in other words seem like the code builds a list validations that consist of a function "pointer" to valMinLen with the parameters given and the rest of the list is the value of super.validations, that is the super class' validations.
I'm sure someone will correct my terminology here :)
The code might be more readable with some proper indentation and introducing a val:
object permanent_link extends MappedString(this, 150) {
override def validations = minimumValidation :: super.validations
val minimumValidation = valMinLen(3,"Link URL must be at least 5 characters") _
}
So as noted before, the :: operator just prepends a new element to a list, the _ has nothing to do with it and is used to obtain a function object, like in
(1 :: 2 :: Nil) map (println _)
which makes a list [1, 2] and applies the function println to every element (the underscore can actually be omitted here). The object println _ constructs a function object from the println method with the _ representing the function's single parameter.