I'm new to Scala and created a infinite Stream of int and want to map() for each int i, the computed value x, which results from method m(i) = x. The point is, that I want the stream to actually stop when x > 0, AND I need the i which was used to compute the HIGHEST x of the list. However I'm struggling with this task, since I get an UnsupportedOperationException empty.max...
I tried using the code below, throwing the described exception. I also tried to create tuple out of (i,m(i)), but instead of actually applying m(i), the method itself got mapped.
This is method m:
def m(t: Int): Double = {
//Some calculation...
}
Ant I tried these options:
Stream.from(1).map(m(_)).takeWhile(_ > 0).toList.max
Stream.from(1).map((_,m(_))).takeWhile(_._2.apply(1) > 0).maxBy(_._2)
The second one shows this:
missing parameter type for expanded function ((x$2: <error>) => m(x$2)) Stream.from(1).map((_,m(_))).takeWhile(_._2.apply(1) > 0).maxBy(_._2)
How can I resolve this as short as possible? Thank you very much guys!
.map((_,m(_)))
This means i => (i, j => m(j)), not i => (i, m(i)) which you want. So just write map(i => (i, m(i))) (or as Luis suggests, i -> m(i)) explicitly. I'd personally prefer braces for this lambda: map { i => (i, m(i)) }.
Related
I have a case class with a parameter a which is a list of int tuple. I want to iterate over a and define operations on a.
I have tried the following:
case class XType (a: List[(Int, Int)]) {
for (x <- a) {
assert(x._2 >= 0)
}
def op(): XType = {
for ( x <- XType(a))
yield (x._1, x._2)
}
}
However, I am getting the error:
"Value map is not a member of XType."
How can I access the integers of tuples and define operations on them?
You're running into an issue with for comprehensions, which are really another way of expressing things like foreach and map (and flatMap and withFilter/filter). See here and here for more explanation.
Your first for comprehension (the one with asserts) is equivalent to
a.foreach(x => assert(x._2 >= 0))
a is a List, x is an (Int, Int), everything's good.
However, the second on (in op) translates to
XType(a).map(x => x)
which doesn't make sense--XType doesn't know what to do with map, like the error said.
An instance of XType refers to its a as simply a (or this.a), so a.map(x => x) would be just fine in op (and then turn the result into a new XType).
As a general rule, for comprehensions are handy for nested maps (or flatMaps or whatever), rather than as a 1-1 equivalent for for loops in other languages--just use map instead.
You can access to the tuple list by:
def op(): XType = {
XType(a.map(...))
}
lazy val minkowskiHOF: (List[Double], List[Double], Int) => Double = (lstx, listy, p) => {
var add = lstx.zip(listy)
.map(pair => pair._1 - pair._2)
.foldLeft(0.0)((acumulator,element) => { Math.pow(Math.abs(element), p) + acumulator })
Math.pow(add, 1.0 / p)
}
cgt: I have a cup. How do I drive a nail through it?
everyone: For what purpose? How should the new cup be different?
cgt: It should be exactly the same cup. I want to learn how to use nails.
Dmytro Mitin: Glue a nail to the side of your cup. Whenever you use the cup ignore the nail.
cgt: Thank you Dmytro. This is what i wanted.
So you want to make a higher order function. What is a higher order function? It's a function that receives a function as a passed parameter and/or returns a function as its result. There are a number of ways you might turn minkowski() into a higher order function.
One option is to make the Math.pow() part a passed parameter.
val minkowskiHOF:(List[Double], List[Double], Int, (Double,Double)=>Double) => Double =
(lstx, listy, p, op) => {
val add = lstx.zip(listy)
.map(pair => Math.abs(pair._1 - pair._2))
.foldLeft(0.0)(_ + op(_, p))
op(add, 1.0 / p)
}
Now when you call minkowskiHOF() with Math.pow as the 4th argument you'll get the Minkowski distance, but you can also pass some other (Double,Double)=>Double function instead of Math.pow and get a different calculation. So now minkowskiHOF() isn't a very good name for your function.
Alternatively, you could return a function.
val minkowskiHOF: (List[Double], Int) => List[Double] => Double =
(listy, p) => lstx => {
val add = lstx.zip(listy)
.map(pair => Math.abs(pair._1 - pair._2))
.foldLeft(0.0)(_ + Math.pow(_, p))
Math.pow(add, 1.0 / p)
}
This minkowskiHOF() function does most of the work to calculate a Minkowski distance, but it returns a function that takes a single List[Double] to complete the calculation. So, again, minkowskiHOF() is perhaps not a completely accurate name.
Conclusion: Higher order functions can be quite a handy tool to have at your disposal but, like a hammer and nail, it's not always appropriate for every job that comes along.
I am working on the Coursera's Scala tutorials. One of the exercises asks to implement a map function to sets type that are defined as follows:
type Set = Int => Boolean. There was a stub for the function:
/**
* Returns a set transformed by applying `f` to each element of `s`.
*/
def map(s: Set, f: Int => Int): Set = ???
I thought that one can check if an element is in s, by doing the following:
(x: Int) => s(x). Which I am thinking should be equivalent to whatever the definition of a set is. Thus, if we want to apply transformation on the set, we can do:
(x: Int) => s(f(x)). And so the definition of function is:
def map(s: Set, f: Int => Int): Set = s(f(x)). But this gives me some weird set if I try it on:
def map(s: Set, f: Int => Int): Set = (x: Int) => s(f(x))
def toStringH(s: Set): String = {
val xs = for (i <- -bound to bound if contains(s, i)) yield i
xs.mkString("{", ",", "}")
}
def printSet(s: Set) { println(toStringH(s)) }
val squaredSet = map((x: Int) => (x> -3 & x<3), (x:Int) => (x+1))
printSet(squaredSet)
So I am wondering where I went wrong. Thanks.
I expect that you mean the progfun1 course by Martin Odersky and its Week 2 task. I believe that generally there is no solution for this problem (it requires finding a reverse function for a given function which I doubt is really possible) and the course authors know about that. Thus they added an additional restriction that you probably missed (I highlighted the important part):
Note that there is no direct way to find which elements are in a set. contains only allows to know whether a given element is included. Thus, if we wish to do something to all elements of a set, then we have to iterate over all integers, testing each time whether it is included in the set, and if so, to do something with it. Here, we consider that an integer x has the property -1000 <= x <= 1000 in order to limit the search space.
Although it is a comment for the forall task it is in the same section and just a few paragraphs above the map task.
I'm trying to sum the values of the pairs that have the same character, but when printing, i get List((),())
here's my code
var lstA = List(("a",1),("b",2))
var lstB = List(("a",3), ("b",4))
val k = lstA.map(a => lstB.foreach(b => {
if(b._1 == a._1) (a._1, a._2+b._2) else a
}))
println(k)
of course there are better ways to do this, but I just want to know why this isn't working.
when debugging and evaluating the line if(b._1 == a._1) (a._1, a._2+b._2) else a i get the values of pairs as expected however when printing the list k is empty
The short and not entirely accurate answer is because foreach doesn't return anything. Actually, though, it does return something. Here is the signature:
def foreach[U](f: (A) ⇒ U): Unit
It returns a Unit type, which is used as a signal that the function has side-effects. From the documentation, the f parameter is:
the function that is applied for its side-effect to every element. The
result of function f is discarded.
So the function is expected to have a side effect. This could be something like println.
I have a recursive function that takes a Map as single parameter. It then adds new entries to that Map and calls itself with this larger Map. Please ignore the return values for now. The function isn't finished yet. Here's the code:
def breadthFirstHelper( found: Map[AIS_State,(Option[AIS_State], Int)] ): List[AIS_State] = {
val extension =
for(
(s, v) <- found;
next <- this.expand(s) if (! (found contains next) )
) yield (next -> (Some(s), 0))
if ( extension.exists( (s -> (p,c)) => this.isGoal( s ) ) )
List(this.getStart)
else
breadthFirstHelper( found ++ extension )
}
In extension are the new entries that shall get added to the map. Note that the for-statement generates an iterable, not a map. But those entries shall later get added to the original map for the recursive call. In the break condition, I need to test whether a certain value has been generated inside extension. I try to do this by using the exists method on extension. But the syntax for extracting values from the map entries (the stuff following the yield) doesn't work.
Questions:
How do I get my break condition (the boolean statement to the if) to work?
Is it a good idea to do recursive work on a immutable Map like this? Is this good functional style?
When using a pattern-match (e.g. against a Tuple2) in a function, you need to use braces {} and the case statement.
if (extension.exists { case (s,_) => isGoal(s) } )
The above also uses the fact that it is more clear when matching to use the wildcard _ for any allowable value (which you subsequently do not care about). The case xyz gets compiled into a PartialFunction which in turn extends from Function1 and hence can be used as an argument to the exists method.
As for the style, I am not functional programming expert but this seems like it will be compiled into a iterative form (i.e. it's tail-recursive) by scalac. There's nothing which says "recursion with Maps is bad" so why not?
Note that -> is a method on Any (via implicit conversion) which creates a Tuple2 - it is not a case class like :: or ! and hence cannot be used in a case pattern match statement. This is because:
val l: List[String] = Nil
l match {
case x :: xs =>
}
Is really shorthand/sugar for
case ::(x, xs) =>
Similarly a ! b is equivalent to !(a, b). Of course, you may have written your own case class ->...
Note2: as Daniel says below, you cannot in any case use a pattern-match in a function definition; so while the above partial function is valid, the following function is not:
(x :: xs) =>
This is a bit convoluted for me to follow, whatever Oxbow Lakes might think.
I'd like first to clarify one point: there is no break condition in for-comprehensions. They are not loops like C's (or Java's) for.
What an if in a for-comprehension means is a guard. For instance, let's say I do this:
for {i <- 1 to 10
j <- 1 to 10
if i != j
} yield (i, j)
The loop isn't "stopped" when the condition is false. It simply skips the iterations for which that condition is false, and proceed with the true ones. Here is another example:
for {i <- 1 to 10
j <- 1 to 10
if i % 2 != 0
} yield (i, j)
You said you don't have side-effects, so I can skip a whole chapter about side effects and guards on for-comprehensions. On the other hand, reading a blog post I made recently on Strict Ranges is not a bad idea.
So... give up on break conditions. They can be made to work, but they are not functional. Try to rephrase the problem in a more functional way, and the need for a break condition will be replaced by something else.
Next, Oxbow is correct in that (s -> (p,c) => isn't allowed because there is no extractor defined on an object called ->, but, alas, even (a :: b) => would not be allowed, because there is no pattern matching going on in functional literal parameter declaration. You must simply state the parameters on the left side of =>, without doing any kind of decomposition. You may, however, do this:
if ( extension.exists( t => val (s, (p,c)) = t; this.isGoal( s ) ) )
Note that I replaced -> with ,. This works because a -> b is a syntactic sugar for (a, b), which is, itself, a syntactic sugar for Tuple2(a, b). As you don't use neither p nor c, this works too:
if ( extension.exists( t => val (s, _) = t; this.isGoal( s ) ) )
Finally, your recursive code is perfectly fine, though probably not optimized for tail-recursion. For that, you either make your method final, or you make the recursive function private to the method. Like this:
final def breadthFirstHelper
or
def breadthFirstHelper(...) {
def myRecursiveBreadthFirstHelper(...) { ... }
myRecursiveBreadthFirstHelper(...)
}
On Scala 2.8 there is an annotation called #TailRec which will tell you if the function can be made tail recursive or not. And, in fact, it seems there will be a flag to display warnings about functions that could be made tail-recursive if slightly changed, such as above.
EDIT
Regarding Oxbow's solution using case, that's a function or partial function literal. It's type will depend on what the inference requires. In that case, because that's that exists takes, a function. However, one must be careful to ensure that there will always be a match, otherwise you get an exception. For example:
scala> List(1, 'c') exists { case _: Int => true }
res0: Boolean = true
scala> List(1, 'c') exists { case _: String => true }
scala.MatchError: 1
at $anonfun$1.apply(<console>:5)
... (stack trace elided)
scala> List(1, 'c') exists { case _: String => true; case _ => false }
res3: Boolean = false
scala> ({ case _: Int => true } : PartialFunction[AnyRef,Boolean])
res5: PartialFunction[AnyRef,Boolean] = <function1>
scala> ({ case _: Int => true } : Function1[Int, Boolean])
res6: (Int) => Boolean = <function1>
EDIT 2
The solution Oxbow proposes does use pattern matching, because it is based on function literals using case statements, which do use pattern matching. When I said it was not possible, I was speaking of the syntax x => s.