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.
Related
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)) }.
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 have superficially read a couple of blog articles/Wikipedia about continuation-passing style. My high-level goal is to find a systematic technique to make any recursive function (or, if there are restrictions, being aware of them) tail-recursive. However, I have trouble articulating my thoughts and I'm not sure if what my attempts of it make any sense.
For the purpose of the example, I'll propose a simple problem. The goal is, given a sorted list of unique characters, to output all possible words made out of these characters in alphabetical order. For example, sol("op".toList, 3) should return ooo,oop,opo,opp,poo,pop,ppo,ppp.
My recursive solution is the following:
def sol(chars: List[Char], n: Int) = {
def recSol(n: Int): List[List[Char]] = (chars, n) match {
case (_ , 0) => List(Nil)
case (Nil, _) => Nil
case (_ , _) =>
val tail = recSol(n - 1)
chars.map(ch => tail.map(ch :: _)).fold(Nil)(_ ::: _)
}
recSol(n).map(_.mkString).mkString(",")
}
I did try to rewrite this by adding a function as a parameter but I did not manage to make something I was convinced to be tail-recursive. I prefer not including my attempt(s) in the question as I'm ashamed of their naiveness, so please excuse me for this.
Therefore the question is basically: how would the function above be written in CPS ?
Try that:
import scala.annotation.tailrec
def sol(chars: List[Char], n: Int) = {
#tailrec
def recSol(n: Int)(cont: (List[List[Char]]) => List[List[Char]]): List[List[Char]] = (chars, n) match {
case (_ , 0) => cont(List(Nil))
case (Nil, _) => cont(Nil)
case (_ , _) =>
recSol(n-1){ tail =>
cont(chars.map(ch => tail.map(ch :: _)).fold(Nil)(_ ::: _))
}
}
recSol(n)(identity).map(_.mkString).mkString(",")
}
The first order of business in performing the CPS transform is deciding on a representation for continuations. We can think of continuations as a suspended computation with a "hole". When the hole is filled in with a value, the remainder of the computation can be computed. So functions are a natural choice for representing continuations, at least for toy examples:
type Cont[Hole,Result] = Hole => Result
Here Hole represents the type of the hole that needs to be filled in, and Result represents the type of value the computation ultimately computes.
Now that we have a way to represent continuations, we can worry about the CPS transform itself. Basically, this involves the following steps:
The transformation is applied recursively to an expression, stopping at "trivial" expressions / function calls. In this context, "trivial" includes functions defined by Scala (since they are not CPS-transformed, and thus do not have a continuation parameter).
We need to add a parameter of type Cont[Return,Result] to each function, where Return is the return type of the untransformed function and Result is the type of the ultimate result of the computation as a whole. This new parameter represents the current continuation. The return type for the transformed function is also changed to Result.
Every function call needs to be transformed to accommodate the new continuation parameter. Everything after the call needs to be put into a continuation function, which is then added to the parameter list.
For example, a function:
def f(x : Int) : Int = x + 1
becomes:
def fCps[Result](x : Int)(k : Cont[Int,Result]) : Result = k(x + 1)
and
def g(x : Int) : Int = 2 * f(x)
becomes:
def gCps[Result](x : Int)(k : Cont[Int,Result]) : Result = {
fCps(x)(y => k(2 * y))
}
Now gCps(5) returns (via currying) a function that represents a partial computation. We can extract the value from this partial computation and use it by supplying a continuation function. For example, we can use the identity function to extract the value unchanged:
gCps(5)(x => x)
// 12
Or, we can print it by using println instead:
gCps(5)(println)
// prints 12
Applying this to your code, we obtain:
def solCps[Result](chars : List[Char], n : Int)(k : Cont[String, Result]) : Result = {
#scala.annotation.tailrec
def recSol[Result](n : Int)(k : Cont[List[List[Char]], Result]) : Result = (chars, n) match {
case (_ , 0) => k(List(Nil))
case (Nil, _) => k(Nil)
case (_ , _) =>
recSol(n - 1)(tail =>
k(chars.map(ch => tail.map(ch :: _)).fold(Nil)(_ ::: _)))
}
recSol(n)(result =>
k(result.map(_.mkString).mkString(",")))
}
As you can see, although recSol is now tail-recursive, it comes with the cost of building a more complex continuation at each iteration. So all we've really done is trade space on the JVM's control stack for space on the heap -- the CPS transform does not magically reduce the space complexity of an algorithm.
Also, recSol is only tail-recursive because the recursive call to recSol happens to be the first (non-trivial) expression recSol performs. In general, though, recursive calls would be take place inside a continuation. In the case where there is one recursive call, we can work around that by transforming only calls to the recursive function to CPS. Even so, in general, we would still just be trading stack space for heap space.
I find myself constantly doing things like the following:
val adjustedActions = actions.scanLeft((1.0, null: CorpAction)){
case ((runningSplitAdj, _), action) => action match {
case Dividend(date, amount) =>
(runningSplitAdj, Dividend(date, amount * runningSplitAdj))
case s # Split(date, sharesForOne) =>
((runningSplitAdj * sharesForOne), s)
}
}
.drop(1).map(_._2)
Where I need to accumulate the runningSplitAdj, in this case, in order to correct the dividends in the actions list. Here, I use scan to maintain the state that I need in order to correct the actions, but in the end, I only need the actions. Hence, I need to use null for the initial action in the state, but in the end, drop that item and map away all the states.
Is there a more elegant way of structuring these? In the context of RxScala Observables, I actually made a new operator to do this (after some help from the RxJava mailing list):
implicit class ScanMappingObs[X](val obs: Observable[X]) extends AnyVal {
def scanMap[S,Y](f: (X,S) => (Y,S), s0: S): Observable[Y] = {
val y0: Y = null.asInstanceOf[Y]
// drop(1) because scan also emits initial state
obs.scan((y0, s0)){case ((y, s), x) => f(x, s)}.drop(1).map(_._1)
}
}
However, now I find myself doing it to Lists and Vectors too, so I wonder if there is something more general I can do?
The combinator you're describing (or at least something very similar) is often called mapAccum. Take the following simplified use of scanLeft:
val xs = (1 to 10).toList
val result1 = xs.scanLeft((1, 0.0)) {
case ((acc, _), i) => (acc + i, i.toDouble / acc)
}.tail.map(_._2)
This is equivalent to the following (which uses Scalaz's implementation of mapAccumLeft):
xs.mapAccumLeft[Double, Int](1, {
case (acc, i) => (acc + i, i.toDouble / acc)
})._2
mapAccumLeft returns a pair of the final state and a sequence of the results at each step, but it doesn't require you to specify a spurious initial result (that will just be ignored and then dropped), and you don't have to map over the entire collection to get rid of the state—you just take the second member of the pair.
Unfortunately mapAccumLeft isn't available in the standard library, but if you're looking for a name or for ideas about implementation, this is a place to start.
My assignment is to write a custom repeat control structure that can be used like this:
var i = 0
repeat {
i = i + 1
}(i > 5)
I currently have the following code for that:
def repeat(f: => Unit): ((=> Boolean) => Unit) = {
(x) => {
while (x) f
}
}
When running this, it seems f (i = i + 1) is never executed.
I have to be honest, I'm not entirely sure what the current type of x is. It's clearly not correct, but I don't have enough knowledge to know where to go from here.
I used to have this:
def repeat(f: => Unit): ((=> Boolean) => Void) = {
(x: (=> Boolean)) => {
while (x) f
}
}
Although this is apparently incorrect Scala, I think it demonstrates my intent better.
I'm sorry if my question is a bit broad/demonstrates effortlessness, but the concept of by-name parameters is very new to me and not explained in my book (Programming in Scala) beyond the basics.
You should also be aware that Scala supports multiple parameter lists. So you could
def compare(a: Int, b: Int)(p: (Int,Int) => Boolean) = p(a,b)
and then write
compare(5,2)(_ > _)
This type of strategy will simplify your logic.
Also, you have your comparison backwards. i starts out at 0 and your loop condition is i > 5, which it is not.
A few extra notes: => X means "compute an X each time one is needed", so ((=> Boolean) => Unit) takes something that will compute a Boolean as needed (and i > 5 can do that, if the check is performed each time, which it will be). (=> Boolean) => Unit means a function that takes as input something that produces Booleans and gives no output. (Well, strictly speaking, Unit type is an output, namely (), which is done for consistency. But it serves the same role as void.)