This sum function working fine, but I am having trouble to write the version that swap x and f:(Int=>Int)
Works fine:
def sum(f:Int=>Int):Int=>Int = {
def ret_fun(x:Int):Int =
if (x==1) f(1)
else f(x)+ret_fun(x-1)
ret_fun
}
Did not work:
def sum(x:Int):Int=>Int = {
def ret_fun(f:Int=>Int):Int =
if (x==1) f(1)
else f(x)+ret_fun(x-1)
ret_fun
}
Did anyone know how to solve this?
First of all, the return type of the second sum should be (Int => Int) => Int, because it's supposed to return a function that accepts an Int => Int function, not an Int number.
Unfortunately you can't iterate over x using recursion of ret_fun, because x is not its argument. However you could use an indirect recursion of sum
def sum(x: Int): (Int => Int) => Int = {
def ret_fun(f: Int => Int): Int =
if (x == 1) f(1)
else f(x) + sum(x - 1)(f)
ret_fun
}
I imagine it may defeat the purpose of your exercise, because it's essentially the same as saying:
def sum(x: Int)(f: Int => Int): Int =
if (x == 1) f(1)
else f(x) + sum(x - 1)(f)
If your idea was to implement ret_fun using direct recursion and achieve the full analogy with the first example, let me comment on why it's problematic.
The reason is that the stop condition x == 1 is defined in terms of x and not in terms of f(x), so it's hard to determine which invocation should recurse and which shouldn't without changing the logic of the algorithm
def sum(x: Int): (Int => Int) => Int = {
def ret_fun(f: Int => Int): Int =
if (???) f(1)
else f(x) + ret_fun(x => f(x - 1))
ret_fun
}
We can, for instance, try if (f(x) == 0) 0, but as I said it will pretty much break the algorithm and will calculate f(x) + f(x - 1) + ... + 0 instead of f(x) + f(x - 1) + ... + f(1)
If you are fine with your second function depending on the first one, you just define it as this:
def sum(x: Int): (Int=>Int) => Int = f => sum(f)(x)
Otherwise you can do this:
def sum(x: Int): (Int => Int) => Int = f => f(x) + (if (x == 1) 0 else sum(x - 1)(f))
There's no need to define ret_fun separately.
If you absolutely want ret_fun, though, you can add x as a parameter to ret_fun, like this:
def sum(x: Int): (Int => Int) => Int = {
def ret_fun(x: Int)(f: Int => Int): Int =
if (x == 1) f(1)
else f(x) + ret_fun(x - 1)(f)
ret_fun(x)
}
If you want the function to be the first parameter, then you can do this, which is basically the same:
def sum(x: Int): (Int => Int) => Int = {
def ret_fun(f: Int => Int)(x: Int): Int =
if (x == 1) f(1)
else f(x) + ret_fun(f)(x - 1)
ret_fun(_)(x)
}
Related
I want to create a function that would return a function which is n-times composed function of f over parameter x, i.e. f(f(f ... f(x) ...)).
Here is my code:
def repeated(f: Int => Int, n: Int) = {
var tek: Int => Int = f
for (i <- 0 to n) {
tek = x => f(tek(x))
}
tek
}
I know this is not right way to do this in Scala, I just want to find out what's happening behind the scenes.
Calling it like repeated(x => x + 1, 5)(1) would result in stack overflow.
What I have notice in debugger is that line inside for loop is executed after repeated is finished. It seems like lazy initiation, maybe body of for loop is a lambda passed by name?
In pure FP:
def repeated[A](f: A => A, n: Int): A => A =
(0 until n).foldLeft(identity[A] _)((ff, _) => ff.andThen(f))
(also works if n=0 - becomes identity)
Or, if you don't like iterating over a Range (which I think wouldn't be much less performant than alternatives), manual tail recursion:
def repeated[A](f: A => A, n: Int): A => A = {
#tailrec def aux(acc: A => A, n: Int): A => A = {
if(n > 0) aux(acc.andThen(f), n - 1)
else acc
}
aux(identity, n)
}
EDIT: there's also the Stream version, as #Karl Bielefeldt mentioned. Should be about about as performant, but of course the best way to choose is to benchmark with your usecase:
def repeated[A](f: A => A, n: Int): A => A =
Stream.iterate(identity[A] _)(_.andThen(f)).apply(n)
EDIT 2: if you have Cats:
def repeated[A](f: A => A, n: Int): A => A =
MonoidK[Endo].algebra[A].combineN(f, n)
Your x => f(tek(x)) is closing over the variable tek. Once the inner for-loop runs at least once, your tek becomes self-referential, because tek = x => f(tek(x)) calls itself, which causes unbounded recursion and StackOverflowError.
If you wanted to do it with a for-loop, you could introduce a local immutable helper variable to break the recursion:
def repeated(f: Int => Int, n: Int) = {
var tek: Int => Int = identity
for (i <- 1 to n) {
val g = tek
tek = x => f(g(x))
}
tek
}
Note that you had at least two applications of f too much in your code:
You didn't start with identity for n = 0
You iterated from 0 to n, that is, (n + 1) times.
A much simpler solution would have been:
def repeated[A](f: A => A, n: Int): A => A = { (a0: A) =>
var res: A = a0
for (i <- 1 to n) {
res = f(res)
}
res
}
I've been trying to finish this scala code that uses a list to output the summation of all positive integers in the list.. I got it working except for having it only work for positive numbers. but i cant get it to only output the positive numbers. I have 2 versions that ive been trying to get to work, i thought maybe it would be easier wit cases, but i ended up running into the same problem. I've been trying if statements with xs<0 , but those don't work, and i cant get the filter to work with the fold. any suggestions with how to handle this?
def sum(xs: List[Int]): Int = {
xs.filter((x: Int) => x > 0)
xs.foldLeft(0) { _ + _ }
}
def sum2(xs: List[Int]): Int = xs match {
case Nil => 0
case y :: ys => y + sum(ys)
}
xs is an immutable List[Int], which means you are not just modifying the same xs value and returning it.
def sum(xs: List[Int]): Int = {
xs.filter((x: Int) => x > 0) // This is a pure expression and effectively does nothing
xs.foldLeft(0) { _ + _ } // This is the value that is returned, modifying the *original* `xs` parameter
}
What you need to do is chain the functions together, to operate on the same value.
def sum(xs: List[Int]): Int = {
xs.filter((x: Int) => x > 0).foldLeft(0) { _ + _ }
}
The type check isn't necessary here, so it can be shorted:
def sum(xs: List[Int]): Int = xs.filter(_ > 0).foldLeft(0)(_ + _)
There is also a sum method on List that does the same thing as your foldLeft.
def sum(xs: List[Int]): Int = xs.filter(_ > 0).sum
List(1, -2, 3).filter(_ > 0).sum // 4
or in a single pass
List(1, -2, 3).foldLeft(0){(acc, i) => if (i > 0) acc + i else acc } //4
Your 1st version is almost right. Remember that filter method doesn't have side effects, so just try this small change:
def sum(xs: List[Int]): Int = {
xs.filter((x: Int) => x > 0).foldLeft(0) { _ + _ }
}
Or simpler version:
def sum(xs: List[Int]): Int = {
xs.filter(_ > 0).sum
}
i ended up trying this , which i think is right. based on the suggestions
val f = xs.filter((x: Int) => x > 0)
f.foldLeft(0) { _ + _ }
I don't have very clear the partial application of functions in Scala...
I will do an example:
def myOperation(x: Int)(y: Int): Int = {
val complexVal = complexCalc(x)
println("complexVal calculated")
complexVal + y
}
def complexCalc(x: Int): Int = x * 2
val partial = myOperation(5)_
println("calculate")
println("result(3): " + partial(3))
println("result(1): " + partial(1))
The output of this will be:
calculate
complexVal calculated
result(3): 13
complexVal calculated
result(1): 11
So the complexVal was calculated 2 times, what if I want to calculate it just once?
For who has javascript knowledge something like:
function myOperation(x) {
var complexVal = complexCalc(x)
return function(y){
complexVal + y
}
}
EDIT:
So what's the difference between what I've written previously and this:
def myOperation2(x: Int, y: Int): Int = {
val complexVal = complexCalculation(x)
println("complexVal calculated")
complexVal + y
}
val partial = myOperation(5)_
val partial2 = myOperation2(5, _: Int)
You can explicitly return a function from myOperation:
def myOperation(x: Int): Int => Int = {
val complexVal = complexCalc(x)
println("complexVal calculated")
(y: Int) => complexVal + y
}
Partial application just creates a new function by filling in some of the arguments of an existing function, but does not actually execute any part of that function.
For what you're trying to do, you want to return a function from a function. In this case, what you're actually doing is currying (true currying).
Try this:
def myOperation(x : Int) : (Int => Int => Int) = {
val complexVal = complexCalc(x)
(y : Int) => complexVal + y
}
Partial application binds a value to a function argument to give you a function with decreased arity (i.e. fewer arguments). This does not provide any form of memoisation of your expensive computation.
Lee's answer is perfectly good way of solving that problem.
I wanted to memoize this:
def fib(n: Int) = if(n <= 1) 1 else fib(n-1) + fib(n-2)
println(fib(100)) // times out
So I wrote this and this surprisingly compiles and works (I am surprised because fib references itself in its declaration):
case class Memo[A,B](f: A => B) extends (A => B) {
private val cache = mutable.Map.empty[A, B]
def apply(x: A) = cache getOrElseUpdate (x, f(x))
}
val fib: Memo[Int, BigInt] = Memo {
case 0 => 0
case 1 => 1
case n => fib(n-1) + fib(n-2)
}
println(fib(100)) // prints 100th fibonacci number instantly
But when I try to declare fib inside of a def, I get a compiler error:
def foo(n: Int) = {
val fib: Memo[Int, BigInt] = Memo {
case 0 => 0
case 1 => 1
case n => fib(n-1) + fib(n-2)
}
fib(n)
}
Above fails to compile error: forward reference extends over definition of value fib
case n => fib(n-1) + fib(n-2)
Why does declaring the val fib inside a def fails but outside in the class/object scope works?
To clarify, why I might want to declare the recursive memoized function in the def scope - here is my solution to the subset sum problem:
/**
* Subset sum algorithm - can we achieve sum t using elements from s?
*
* #param s set of integers
* #param t target
* #return true iff there exists a subset of s that sums to t
*/
def subsetSum(s: Seq[Int], t: Int): Boolean = {
val max = s.scanLeft(0)((sum, i) => (sum + i) max sum) //max(i) = largest sum achievable from first i elements
val min = s.scanLeft(0)((sum, i) => (sum + i) min sum) //min(i) = smallest sum achievable from first i elements
val dp: Memo[(Int, Int), Boolean] = Memo { // dp(i,x) = can we achieve x using the first i elements?
case (_, 0) => true // 0 can always be achieved using empty set
case (0, _) => false // if empty set, non-zero cannot be achieved
case (i, x) if min(i) <= x && x <= max(i) => dp(i-1, x - s(i-1)) || dp(i-1, x) // try with/without s(i-1)
case _ => false // outside range otherwise
}
dp(s.length, t)
}
I found a better way to memoize using Scala:
def memoize[I, O](f: I => O): I => O = new mutable.HashMap[I, O]() {
override def apply(key: I) = getOrElseUpdate(key, f(key))
}
Now you can write fibonacci as follows:
lazy val fib: Int => BigInt = memoize {
case 0 => 0
case 1 => 1
case n => fib(n-1) + fib(n-2)
}
Here's one with multiple arguments (the choose function):
lazy val c: ((Int, Int)) => BigInt = memoize {
case (_, 0) => 1
case (n, r) if r > n/2 => c(n, n - r)
case (n, r) => c(n - 1, r - 1) + c(n - 1, r)
}
And here's the subset sum problem:
// is there a subset of s which has sum = t
def isSubsetSumAchievable(s: Vector[Int], t: Int) = {
// f is (i, j) => Boolean i.e. can the first i elements of s add up to j
lazy val f: ((Int, Int)) => Boolean = memoize {
case (_, 0) => true // 0 can always be achieved using empty list
case (0, _) => false // we can never achieve non-zero if we have empty list
case (i, j) =>
val k = i - 1 // try the kth element
f(k, j - s(k)) || f(k, j)
}
f(s.length, t)
}
EDIT: As discussed below, here is a thread-safe version
def memoize[I, O](f: I => O): I => O = new mutable.HashMap[I, O]() {self =>
override def apply(key: I) = self.synchronized(getOrElseUpdate(key, f(key)))
}
Class/trait level val compiles to a combination of a method and a private variable. Hence a recursive definition is allowed.
Local vals on the other hand are just regular variables, and thus recursive definition is not allowed.
By the way, even if the def you defined worked, it wouldn't do what you expect. On every invocation of foo a new function object fib will be created and it will have its own backing map. What you should be doing instead is this (if you really want a def to be your public interface):
private val fib: Memo[Int, BigInt] = Memo {
case 0 => 0
case 1 => 1
case n => fib(n-1) + fib(n-2)
}
def foo(n: Int) = {
fib(n)
}
Scalaz has a solution for that, why not reuse it?
import scalaz.Memo
lazy val fib: Int => BigInt = Memo.mutableHashMapMemo {
case 0 => 0
case 1 => 1
case n => fib(n-2) + fib(n-1)
}
You can read more about memoization in Scalaz.
Mutable HashMap isn't thread safe. Also defining case statements separately for base conditions seems unnecessary special handling, rather Map can be loaded with initial values and passed to Memoizer. Following would be the signature of Memoizer where it accepts a memo(immutable Map) and formula and returns a recursive function.
Memoizer would look like
def memoize[I,O](memo: Map[I, O], formula: (I => O, I) => O): I => O
Now given a following Fibonacci formula,
def fib(f: Int => Int, n: Int) = f(n-1) + f(n-2)
fibonacci with Memoizer can be defined as
val fibonacci = memoize( Map(0 -> 0, 1 -> 1), fib)
where context agnostic general purpose Memoizer is defined as
def memoize[I, O](map: Map[I, O], formula: (I => O, I) => O): I => O = {
var memo = map
def recur(n: I): O = {
if( memo contains n) {
memo(n)
} else {
val result = formula(recur, n)
memo += (n -> result)
result
}
}
recur
}
Similarly, for factorial, a formula is
def fac(f: Int => Int, n: Int): Int = n * f(n-1)
and factorial with Memoizer is
val factorial = memoize( Map(0 -> 1, 1 -> 1), fac)
Inspiration: Memoization, Chapter 4 of Javascript good parts by Douglas Crockford
Context
object Fibonacci {
final val Threshold = 30
def fibonacci(n: Int)(implicit implementation: Fibonacci): Int = implementation match {
case f: functional.type if n > Threshold => fibonacci(n)(imperativeWithLoop)
case f: imperativeWithRecursion.type => f(n)
case f: imperativeWithLoop.type => f(n)
case f: functional.type => f(n)
}
sealed abstract class Fibonacci extends (Int => Int)
object functional extends Fibonacci {
def apply(n: Int): Int =
if (n <= 1) n else apply(n - 1) + apply(n - 2)
}
object imperativeWithRecursion extends Fibonacci {
def apply(n: Int) = {
#scala.annotation.tailrec
def recursion(i: Int, f1: Int, f2: Int): Int =
if (i == n) f2 else recursion(i + 1, f2, f1 + f2)
if (n <= 1) n else recursion(1, 0, 1)
}
}
implicit object imperativeWithLoop extends Fibonacci {
def apply(n: Int) = {
def loop = {
var res = 0
var f1 = 0
var f2 = 1
for (i <- 2 to n) {
res = f1 + f2
f1 = f2
f2 = res
}
res
}
if (n <= 1) n else loop
}
}
}
Example
object Main extends App { // or REPL
import Fibonacci._
println(fibonacci(6)(imperativeWithRecursion)) // 8
println(fibonacci(6)(imperativeWithLoop)) // 8
println(fibonacci(6)(functional)) // 8
println(fibonacci(6)) // 8
println(fibonacci(40)(functional)) // 102334155
}
Explanation
I was playing with Scala and ended up with this code. It compiles and runs, but...
Questions:
1) Is there any difference (readbility, performance, known bugs, anything) between
case f: functional.type => f(n)
and
case `functional` => functional(n)
This is supposed to be more of a discussion, so I'm not only interested in facts. Any opinion is welcomed.
2) Look at the first line of the fibonacci method. Here it is:
case f: functional.type if n > Threshold => fibonacci(n)(imperativeWithLoop)
If I leave the 2nd parameter list (imperativeWithLoop) out, the code compiles but enters an infinite loop when I run it. Does anyone know why? The default implementation imperativeWithLoop is known to the compiler (no errors are produced). So why doesn't it get implicitly invoked? (I assume it doesn't)
Regarding the first question, there are small differences, but none that matter here. But it would be better if you uppercased the objects, in which case you could write this:
case Functional => Functional(n)
Regarding the second question, if you leave out imperativeWithLoop, it will select the implicit Fibonacci closest in scope -- implementation (which has already be found to be equal to funcional). So it will call itself with the exact same parameters as it had called before, and, therefore, enter an infinite loop.