Scala underspecified types - scala

I have the following spark code snippet .
But get the following error:
:8: error: missing parameter type.
which happens here:
val index:Int= col1(i) ; tokened +=splitted(index) + " " ; } }
^
I can't work out where it steps from as it seems like i've specified all properties. I also need to return the string so for the method to be string => string (currently it's string -> unit) This is my first time ever coding in scala so apologies if this is a stupid question
line => { var col1:Array[Int] = Array(1,2) ; var tokened:String = "" ;
var splitted:Array[String]=line.split(" ") ;
for (i<- 0 to col1.length) {
val index:Int= col1(i);
tokened +=splitted(index) + " " ;
}
}

I guess this is what you need:
(line: String) => { /* Previously missing type annotation */
var col1:Array[Int] = Array(1,2)
var tokened:String = ""
var splitted:Array[String]=line.split(" ")
for (i<- 0 to col1.length) {
val index:Int= col1(i)
tokened += splitted(index) + " "
}
tokened /* Return value */
}
In order to make the function type explicit, you could store the anonymous function in a function-typed variable:
val f: (String => String) = line => { ... }

Related

Hello I am new to Scala, I have a question about an anonymous function problem

How this function returns "hello there"? There is definitely something that I am missing here but I don't see it
def saySomething(prefix: String) = (s: String) => {
prefix + " " + s
}
def saySomethingElse = saySomething("hello")
print(saySomethingElse("there"))
I tried tracing how "hello" is substituted by prefix since its the first string being passed in the function "saySomething" but then I don't understand how "there" is attached to the result.
Any help is appreciated
Breaking it down, it works like this:
def saySomething(prefix: String) = (s: String) => {
prefix + " " + s
}
This is a function called saySomething that returns a value:
def saySomething(prefix: String) = ???
The value it returns is an anonymous function:
(s: String) => { prefix + " " + s }
Each time you call saySomething(prefix: String), a new function is created and the value of prefix is remembered by that new function. So when you call saySomething("hello") it remembers "hello" and returns this.
(s: String) => { "hello" + " " + s }
def saySomethingElse = (s: String) => { "hello" + " " + s }
When you call that new function, you get the final string:
saySomethingElse("there")
// == ((s: String) => { "hello" + " " + s })("there")
// == "hello" + " " + "there"
You could call it with a different value and get a different result:
saySomethingElse("Dolly")
// == ((s: String) => { "hello" + " " + s })("Dolly")
// == "hello" + " " + "Dolly"
Note that saySomethingElse can just be a val not a def. It is just a variable that contains a function, it doesn't need to be a function itself.

How to access list in Scala test case

I have a test case as a list, and I want to access "Andorra" as input[0] and "04" as input[1] of the list for a parameter, but I am given the error value input of type (String, String) does not take type parameters. How do I properly access these strings and use them for my parameters?
test("normal case") {
val testCases = List {
("Andorra", "04") -> (Map("la massana" -> 7211), List("les escaldes"))
}
for ((input, (mapOut, listOut)) <- testCases) {
var computedMap: collection.mutable.Map[String, Int] = PaleBlueDot.cityPopulations(countriesFile, citiesFilename, input[0], input[1])
var computedList: List[String] = PaleBlueDot.aboveAverageCities(countriesFile, citiesFilename, input[0])
assert(computedMap == mapOut, input + " -> " + computedMap)
assert(computedList.sorted == listOut.sorted, input + " -> " + computedList)
}
}

unreachable code in scala

val LIST = scala.collection.mutable.MutableList[String]()
val filterF = new Function[Path, Boolean] {
def apply(x: Path): Boolean = {
println("looking into " + x)
val flag = if (x.toString.split("/").last.split("_").last.toLong < System.currentTimeMillis) {
println("considered " + x)
LIST += x.toString
return true
} else {
println("NOT considered " + x)
return false
}
return flag
}
}
I am trying to update the external variable LIST inside the function filterF. But the problem is that after the println("looking into "+x)
line the rest of the code is unreachable.
val flag = if (x.toString.split("/").last.split("_").last.toLong < System.currentTimeMillis) {
println("considered " + x)
LIST += x.toString
return true
} else {
println("NOT considered " + x)
return false
}
return flag
I can't understand why this code is unreachable. Is there some character in the code that is actually reason for this?
Do not use return
When you use return control of execution will leave the function and all code after the return statement will not be reachable
code after return will be unreachable
def foo: Int = {
return 1
2 + 3 //unreachable
}
In case of if expression
def bar: Int = {
if (true) {
return 1
} else {
return 2
}
1 + 2 //unreachable
}
In Scala return statement is optional and not recommended as its not consider functional coding practice.
The value of last expression in the code block is the return value in Scala. So don't worry about explicit return just leave it to the program
val flag = if (x.toString.split("/").last.split("_").last.toLong < System.currentTimeMillis) {
println("considered " + x)
LIST += x.toString
true //removed return
} else {
println("NOT considered " + x)
false // removed return
}
Halting the program executing by throwing an exception or by returning value or by explicitly calling exit is not functional way of doing things. Unfortunately Scala does allow it. But if you want to be a good citizen of functional world. You better avoid it.
Avoid mutable collections
Use mutable collections if you have a strong need for it. There are advantages of immutable collections
1) They are thread safe.
2) Bug free (no surprises by accidental mutations and no blocking).
3) Referential transparency.
4) Reasonable performance.
Use immutable list instead of mutable list.
Use Scala lambda notation and Syntactic sugar
Syntactic sugar is there for a reason. Syntactic sugar reduces the boilerplate code. So that your code looks clear, cleaner and better. Helps in code maintainability. Code remains bug free for longer time.
Instead of Function1 trait use lambda notation.
scala> val f = new Function1[String, String] { def apply(str: String): String = str}
f: String => String = <function1>
scala> val f = {str: String => str}
f: String => String = <function1>
So your code becomes
val paths = List[Path]() //assume you have Paths in it.
val filter = {path: Path => path.toString.split("/").last.split("_").last.toLong < System.currentTimeMillis }
val resultList = paths.filter(filter)
This is caused the flag is val not def, but your statement is using the return to return true or false. the return keywords is only for method not for function.
The correct way maybe like:
val flag = if (x.toString.split("/").last.split("_").last.toLong < System.currentTimeMillis) {
println("considered " + x)
LIST += x.toString
true
}
else {
println("NOT considered " + x)
false
}

Build dynamic query with Slick 2.1.0

Goal is to filter Items with optional keywords and/or shopId.
If none of them are defined, all Items should be returned.
My attempt is
case class ItemSearchParameters(keywords: Option[String], shopId: Option[Long])
def search(params: ItemSearchParameters): Either[Failure, List[Item]] = {
try {
db withDynSession {
val q = Items.query
if (params.keywords.isDefined) {
q.filter { i =>
((i.title like "%" + params.keywords + "%")
|| (i.description like "%" + params.keywords + "%"))
}
}
if (params.shopId.isDefined) {
q.filter { i =>
i.shopId === params.shopId
}
}
Right(q.run.toList)
}
} catch {
case e: SQLException =>
Left(databaseError(e))
}
}
params.keywords or params.ShopId defined this function returned all Items. Can someone please explain what is wrong?
Update: second attempt
def search(params: ItemSearchParameters): Either[Failure, List[Item]] = {
try {
db withDynSession {
var q = Items.query
q = params.keywords.map{ k => q.filter(_.title like "%" + k + "%")} getOrElse q
q = params.keywords.map{ k => q.filter(_.description like "%" + k + "%")} getOrElse q
q = params.shopId.map{ sid => q.filter(_.shopId === sid)} getOrElse q
Right(q.run.toList)
}
} catch {
case e: SQLException =>
Left(databaseError(e))
}
}
For this second attempt how to do (title OR description) if keywords isDefined?
Update: Third attempt with MaybeFilter Not working
case class MaybeFilter[X, Y](val query: scala.slick.lifted.Query[X, Y, Seq]) {
def filteredBy(op: Option[_])(f:(X) => Column[Option[Boolean]]) = {
op map { o => MaybeFilter(query.filter(f)) } getOrElse { this }
}
}
class ItemDAO extends Configuration {
implicit def maybeFilterConversor[X,Y](q:Query[X,Y,Seq]) = new MaybeFilter(q)
def search(params: ItemSearchParameters): Either[Failure, List[Item]] = {
try {
db withDynSession {
val q = Items
.filteredBy(params.keywords){i => ((i.title like "%" + params.keywords + "%")
|| (i.description like "%" + params.keywords + "%"))}
.filteredBy(params.shopId){_.shopId === params.shopId}
.query
Right(q.list)
}
} catch {
case e: SQLException =>
Left(databaseError(e))
}
}
}
Third attempt returns empty list if keywords is given
def search(params: ItemSearchParameters): Either[Failure, List[Item]] = {
try {
db withDynSession {
var q = Items.query
q = params.keywords.map{ k => q.filter(
i => (i.title like "%" + k + "%")
|| (i.description like "%" + k + "%")
)} getOrElse q
q = params.shopId.map{ sid => q.filter(
_.shopId === sid
)} getOrElse q
Right(q.run.toList)
}
} catch {
case e: SQLException =>
Left(databaseError(e))
}
}
I am not sure it is the best answer because of var q
As I understood you correct, you want to make a filter by optional fields.
Your second attempt is quiet closer to reality, the first has incorrect matching, you compare option fields to non option. You've answered your own answer while I was writing this response :)
I'd like to recommend you this MaybeFilter https://gist.github.com/cvogt/9193220
Or here is modified version: https://github.com/neowinx/hello-slick-2.1-dynamic-filter/blob/master/src/main/scala/HelloSlick.scala#L3-L7
Maybe this can help you to solve your problem in a more generic way.

Scala anonymous functions

Why does my anonymous function not work?
Compiler shows me an error on line with
foreach((line: String) => {
My code:
Source.fromFile(siteDir.getPath).getLines()
.map(_.trim())
.filter(!_.isEmpty())
.foreach((line: String) => { // I got here "error: type mismatch; found : Unit required: String"
val pos = line.indexOf('=')
if (pos != -1) {
val key = line.substring(0, pos).trim()
val value = line.substring(pos + 1).trim()
readMeCache(siteId.get) + (key -> value)
}
})
What is the right way to fix it?