I am trying to build a list in scala that given input (length,and a function) the output would be a list from 0 up to that length-1.
for example:
listMaker(3,f) = List(0,1,2)
so far I have created a helper class that takes 2 int and returns a list in that range.
the listMaker function is as follows:
def listMaker[A](length:Int, f:Int =>A):List[A] = length match{
case 0 => List()
case _ => listMaker(length,f)
}
my f function just takes a variable x and returns that:
def f(x:Int)=x
the comment below makes sense, but it still gets me errors. I think the edited code is an easier way to get where I would like to
However, now I get an infinite loop. What part of the logic am I missing?
A recursive function typically has to gradually "bite off" pieces of the input data until there is nothing left - otherwise it can never terminate.
What this means in your particular case is that length must decrease on each recursive call until it reaches zero.
def listMaker[A](length:Int, f:Int =>A):List[A] = length match{
case 0 => List()
case _ => listMaker(length,f)
}
But you are not reducing length - you are passing it unchanged to the next recursive call, so, your function cannot terminate.
(There are other problems too - you need to build up your result list as you recurse, but your current code simply returns an empty list. I assume this is a learning exercise, so I'm not supplying working code...).
Related
I currently have a value of result that is a string which represents cycles in a graph
> scala result
String =
0:0->52->22;
5:5->70->77;
8:8->66->24;8->42->32;
. //
. // trimmed to get by point across
. //
71:71->40->45;
77:77->34->28;77->5->70;
84:84->22->29
However, I want to have the output have the numbers in between be included and up to a certain value included. The example code would have value = 90
0:0->52->22;
1:
2:
3:
4:
5:5->70->77;
6:
7:
8:8->66->24;8->42->32;
. //
. // trimmed
. //
83:
84:84->22->29;
85:
86:
87:
88:
89:
90:
If it helps or makes any difference, this value is changed to a list for later purposes, such like
list_result = result.split("\n").toList
List[String] = List(0:0->52->22;, 5:5->70->77;, 8:8->66->24;8->42->32;, 11:11->26->66;11->17->66;
My initial thought was to insert the missing numbers into the list and then sort it, but I had trouble with the sorting so I instead look here for a better method.
Turn your list_result into a Map with default values. Then walk through the desired number range, exchanging each for its Map value.
val map_result: Map[String,List[String]] =
list_result.groupBy("\\d+:".r.findFirstIn(_).getOrElse("bad"))
.withDefault(List(_))
val full_result: String =
(0 to 90).flatMap(n => map_result(s"$n:")).mkString("\n")
Here's a Scastie session to see it in action.
One option would be to use a Map as an intermediate data structure:
val l: List[String] = List("0:0->52->22;", "5:5->70->77;", "8:8->66->24;8->42->32;", "11:11->26->66;11->17->66;")
val byKey: List[Array[String]] = l.map(_.split(":"))
val stop = 90
val mapOfValues = (1 to stop).map(_->"").toMap
val output = byKey.foldLeft(mapOfValues)((acc, nxt) => acc + (nxt.head.toInt -> nxt.tail.head))
output.toList.sorted.map {case (key, value) => println(s"$key, $value")}
This will give you the output you are after. It breaks your input strings into pseudo key-value pairs, creates a map to hold the results, inserts the elements of byKey into the map, then returns a sorted list of the results.
Note: If you are using this in anything like production code you'd need to properly check that each Array in byKey does have two elements to prevent any nullPointerExceptions with the later calls to head and tail.head.
The provided solutions are fine, but I would like to suggest one that can process the data lazily and doesn't need to keep all data in memory at once.
It uses a nice function called unfold, which allows to "unfold" a collection from a starting state, up to a point where you deem the collection to be over (docs).
It's not perfectly polished but I hope it may help:
def readLines(s: String): Iterator[String] =
util.Using.resource(io.Source.fromString(s))(_.getLines)
def emptyLines(from: Int, until: Int): Iterator[(String)] =
Iterator.range(from, until).map(n => s"$n:")
def indexOf(line: String): Int =
Integer.parseInt(line.substring(0, line.indexOf(':')))
def withDefaults(from: Int, to: Int, it: Iterator[String]): Iterator[String] = {
Iterator.unfold((from, it)) { case (n, lines) =>
if (lines.hasNext) {
val next = lines.next()
val i = indexOf(next)
Some((emptyLines(n, i) ++ Iterator.single(next), (i + 1, lines)))
} else if (n < to) {
Some((emptyLines(n, to + 1), (to, lines)))
} else {
None
}
}.flatten
}
You can see this in action here on Scastie.
What unfold does is start from a state (in this case, the line number from and the iterator with the lines) and at every iteration:
if there are still elements in the iterator it gets the next item, identifies its index and returns:
as the next item an Iterator with empty lines up to the latest line number followed by the actual line
e.g. when 5 is reached the empty lines between 1 and 4 are emitted, terminated by the line starting with 5
as the next state, the index of the line after the last in the emitted item and the iterator itself (which, being stateful, is consumed by the repeated calls to unfold at each iteration)
e.g. after processing 5, the next state is 6 and the iterator
if there are no elements in the iterator anymore but the to index has not been reached, it emits another Iterator with the remaining items to be printed (in your example, those after 84)
if both conditions are false we don't need to emit anything anymore and we can close the "unfolding" collection, signalling this by returning a None instead of Some[(Item, State)]
This returns an Iterator[Iterator[String]] where every nested iterator is a range of values from one line to the next, with the default empty lines "sandwiched" in between. The call to flatten turns it into the desired result.
I used an Iterator to make sure that only the essential state is kept in memory at any time and only when it's actually used.
I have a function called collatz and I need to find how many times it calls itself, but I'm not allowed to use any vars.
The function works perfectly with vars but i have to use vals.
In case sinanspd's answer does not answer your question, here is some example code.
Let us say your function collatz has a signature as follows:
def collatz(input: Type1): Type2 = ???
The way to count how many times it is called is to either modify collatz itself, or else to use some wrapper function.
def counter(oldCount: Int, fun: Type1 => Type2, input: Type1): (Int, Type2) = {
val output = fun(input)
(oldCount + 1, output)
}
The first time you call counter, call it with oldCount set to 0. Every time you call counter, pass in the old version of count. The first value of your output tuple will be the new count.
In the following example:
def maybeTwice2(b: Boolean, i: => Int) = {
lazy val j = i
if (b) j+j else 0
}
Why is hi not printed twice when I call it like:
maybeTwice2(true, { println("hi"); 1+41 })
This example is actually from the book "Functional Programming in Scala" and the reason given as why "hi" not getting printed twice is not convincing enough for me. So just thought of asking this here!
So i is a function that gives an integer right? When you call the method you pass b as true and the if statement's first branch is executed.
What happens is that j is set to i and the first time it is later used in a computation it executes the function, printing "hi" and caching the resulting value 1 + 41 = 42. The second time it is used the resulting value is already computed and hence the function returns 84, without needing to compute the function twice because of the lazy val j.
This SO answer explores how a lazy val is internally implemented. In j + j, j is a lazy val, which amounts to a function which executes the code you provide for the definition of the lazy val, returns an integer and caches it for further calls. So it prints hi and returns 1+41 = 42. Then the second j gets evaluated, and calls the same function. Except this time, instead of running your code, it fetches the value (42) from the cache. The two integers are then added (returning 84).
There is some misunderstanding between me and Scala
0 or 1?
object Fun extends App {
def foo(list:List[Int], count:Int = 0): Int = {
if (list.isEmpty) { // when this is true
return 1 // and we are about to return 1, the code goes to the next line
}
foo(list.tail, count + 1) // I know I do not use "return here" ...
count
}
val result = foo( List(1,2,3) )
println ( result ) // 0
}
Why does it print 0?
Why does recursion work even without "return"
(when it is in the middle of function, but not in the end)?
Why doesn't it return 1? when I use "return" explicitly?
--- EDIT:
It will work if I use return here "return foo(list.tail, count + 1)'.
Bu it does NOT explain (for me) why "return 1" does not work above.
If you read my full explanation below then the answers to your three questions should all be clear, but here's a short, explicit summary for everyone's convenience:
Why does it print 0? This is because the method call was returning count, which had a default value of 0—so it returns 0 and you print 0. If you called it with count=5 then it would print 5 instead. (See the example using println below.)
Why does recursion work even without "return" (when it is in the middle of function, but not in the end)? You're making a recursive call, so the recursion happens, but you weren't returning the result of the recursive call.
Why doesn't it return 1? when I use "return" explicitly? It does, but only in the case when list is empty. If list is non-empty then it returns count instead. (Again, see the example using println below.)
Here's a quote from Programming in Scala by Odersky (the first edition is available online):
The recommended style for methods is in fact to avoid having explicit, and especially multiple, return statements. Instead, think of each method as an expression that yields one value, which is returned. This philosophy will encourage you to make methods quite small, to factor larger methods into multiple smaller ones. On the other hand, design choices depend on the design context, and Scala makes it easy to write methods that have multiple, explicit returns if that's what you desire. [link]
In Scala you very rarely use the return keyword, but instead take advantage that everything in an expression to propagate the return value back up to the top-level expression of the method, and that result is then used as the return value. You can think of return as something more like break or goto, which disrupts the normal control flow and might make your code harder to reason about.
Scala doesn't have statements like Java, but instead everything is an expression, meaning that everything returns a value. That's one of the reasons why Scala has Unit instead of void—because even things that would have been void in Java need to return a value in Scala. Here are a few examples about how expressions work that are relevant to your code:
Things that are expressions in Java act the same in Scala. That means the result of 1+1 is 2, and the result of x.y() is the return value of the method call.
Java has if statements, but Scala has if expressions. This means that the Scala if/else construct acts more like the Java ternary operator. Therefore, if (x) y else z is equivalent to x ? y : z in Java. A lone if like you used is the same as if (x) y else Unit.
A code block in Java is a statement made up of a group of statements, but in Scala it's an expression made up of a group of expressions. A code block's result is the result of the last expression in the block. Therefore, the result of { o.a(); o.b(); o.c() } is whatever o.c() returned. You can make similar constructs with the comma operator in C/C++: (o.a(), o.b(), o.c()). Java doesn't really have anything like this.
The return keyword breaks the normal control flow in an expression, causing the current method to immediately return the given value. You can think of it kind of like throwing an exception, both because it's an exception to the normal control flow, and because (like the throw keyword) the resulting expression has type Nothing. The Nothing type is used to indicate an expression that never returns a value, and thus can essentially be ignored during type inference. Here's simple example showing that return has the result type of Nothing:
def f(x: Int): Int = {
val nothing: Nothing = { return x }
throw new RuntimeException("Can't reach here.")
}
Based on all that, we can look at your method and see what's going on:
def foo(list:List[Int], count:Int = 0): Int = {
// This block (started by the curly brace on the previous line
// is the top-level expression of this method, therefore its result
// will be used as the result/return value of this method.
if (list.isEmpty) {
return 1 // explicit return (yuck)
}
foo(list.tail, count + 1) // recursive call
count // last statement in block is the result
}
Now you should be able to see that count is being used as the result of your method, except in the case when you break the normal control flow by using return. You can see that the return is working because foo(List(), 5) returns 1. In contrast, foo(List(0), 5) returns 5 because it's using the result of the block, count, as the return value. You can see this clearly if you try it:
println(foo(List())) // prints 1 because list is empty
println(foo(List(), 5)) // prints 1 because list is empty
println(foo(List(0))) // prints 0 because count is 0 (default)
println(foo(List(0), 5)) // prints 5 because count is 5
You should restructure your method so that the value that the body is an expression, and the return value is just the result of that expression. It looks like you're trying to write a method that returns the number of items in the list. If that's the case, this is how I'd change it:
def foo(list:List[Int], count:Int = 0): Int = {
if (list.isEmpty) count
else foo(list.tail, count + 1)
}
When written this way, in the base case (list is empty) it returns the current item count, otherwise it returns the result of the recursive call on the list's tail with count+1.
If you really want it to always return 1 you can change it to if (list.isEmpty) 1 instead, and it will always return 1 because the base case will always return 1.
You're returning the value of count from the first call (that is, 0), not the value from the recursive call of foo.
To be more precise, in you code, you don't use the returned value of the recursive call to foo.
Here is how you can fix it:
def foo(list:List[Int], count:Int = 0): Int = {
if (list.isEmpty) {
1
} else {
foo(list.tail, count + 1)
}
}
This way, you get 1.
By the way, don't use return. It doesn't do always what you would expect.
In Scala, a function return implicitly the last value. You don't need to explicitly write return.
Your return works, just not the way you expect because you're ignoring its value. If you were to pass an empty list, you'd get 1 as you expect.
Because you're not passing an empty list, your original code works like this:
foo called with List of 3 elements and count 0 (call this recursion 1)
list is not empty, so we don't get into the block with return
we recursively enter foo, now with 2 elements and count 1 (recursion level 2)
list is not empty, so we don't get into the block with return
we recursively enter foo, now with 1 element and count 2 (recursion level 3)
list is not empty, so we don't get into the block with return
we now enter foo with no elements and count 3 (recursion level 4)
we enter the block with return and return 1
we're back to recursion level 3. The result of the call to foo from which we just came back in neither assigned nor returned, so it's ignored. We proceed to the next line and return count, which is the same value that was passed in, 2
the same thing happens on recursion levels 2 and 1 - we ignore the return value of foo and instead return the original count
the value of count on the recursion level 1 was 0, which is the end result
The fact that you do not have a return in front of foo(list.tail, count + 1) means that, after you return from the recursion, execution is falling through and returning count. Since 0 is passed as a default value for count, once you return from all of the recursed calls, your function is returning the original value of count.
You can see this happening if you add the following println to your code:
def foo(list:List[Int], count:Int = 0): Int = {
if (list.isEmpty) { // when this is true
return 1 // and we are about to return 1, the code goes to the next line
}
foo(list.tail, count + 1) // I know I do not use "return here" ...
println ("returned from foo " + count)
count
}
To fix this you should add a return in front of foo(list.tail.....).
you return count in your program which is a constant and is initialized with 0, so that is what you are returning at the top level of your recursion.
I have the following code, but I can't get it to work. As soon as I place a while loop inside the case, it's returning a unit, no matter what I change within the brackets.
case While(c, body) =>
while (true) {
eval(Num(1))
}
}
How can I make this while loop return a non-Unit type?
I tried adding brackets around my while condition, but still it doesn't do what it's supposed to.
Any pointers?
Update
A little more background information since I didn't really explain what the code should do, which seems to be handy if I want to receive some help;
I have defined a eval(exp : Exp). This will evaluate a function.
Exp is an abstract class. Extended by several classes like Plus, Minus (few more basic operations) and a IfThenElse(cond : Exp, then : Exp, else : Exp). Last but not least, there's the While(cond: Exp, body: Exp).
Example of how it should be used;
eval(Plus(Num(1),Num(4)) would result in NumValue(5). (Evaluation of Num(v : Value) results in NumValue(v). NumValue extends Value, which is another abstract class).
eval(While(Lt(Num(1),Var("n")), Plus(Num(1), Var("n"))))
Lt(a : Exp, b : Exp) returns NumValue(1) if a < b.
It's probably clear from the other answer that Scala while loops always return Unit. What's nice about Scala is that if it doesn't do what you want, you can always extend it.
Here is the definition of a while-like construct that returns the result of the last iteration (it will throw an exception if the loop is never entered):
def whiley[T](cond : =>Boolean)(body : =>T) : T = {
#scala.annotation.tailrec
def loop(previous : T) : T = if(cond) loop(body) else previous
if(cond) loop(body) else throw new Exception("Loop must be entered at least once.")
}
...and you can then use it as a while. (In fact, the #tailrec annotation will make it compile into the exact same thing as a while loop.)
var x = 10
val atExit = whiley(x > 0) {
val squared = x * x
println(x)
x -= 1
squared
}
println("The last time x was printed, its square was : " + atExit)
(Note that I'm not claiming the construct is useful.)
Which iteration would you expect this loop to return? If you want a Seq of the results of all iterations, use a for expression (also called for comprehension). If you want just the last one, create a var outside the loop, set its value on each iteration, and return that var after the loop. (Also look into other looping constructs that are implemented as functions on different types of collections, like foldLeft and foldRight, which have their own interesting behaviors as far as return value goes.) The Scala while loop returns Unit because there's no sensible one size fits all answer to this question.
(By the way, there's no way for the compiler to know this, but the loop you wrote will never return. If the compiler could theoretically be smart enough to figure out that while(true) never terminates, then the expected return type would be Nothing.)
The only purpose of a while loop is to execute a side-effect. Or put another way, it will always evaluate to Unit.
If you want something meaningful back, why don't you consider using an if-else-expression or a for-expression?
As everyone else and their mothers said, while loops do not return values in Scala. What no one seems to have mentioned is that there's a reason for that: performance.
Returning a value has an impact on performance, so the compiler would have to be smart about when you do need that return value, and when you don't. There are cases where that can be trivially done, but there are complex cases as well. The compiler would have to be smarter, which means it would be slower and more complex. The cost was deemed not worth the benefit.
Now, there are two looping constructs in Scala (all the others are based on these two): while loops and recursion. Scala can optimize tail recursion, and the result is often faster than while loops. Or, otherwise, you can use while loops and get the result back through side effects.