scala sys.process_ illegal start of simple expression error - scala

I got an error "illegal start of simple expression" in scala while trying to do this:
def test() = {
val h = "ls"!
if (h != 0)
println("error")
}
this is the error
[error] if (h != 0)
[error] one error found
[error] (compile:compileIncremental) Compilation failed
Can anyone tell me what I did wrong?

Scala compiler is getting confused here because you are calling ! as a postfix operator. It can't figure out which version to use and where to place the implied semicolon. You can either add a semicolon like this:
def test() = {
val h = "ls"!;
if (h != 0)
println("error")
}
or call it as a method:
def test() = {
val h = "ls".!
if (h != 0)
println("error")
}
or add a new line:
def test() = {
val h = "ls"!
if (h != 0)
println("error")
}

Best practice to use a postfix operator is to use dot . operator. You should invoke it like val h = "ls".!
It makes code less ambiguous as semicolon is optional in Scala and compiler might treat it as an infix notation.
From Scala doc:
This style is unsafe, and should not be used. Since semicolons are
optional, the compiler will attempt to treat it as an infix method if
it can, potentially taking a term from the next line.
For full reference see this link: Suffix Notation. This post may also be helpful Scala's "postfix ops".

Related

Type mismatch even when Vector type has been declared

I have a very simple method in a class:
def partysCandidate(party: String): Vector[Candidate]= {
var result = Vector[Candidate]()
for (candidate <- this.candidates) {
if (candidate.party == party) result = result + candidate
}
result
}
However it gave me Error type mismatch found : package.Candidate required: String at result + candidate. I couldn't figure out why. Any help would be much appreciated.
Many thanks!
There is no method + on a Vector, there are +: (prepend), :+ (append) (colon is treated as mnemonic for collection), etc.
There is however any2stringadd implicit class which - when you call sth.+(x: String) on something which doesn't have such method - call .toString on sth before appending x to it, which would return String. This results in the error you see. Accidental usage of this extension method is a reason why this got deprecated and why many linters defend against it.
Your code could be fixed by using the right operator e.g.
if (candidate.party == party) result = result :+ candidate
however in this particular case you can just use for-comprenension to build the result without mutation
def partysCandidate(party: String): Vector[Candidate] =
for {
candidate <- candidates
if candidate.party == party
} yield candidate
or even shorter
def partysCandidate(party: String): Vector[Candidate] =
candidates.filter(c => c.party == party)

Error while finding lines starting with H or I using Scala

I am trying to learn Spark and Scala. I am working on a scenario to identify the lines that start with H or I. Below is my code
def startWithHorI(s:String):String=
{
if(s.startsWith("I")
return s
if(s.startsWith("H")
return s
}
val fileRDD=sc.textFile("wordcountsample.txt")
val checkRDD=fileRDD.map(startWithHorI)
checkRDD.collect
It is throwing an error while creating the function Found:Unit Required:Boolean.
From research I understood that it is not able to recognize the return as Unit means void. Could someone help me.
There are a few things wrong with your def, we will start there:
It is throwing the error because according to the code posted, your syntax is incomplete and the def is defined improperly:
def startWithHorI(s:String): String=
{
if(s.startsWith("I")) // missing extra paren char in original post
s // do not need return statement
if(s.startsWith("H")) // missing extra paren char in original post
s // do not need return statement
}
This will still return an error because we are expecting a String when the compiler sees that it's returning an Any. We cannot do this if we do not have an else case (what will be returned when s does not start with H or I?) - the compiler will see this as an Any return type. The correction for this would be to have an else condition that ultimately returns a String.
def startWithHorI(s: String): String = {
if(s.startsWith("I")) s else "no I"
if(s.startsWith("H")) s else "no H"
}
If you don't want to return anything, then an Option is worth looking at for a return type.
Finally we can achieve what you are doing via filter - no need to map with a def:
val fileRDD = sc.textFile("wordcountsample.txt")
val checkRDD = fileRDD.filter(s => s.startsWith("H") || s.startsWith("I"))
checkRDD.collect
While passing any function to rdd.map(fn) make sure that fn covers all possible scenarios.
If you want to completely avoid strings which does not start with either H or I then use flatMap and return Option[String] from your function.
Example:
def startWithHorI(s:String): Option[String]=
{
if(s.startsWith("I") || s.startsWith("H")) Some(s)
else None
}
Then,
sc.textFile("wordcountsample.txt").flatMap(startWithHorI)
This will remove all rows not starting with H or I.
In general, to minimize run-time errors try to create total functions which handles all possible values of the arguments.
Something like below would work for you?
val fileRDD=sc.textFile("wordcountsample.txt")
fileRDD.collect
Array[String] = Array("Hello ", Hello World, Instragram, Good Morning)
val filterRDD=fileRDD.filter( x=> (x(0) == 'H'||x(0) == 'I'))
filterRDD.collect()
Array[String] = Array("Hello ", Hello World, Instragram)

How to reassign value to def in scala

I am writing a parser in which I have the following function:
def lastop:(Either[RDD[(Int,Array[Float])], Float], Either[RDD[(Int,Array[Float])], Float]) => RDD[(Int,Array[Float])] = add
In which "add" is a function to perform addition. Then I want to use it in my program like the following line:
terms.foreach(t =>
t match { case nums ~ op => lastop = op; stack = reduce(stack ++ nums, op)}
I am getting the following error:
[error] /home/mahsa/calculator/temp/ScalaParser.scala:183: reassignment to val
[error] t match { case nums ~ op => lastop = op; stack = reduce(stack ++ nums, op)}
[error] ^
Can't figure how to solve this error!
You want to store a changing reference to the function you want to invoke. If you are storing and reassigning something, that implies you need a var, not a val or a def. Try declaring lastop like:
var lastop:(Either[RDD[(Int,Array[Float])], Float], Either[RDD[(Int,Array[Float])], Float]) => RDD[(Int,Array[Float])] = add
Note that you will still need to invoke lastop like a function, since retrieving the var's value will return a function. It's a subtle but significant difference.

for comprehensions with if guard

How do I use for comprehensions with if guard?
type Error = String
type Success = String
def csrfValidation(session:Session, body:JsValue):Either[Error,Success] = {
val csrfRet = for (csrfSession <- csrfStateSessionValidation(session).right;
csrfReq <- csrfStateReqBodyValidation(body).right if (csrfSession == csrfReq)) yield (csrfReq)
if (csrfRet.isRight)
Right(csrfRet)
else {
Logger.warn("request and session csrf is not the same")
Left("Oops,something went wrong, request and session csrf is not the same")
}
}
I got this error when using it.
'withFilter' method does not yet exist on scala.util.Either.RightProjection[Error,Success], using `filter' method instead
EDIT:
I got another error. I think it returns an option result when if guard is used.
[error] type mismatch;
[error] found : Option[scala.util.Either[Nothing,controllers.ProfileApiV1.Success]]
[error] required: scala.util.Either[?,?]
[error] csrfReq <- csrfStateReqBodyValidation(body).right if (csrfSession == csrfReq)) yield (csrfReq)
EDIT2
This is what I did to fix above error. I also move if-guard to later process.
val result = for {
foo <- Right[String,String]("teststring").right
bar <- Right[String,String]("teststring").right
} yield (foo, bar)
result fold (
ex => Left("Operation failed with " + ex),
v => v match {
case (x,y) =>
if (x == y) Right(x)
else Left("value is different")
}
)
I believe what you are seeing is a compiler warning and not an actual error. The RightProjection does not support withFilter which is what is "preferred" (but not yet required) for a guard condition, so plain old filter is used instead. As to the difference to these functions and why this came about, check out the link below for an explanation.
http://scala-programming-language.1934581.n4.nabble.com/Rethinking-filter-td2009215.html#a2009218
Add either a semi-colon or a new line just before the if.

Scala's infix notation with object +, why not possible?

I can name objects like this, but can't call m:
object + {
def m (s: String) = println(s)
}
Can't call +.m("hi"):
<console>:1: error: illegal start of simple expression
+.m("hi")
Also can't call + m "hi" (preferred for DSL-usage).
But with object ++ it works fine! Do they conflict with (not existent) unary_+ methods? Is it possible to avoid this?
Indeed it is not possible with unary operators. If you want to call it anyways, you could resort to using the name generated by the compiler for the JVM (which starts with a dollar):
scala> object + {
| def m( s: String ) = println(s)
| }
defined module $plus
scala> +.m("hello")
<console>:1: error: illegal start of simple expression
+.m("hello")
^
scala> $plus.m("hello")
hello
I believe the problem is that in order to handle unary operators without ambiguity, scala relies on a special case: only !, +, - and ~ are treated as unary operators. Thus in +.m("hi"), scala treat + as an unary operator and can't make sense of the whole expression.
Another code using package:
object Operator extends App {
// http://stackoverflow.com/questions/13367122/scalas-infix-notation-with-object-why-not-possible
pkg1.Sample.f
pkg2.Sample.f
}
package pkg1 {
object + {
def m (s: String) = println(s)
}
object Sample {
def f = {
// +.m("hi") => compile error: illegal start of simple expression
// + m "hi" => compile error: expected but string literal found.
$plus.m("hi pkg1")
$plus m "hi pkg1"
}
}
}
package pkg2 {
object + {
def m (s: String) = println(s)
}
object Sample {
def f = {
pkg2.+.m("hi pkg2")
pkg2.+ m "hi pkg2"
pkg2.$plus.m("hi pkg2")
pkg2.$plus m "hi pkg2"
}
}
}
java version "1.7.0_09"
Scala code runner version 2.9.2