if/else in Scala: Illegal start of simple expression/Il - scala

These are the errors:
scala.scala:13: error: not found: value listaFibonaccisAux
listaFibonaccisAux int 0
^
scala.scala:4: error: illegal start of simple expression
if (int>fibby) fibby :: (listaFibonaccisAux int (n+1))
^
scala.scala:1: error: illegal start of definition
else List()
^
scala.scala:1: error: eof expected but '}' found.
}
^
And here's my code, the errors seem to refer to the simple if/else statements, I already tried wrapping and unwrapping stuff in parens, but it did not help:
def listaFibonaccis (int:Int):List[Int]=
{
listaFibonaccisAux (int, 0)
}
def listaFibonaccisAux (int:Int, n:Int):List[Int]=
{
var fibby = fib n
if (int> fibby)
fibby :: (listaFibonaccisAux (int, (n+1)))
else
List()
}
def fib( n : Int) : Int = n match
{
case 0 | 1 => n
case _ => fib( n-1 ) + fib( n-2 )
}
fib finds a number n in the fibonacci sequence
listaFibonaccisAux creates a list of fibonacci numbers using fib, and stops when the numbers get bigger than int
listaFibonaccis is just a simple wrapper to call the other one with the 0 to start it
it's a plain if/else statement giving me trouble, and that's sad.

The compiler is complaining about the if/else because it doesn't think the line before has ended properly.
Try this: fib(n)
While "infix" (space notation) is sometimes handy...
instance.method(arg) into instance method arg
...it can't be applied as you've tried to use it.

Related

Identifier expected but integer literal found

I got this problem when writing a recursive function that calculates the number of points where two general functions f1 and f2 are equal(Assuming only Integer values).
object X1 {
def numEqual(f1:Int=>Int,f2:Int=>Int)(a:Int,b:Int):Int=
if(a>b) 0
else f1(a)==f2(a) ? 1+numEqual(f1,f2)(a+1,b):0+numEqual(f1,f2)(a+1,b)
And this is what compiler says :
X1.scala:5: error: identifier expected but integer literal found.
f1(a)==f2(a) ? 1+numEqual(f1,f2)(a+1,b) : 0+numEqual(f1,f2)(a+1,b)
^
one error found.
Thank you!
The if construct in Scala is an expression. As the others already said, there's no ternary operator because there's no need for it - the if being already an expression.
I rewrote your function to a tail-recursive version (to avoid StackOverflowErrors), let's see how it looks:
#tailrec def numEqual(f1: Int => Int, f2: Int => Int)(a: Int, b: Int, res: Int = 0): Int =
if (a > b) res
else {
val inc = if (f1(a) == f2(a)) 1 else 0
numEqual(f1, f2)(a + 1, b, res + inc)
}
Notice how the result of the if expression is assigned to inc - here you would normally use the ternary operator. Anyway, I hope this helps you.
the ? : operator doesn't exist in scala
Scala does not use the ternary operator, http://alvinalexander.com/scala/scala-ternary-operator-syntax

Why is it possible to assign recursive lambdas to non-lazy vals in Scala?

In the following statement the val f is defined as a lambda that references itself (it is recursive):
val f: Int => Int = (a: Int) =>
if (a > 10) 3 else f(a + 1) + 1 // just some simple function
I've tried it in the REPL, and it compiles and executes correctly.
According to the specification, this seems like an instance of illegal forward referencing:
In a statement sequence s[1]...s[n] making up a block, if a simple
name in s[i] refers to an entity defined by s[j] where j >= i,
then for all s[k] between and including s[i] and s[j],
s[k] cannot be a variable definition.
If s[k] is a value definition, it must be lazy.
The assignment is a single statement, so it satisfied the j >= i criteria, and it is included in the interval of statements the two rules apply to (between and including s[i] and s[j]).
However, it seems that it violates the second rule, because f is not lazy.
How is that a legal statement (tried it in Scala 2.9.2)?
You probably tried to use this in the REPL, which wraps all contents in an object definition. This is important because in Scala (or better: on the JVM) all instance values are initialized with a default value, which is null for all AnyRefs and 0, 0.0 or false for AnyVals. For method values this default initialization does not happen, therefore you get an error message in this case:
scala> object x { val f: Int => Int = a => if (a > 10) 3 else f(a+1)+1 }
defined object x
scala> def x { val f: Int => Int = a => if (a > 10) 3 else f(a+1)+1 }
<console>:7: error: forward reference extends over definition of value f
def x { val f: Int => Int = a => if (a > 10) 3 else f(a+1)+1 }
^
This behavior can even lead to weird situations, therefore one should be careful with recursive instance values:
scala> val m: Int = m+1
m: Int = 1
scala> val s: String = s+" x"
s: String = null x

Scala for comprehension of sequence inside a Try

I am writing a Scala program in which there is an operation that creates a sequence. The operation might fail, so I enclose it inside a Try. I want to do sequence creation and enumeration inside a for comprehension, so that a successfully-created sequence yields a sequence of tuples where the first element is the sequence and the second is an element of it.
To simplify the problem, make my sequence a Range of integers and define a createRange function that fails if it is asked to create a range of an odd length. Here is a simple for comprehension that does what I want.
import scala.util.Try
def createRange(n: Int): Try[Range] = {
Try {
if (n % 2 == 1) throw new Exception
else Range(0, n)
}
}
def rangeElements(n: Int) {
for {
r <- createRange(n)
x <- r
} println(s"$r\t$x")
}
def main(args: Array[String]) {
println("Range length 3")
rangeElements(3)
println("Range length 4")
rangeElements(4)
}
If you run this it correctly prints.
Range length 3
Range length 4
Range(0, 1, 2, 3) 0
Range(0, 1, 2, 3) 1
Range(0, 1, 2, 3) 2
Range(0, 1, 2, 3) 3
Now I would like to rewrite my rangeElements function so that instead of printing as a side-effect it returns a sequence of integers, where the sequence is empty if the range was not created. What I want to write is this.
def rangeElements(n: Int):Seq[(Range,Int)] = {
for {
r <- createRange(n)
x <- r
} yield (r, x)
}
// rangeElements(3) returns an empty sequence
// rangeElements(4) returns the sequence (Range(0,1,2,3), 0), (Range(0,1,2,3), 1) etc.
This gives me two type mismatch compiler errors. The r <- createRange(n) line required Seq[Int] but found scala.util.Try[Nothing]. The x <- r line required scala.util.Try[?] but found scala.collection.immutable.IndexedSeq[Int].
Presumably there is some type erasure with the Try that is messing me up, but I can't figure out what it is. I've tried various toOption and toSeq qualifiers on the lines in the for comprehension to no avail.
If I only needed to yield the range elements I could explicitly handle the Success and Failure conditions of createRange myself as suggested by the first two answers below. However, I need access to both the range and its individual elements.
I realize this is a strange-sounding example. The real problem I am trying to solve is a complicated recursive search, but I don't want to add in all its details because that would just confuse the issue here.
How do I write rangeElements to yield the desired sequences?
The problem becomes clear if you translate the for comprehension to its map/flatMap implementation (as described in the Scala Language Spec 6.19). The flatMap has the result type Try[U] but your function expects Seq[Int].
for {
r <- createRange(n)
x <- r
} yield x
createRange(n).flatMap {
case r => r.map {
case x => x
}
}
Is there any reason why you don't use the getOrElse method?
def rangeElements(n: Int):Seq[Int] =
createRange(n) getOrElse Seq.empty
The Try will be Success with a Range when n is even or a Failure with an Exception when n is odd. In rangeElements match and extract those values. Success will contain the valid Range and Failure will contain the Exception. Instead of returning the Exception return an empty Seq.
import scala.util.{Try, Success, Failure}
def createRange(n: Int): Try[Range] = {
Try {
if (n % 2 == 1) throw new Exception
else Range(0, n)
}
}
def rangeElements(n: Int):Seq[Tuple2[Range, Int]] = createRange(n) match {
case Success(s) => s.map(xs => (s, xs))
case Failure(f) => Seq()
}
scala> rangeElements(3)
res35: Seq[(Range, Int)] = List()
scala> rangeElements(4)
res36: Seq[(Range, Int)] = Vector((Range(0, 1, 2, 3),0), (Range(0, 1, 2, 3),1), (Range(0, 1, 2, 3),2), (Range(0, 1, 2,3),3))

Adding to scala map within for loop and conditional statement

I'm getting an error message of "error: type arguments [Any] do not conform to trait Cloneable's type parameter bounds [+A <: AnyRef]," which I can't make heads or tails of.
Specifically,
var M = mutable.Map[Int, mutable.Set[Int]]()
for(i <- 1 to 100; j <- 1 to 100) {
if(!M.contains(i)) {M += i -> mutable.Set[Int](j)}
else {M(i) += j}
}
(I'm actually trying something more complicated, but this is the error generating code tweaked and simplified to a minimum)
And the last line of the above code generates the error message. If I strip it down further
for(i <- 1 to 100; j <- 1 to 100) {
if(!M.contains(i)) {M += i -> mutable.Set[Int](j)}
}
it works!
How do I make the above code work?
Digal diagnosed the problem (failure to unify the types of the if-else branches) and it looks like a compiler bug. Here's a further simplified case that will give an error in the REPL, after a lengthy compilation time,
if (true) {
null: collection.mutable.Map[Int, Int]
} else {
null: collection.mutable.Set[Int]
}
In the meantime, you can get your code to compile with an explicit type sprinkled somewhere in the if-else statement,
for(i <- 1 to 100; j <- 1 to 100) {
if(!M.contains(i)) {M += i -> mutable.Set[Int](j)}
else {M(i) += j}: Unit
}
I filed an issue here: https://issues.scala-lang.org/browse/SI-4938
I've reduced your example even further:
scala> if(!M.contains(1)) {M += 1 -> mutable.Set[Int](1)} else {M(1) += 1};
<console>:9: error: type arguments [Any] do not conform to trait Cloneable's type parameter bounds [+A <: AnyRef]
val res17 =
^
The problem seem to occur when compiler tries to find common return type for both branches:
The first one is
scala> M += 1 -> mutable.Set[Int](1)
res19: scala.collection.mutable.Map[Int,scala.collection.mutable.Set[Int]] = ...
And the "else" part is
scala> M(1) += 1
res18: scala.collection.mutable.Set[Int] = Set(1)
If I add a return value to the end of this expression, REPL eats it without errors:
scala> if(!M.contains(1)) {M += 1 -> mutable.Set[Int](1)} else {M(1) += 1}; println("hello")
hello
Because the expression's return type is Unit.

how to simplify scala's function literal like this?

I'm new to scala and trying to write a function literal that check whether a given integer is odd or not.
my first attempt is:
val isOdd = (x:Int) => (x & 1) == 1
it works great, and, since the parameter x only appears once within this function literal, I'm tempted to use the "_" notation to simplify it further, like this:
val isOdd = ((_:Int) & 1 ) == 1
however this time the compiler complains :
warning: comparing a fresh object using `==' will always yield false
val isOdd = ((_:Int) & 1 ) == 1
what does this warning mean? why does the compiler recognize ((_ :Int) & 1) as fresh object rather than a bitwise operation that results in a value? is there any way to write this function literal using the "_" notation?
The problem is basically that Scala needs to tell the difference between
val isOdd = ((_:Int) & 1 ) == 1
where you want everything to the right of the equals sign to be a lambda, and
val result = collection.map( _ + 1 )
where you want only the stuff inside the parentheses to be a lambda
Scala has decided that when you use the underscore to create a lambda, that it's going to pick the innermost set of parentheses as the boundaries of that lambda. There's one exception: (_:Int) doesn't count as the innermost parentheses because its purpose is only to group they type declaration with the _ placeholder.
Hence:
val isOdd = ((_:Int) & 1 ) == 1
^^^^^^^^^^^^^^
this is the lambda
val result = collection.map( _ + 1 )
^^^^^^^
this is the lambda
val result = collection.map(( _ + 1) / 2)
^^^^^^^^
this is the lambda
and the compiler can't infer the type of the _
val result = somemap.map(( _ + 1) / 2 * _)
^^^^^^^^
this is an inner lambda with one parameter
and the compiler can't infer the type of the _
^^^^^^^^^^^^^^^^^
this is an outer lambda with one parameter
This last case lets you do things like
_.map(_ + 1)
and have that get translated into
x => x.map( y=> y + 1 )
Only slightly cheating:
val isOdd = (_: Int) % 2 == 1
:-)
There you go:
val isOdd = ((_: Int) & 1) andThen (1 ==)
What Scala is doing is this:
it sees ((_:Int) & 1 ) and creates an object of type (Int) => Int, that is, a function.
it then applies the comparison operator == to compare this function to the value 1
A function is not equal to the value 1. Therefore the result is false, so your code is equivalent to:
val isOdd = false
What you could do is create another anonymous function that does the == 1 part of your computation. This is ugly:
val isOdd = ((_: Int) & 1)(_: Int) == 1
This is equivalent to the more verbose (and perhaps easier to understand):
val isOdd = (x: Int) => 1 == ((_: Int) & 1)(x)
A different approach
val isOdd = (_:Int).&(1) == 1