I read the tutorials on how to write a for loop in scala but it doesn't seem to work.
object Main {
def pascalTriangle(rows:Int):List[Int]= {
var previousRow:List[Int] = Nil
var row:List[Int] = Nil
for(i <- 1 to rows) {
for( j <- 1 to i+1){
if (j == 1 || j == i)
row :+ 1
else
row :+ previousRow(j) + previousRow(j - 1)
}
previousRow = row
println (row)
row = Nil
}
}
def main(args: Array[String]) {
pascalTriangle(6)
}
}
I keep getting a type mismatch error within the for loop's conditions.
Your method pascalTriangle is declared to return a List[int].
However, the last expression in the body of the method is your outer for-loop. This is the expression whose value will be returned by the method.
As for-loops (that don't use the yield keyword) evaluate to (): Unit, there is a type-mismatch with the expected return type (for-loops without yield are used only for side-effect).
If you wanted to, for example, return row, you would need to simply write 'row' at the end of the method, after the outer for-loop.
Related
I implemented to find max value in the list.
I know that in Scala, You don't have to use 'return', just drop it.
So I wrote like this,
def max(xs: List[Int]):Int={
if(xs.isEmpty) throw new java.util.NoSuchElementException
def f(cur_max:Int, xs:List[Int]):Int={
if(xs.isEmpty)
cur_max // <- it doesn't return value but just keep going below code.
if(cur_max < xs.head)
f(xs.head,xs.tail)
else
f(cur_max,xs.tail)
}
f(xs.head,xs)
}
When it traversed to end of List, it should be returned cur_max value.
However, It just keeps going. Why doesn't it return cur_max.
To fix this problem, I put 'return' expression that Scala doesn't recommend like ('return cur_max').
In Scala it is not enought just to drop value - method returns last evaluated statement. In your case you have two statements:
if(xs.isEmpty)
cur_max
and
if(cur_max < xs.head)
f(xs.head,xs.tail)
else
f(cur_max,xs.tail)
So the result of second expression one gets returned.
To fix it add else statement:
if(xs.isEmpty)
cur_max
else if(cur_max < xs.head)
f(xs.head,xs.tail)
else
f(cur_max,xs.tail)
made several changes. some of them just code style to be more readable like having brackets on if expressions.
def max(xs: List[Int]): Int = {
def f(cur_max: Int, xs: List[Int]): Int = {
if (xs.isEmpty) {
cur_max // <- it doesn't return value but just keep going below code.
} else {
if (cur_max < xs.head) {
f(xs.head, xs.tail)
}
else {
f(cur_max, xs.tail)
}
}
}
if (xs.isEmpty) {
throw new java.util.NoSuchElementException
} else {
f(xs.head, xs.tail)
}
}
basically there are some cases on your inner function, which you named f:
the list is empty -> you should return the current max value
the list is not empty AND the current max is smaller than the first element of the remaining list -> update the current max and call the function with the list tail
the list is not empty AND the current max is >= than the first element of the remaining list -> call the function with the list tail and the same current max
Here is an artificial toy example that demonstrates my problem:
def sscce(): Int = {
val rand = new Random()
var count = 0
while (true) { // type mismatch; found: Unit, required: Int
count += 1
if (rand.nextInt() == 42) return count
}
}
How can I help the compiler understand that this method will always return an Int?
I know the above toy example could easily be refactored to get rid of the infinite loop altogether, but I really want to have the infinite loop in my actual code. Trust me on this ;)
Always return an Int:
def sscce(): Int = {
val rand = new Random()
var count = 0
while (true) {
count += 1
if (rand.nextInt() == 42) return count
}
count // <-- this
}
You can also do:
def foo: Int = {
...
while(true) {
... return ...
}
throw new IllegalStateException // unreachable
}
this will typecheck because the type of the throw is Nothing, which is a subtype of Int.
See this question. While loops don't return a value. i.e. they return Unit which is the last statement in your function. So, the definition says it returns an Int but it actually returns Unit thus the type error. #ionut's answer fixes the type error by returning count as the last statement or here is a recursive approach.
def sscce(): Int = {
val rand = new Random()
def ssccer(count: Int): Int = {
if(rand.nextInt == 42) return count
else ssccer(count + 1)
}
ssccer(0)
}
Per the SLS, a while loop is executed similarly to:
def whileLoop(cond: => Boolean)(body: => Unit): Unit =
if (cond) { body ; whileLoop(cond)(body) } else {}
ie., it returns Unit. So the compiler sees the while as the last statement in sscce(), and therefore assumes that you're trying to return Unit. I don't think it's smart enough to realize that return count will eventually always return an Int.
The simple solution is to follow the suggestion of #Brian or #IonutGStan, and force it to return count, whether it truly needs it or not.
From a code quality standpoint, it would be good to ditch the while(true) loop and replace it with something more readable. As a nice side effect, it also solves your problem:
def sscce(): Int = {
val rand = new Random()
var count = 1
while (rand.nextInt() != 42) {
count += 1
}
count
}
I am new to Scala and try to use it in a functional way. Here are my questions:
Why can't I create a new binding for 'cnt' variable with function return value using '<-' operator?
How can increment immutable variable in a functional way (similar to Haskell <-) ? For the sake of experiment I don't want to use mutable vars.
import scala.io.Source
object MyProgram {
def main(args: Array[String]): Unit = {
if (args.length > 0) {
val lines = Source.fromFile(args(0)).getLines()
val cnt = 0
for (line <- lines) {
cnt <- readLines(line, cnt)
}
Console.err.println("cnt = "+cnt)
}
}
def readLines(line: String, cnt:Int):Int = {
println(line.length + " " + line)
val newCnt = cnt + 1
return (newCnt)
}
}
As for side effects, I could never expect that (line <- lines) is so devastating! It completely unwinds lines iterator. So running the following snippet will make size = 0 :
val lines = Source.fromFile(args(0)).getLines()
var cnt = 0
for (line <- lines) {
cnt = readLines(line, cnt)
}
val size = lines.size
Is it a normal Scala practice to have well-hidden side-effects like this?
You could fold on lines like so:
val lines = Source.fromFile(args(0)).getLines()
val cnt = lines.foldLeft(0) { case (count, line) => readLines(line, count) }
Console.err.println("cnt = "+cnt)
Your readLines method does side-effect with the call to println, but using foldLeft guarantees left-to-right processing of the list, so the output should be the same.
Why can't I reassign immutable 'cnt' variable with function return value using '<-' operator?
Why would you? If you has java experience, <- has the simular meaning as : in for(Item x: someCollection). It is just a syntactic sugar for taking current item from collection and naming it, it is not a bind operator in general.
Moreover, isn't reassign immutable oxymoron?
How can increment immutable variable in a functional way (similar to Haskell <-)?
Scala people usually use .zipWithIndex but this will work only if you're going to use counter inside for comprehension:
for((x, i) <- lines.zipWithIndex) { println("the counter value is" + i) }
So I think you need to stick with lines.count or use fold/reduce or = to assign new value to variable.
<- is not an operator, just a syntax used in for expressions. You have to use =. If you want to use <- it must be within the for-iteration-expression. And you cannot increment a val. If you want to modify that variable, make it a var.
Scala noob here.
Here is my simple for loop
def forExampleStoreValues = {
println(">>forExampleStoreValues");
val retVal = for{i <- 1 to 5 if i % 2 == 0} yield i;
println("retVal=" + retVal);
}
My expectation is when I call this, the last val will be returned automatically. However when I call this from main,
object MainRunner {
def main(args: Array[String]){
println("Scala stuff!"); // println comes from Predef which definitions for anything inside a Scala compilation unit.
runForExamples();
}
def runForExamples() {
val forLE = new ForLoopExample(); // No need to declare type.
println("forExampleStoreValues=" +forLE.forExampleStoreValues)
}
}
The output is:
>>forExampleStoreValues
retVal=Vector(2, 4)
forExampleStoreValues=()
So then I try to explictly return the retval.
def forExampleStoreValues = {
println(">>forExampleStoreValues");
val retVal = for{i <- 1 to 5 if i % 2 == 0} yield i;
println("retVal=" + retVal);
return retval;
}
This gives:
method forExampleStoreValues has return statement; needs result type
So I change function signature to:
def forExampleStoreValues():Vector
which gives:
Vector takes type parameters
At this stage, not sure what to put in and I want to ensure I am not doing something I don't need to do.
You don't need an explicit return. The last expression in your method will always be returned.
def forExampleStoreValues = {
println(">>forExampleStoreValues")
val retVal = for{i <- 1 to 5 if i % 2 == 0} yield i
println("retVal=" + retVal)
retVal
}
This also means that if you end your method with println(...), it will return () of type Unit, since that is the return type of println. If you do you an explicit return (usually because you want to return early), you need to specify the result type. The result type is Vector[Int], not Vector.
The last value in a Scala function is returned. The explicit return is not necessary.
Your code can be simplified to this where the for expression returns a IndexSeq[Int] which is inferred by the compiler.
def forExampleStoreValues = {
for{i <- 1 to 5 if i % 2 == 0} yield i;
}
scala>forExampleStoreValues
res0: scala.collection.immutable.IndexedSeq[Int] = Vector(2, 4)
The expression for{i <- 1 to 5 if i % 2 == 0} yield i; returns an instance of Vector[Int] which implements the trait IndexedSeq. So, to manually specify the type you can add IndexedSeq[Int] to the for expression.
def forExampleStoreValues: IndexedSeq[Int] = {
for{i <- 1 to 5 if i % 2 == 0} yield i;
}
Much like this question:
Functional code for looping with early exit
Say the code is
def findFirst[T](objects: List[T]):T = {
for (obj <- objects) {
if (expensiveFunc(obj) != null) return /*???*/ Some(obj)
}
None
}
How to yield a single element from a for loop like this in scala?
I do not want to use find, as proposed in the original question, i am curious about if and how it could be implemented using the for loop.
* UPDATE *
First, thanks for all the comments, but i guess i was not clear in the question. I am shooting for something like this:
val seven = for {
x <- 1 to 10
if x == 7
} return x
And that does not compile. The two errors are:
- return outside method definition
- method main has return statement; needs result type
I know find() would be better in this case, i am just learning and exploring the language. And in a more complex case with several iterators, i think finding with for can actually be usefull.
Thanks commenters, i'll start a bounty to make up for the bad posing of the question :)
If you want to use a for loop, which uses a nicer syntax than chained invocations of .find, .filter, etc., there is a neat trick. Instead of iterating over strict collections like list, iterate over lazy ones like iterators or streams. If you're starting with a strict collection, make it lazy with, e.g. .toIterator.
Let's see an example.
First let's define a "noisy" int, that will show us when it is invoked
def noisyInt(i : Int) = () => { println("Getting %d!".format(i)); i }
Now let's fill a list with some of these:
val l = List(1, 2, 3, 4).map(noisyInt)
We want to look for the first element which is even.
val r1 = for(e <- l; val v = e() ; if v % 2 == 0) yield v
The above line results in:
Getting 1!
Getting 2!
Getting 3!
Getting 4!
r1: List[Int] = List(2, 4)
...meaning that all elements were accessed. That makes sense, given that the resulting list contains all even numbers. Let's iterate over an iterator this time:
val r2 = (for(e <- l.toIterator; val v = e() ; if v % 2 == 0) yield v)
This results in:
Getting 1!
Getting 2!
r2: Iterator[Int] = non-empty iterator
Notice that the loop was executed only up to the point were it could figure out whether the result was an empty or non-empty iterator.
To get the first result, you can now simply call r2.next.
If you want a result of an Option type, use:
if(r2.hasNext) Some(r2.next) else None
Edit Your second example in this encoding is just:
val seven = (for {
x <- (1 to 10).toIterator
if x == 7
} yield x).next
...of course, you should be sure that there is always at least a solution if you're going to use .next. Alternatively, use headOption, defined for all Traversables, to get an Option[Int].
You can turn your list into a stream, so that any filters that the for-loop contains are only evaluated on-demand. However, yielding from the stream will always return a stream, and what you want is I suppose an option, so, as a final step you can check whether the resulting stream has at least one element, and return its head as a option. The headOption function does exactly that.
def findFirst[T](objects: List[T], expensiveFunc: T => Boolean): Option[T] =
(for (obj <- objects.toStream if expensiveFunc(obj)) yield obj).headOption
Why not do exactly what you sketched above, that is, return from the loop early? If you are interested in what Scala actually does under the hood, run your code with -print. Scala desugares the loop into a foreach and then uses an exception to leave the foreach prematurely.
So what you are trying to do is to break out a loop after your condition is satisfied. Answer here might be what you are looking for. How do I break out of a loop in Scala?.
Overall, for comprehension in Scala is translated into map, flatmap and filter operations. So it will not be possible to break out of these functions unless you throw an exception.
If you are wondering, this is how find is implemented in LineerSeqOptimized.scala; which List inherits
override /*IterableLike*/
def find(p: A => Boolean): Option[A] = {
var these = this
while (!these.isEmpty) {
if (p(these.head)) return Some(these.head)
these = these.tail
}
None
}
This is a horrible hack. But it would get you the result you wished for.
Idiomatically you'd use a Stream or View and just compute the parts you need.
def findFirst[T](objects: List[T]): T = {
def expensiveFunc(o : T) = // unclear what should be returned here
case class MissusedException(val data: T) extends Exception
try {
(for (obj <- objects) {
if (expensiveFunc(obj) != null) throw new MissusedException(obj)
})
objects.head // T must be returned from loop, dummy
} catch {
case MissusedException(obj) => obj
}
}
Why not something like
object Main {
def main(args: Array[String]): Unit = {
val seven = (for (
x <- 1 to 10
if x == 7
) yield x).headOption
}
}
Variable seven will be an Option holding Some(value) if value satisfies condition
I hope to help you.
I think ... no 'return' impl.
object TakeWhileLoop extends App {
println("first non-null: " + func(Seq(null, null, "x", "y", "z")))
def func[T](seq: Seq[T]): T = if (seq.isEmpty) null.asInstanceOf[T] else
seq(seq.takeWhile(_ == null).size)
}
object OptionLoop extends App {
println("first non-null: " + func(Seq(null, null, "x", "y", "z")))
def func[T](seq: Seq[T], index: Int = 0): T = if (seq.isEmpty) null.asInstanceOf[T] else
Option(seq(index)) getOrElse func(seq, index + 1)
}
object WhileLoop extends App {
println("first non-null: " + func(Seq(null, null, "x", "y", "z")))
def func[T](seq: Seq[T]): T = if (seq.isEmpty) null.asInstanceOf[T] else {
var i = 0
def obj = seq(i)
while (obj == null)
i += 1
obj
}
}
objects iterator filter { obj => (expensiveFunc(obj) != null } next
The trick is to get some lazy evaluated view on the colelction, either an iterator or a Stream, or objects.view. The filter will only execute as far as needed.