I am curious if can implement a Scala function similar to this Javascript function. Obviously, I can do it easily with an inner function.
Knowing that Scala has to declare the parameter type and arity upfront, I just wonder if there is anything I could use to implement this JS function. Thanks.
function factorial(x) {
if (x < 0) throw Error("Cannot calculate factorial of a negative number");
return (function(f) {
return f(f, x, 1);
})(function(f, i, fact) {
return i === 0 ? fact : f(f, i-1, i*fact);
});
}
If I have understood your question correctly, indeed you can do this and the best known approach is to use what's called a Y-combinator. In short a Y-combinator takes a function as a parameter and keeps applying it. The Y-combinator has no knowledge of the parameter types involved
Copying the example Y-combinator right from rosetta code:
def Y[A,B](f: (A=>B)=>(A=>B)) = {
case class W(wf: W=>A=>B) {
def apply(w: W) = wf(w)
}
val g: W=>A=>B = w => f(w(w))(_)
g(W(g))
}
defines your combinator. You can then pass it your recursive function
val fac = Y[Int, Int](f => i => if (i <= 0) 1 else f(i - 1) * i)
fac: Int => Int = <function1>
And then give that something to evaluate
scala> fac(6)
res0: Int = 720
Related
Learning Scala and functional programming in general. In the following tail-recursive factorial implementation:
def factorialTailRec(n: Int) : Int = {
#tailrec
def factorialRec(n: Int, f: => Int): Int = {
if (n == 0) f else factorialRec(n - 1, n * f)
}
factorialRec(n, 1)
}
I wonder whether there is any benefit to having the second parameter called by value vs called by name (as I have done). In the first case, every stack frame is burdened with a product. In the second case, if my understanding is correct, the entire chain of products will be carried over to the case if ( n== 0) at the nth stack frame, so we will still have to perform the same number of multiplications. Unfortunately, this is not a product of form a^n, which can be calculated in log_2n steps through repeated squaring, but a product of terms that differ by 1 every time. So I can't see any possible way of optimizing the final product: it will still require the multiplication of O(n) terms.
Is this correct? Is call by value equivalent to call by name here, in terms of complexity?
Let me just expand a little bit what you've already been told in comments.
That's how by-name parameters are desugared by the compiler:
#tailrec
def factorialTailRec(n: Int, f: => Int): Int = {
if (n == 0) {
val fEvaluated = f
fEvaluated
} else {
val fEvaluated = f // <-- here we are going deeper into stack.
factorialTailRec(n - 1, n * fEvaluated)
}
}
Through experimentation I found out that with the call by name formalism, the method becomes... non-tail recursive! I made this example code to compare factorial tail-recursively, and factorial non-tail-recursively:
package example
import scala.annotation.tailrec
object Factorial extends App {
val ITERS = 100000
def factorialTailRec(n: Int) : Int = {
#tailrec
def factorialTailRec(n: Int, f: => Int): Int = {
if (n == 0) f else factorialTailRec(n - 1, n * f)
}
factorialTailRec(n, 1)
}
for(i <-1 to ITERS) println("factorialTailRec(" + i + ") = " + factorialTailRec(i))
def factorial(n:Int) : Int = {
if(n == 0) 1 else n * factorial(n-1)
}
for(i <-1 to ITERS) println("factorial(" + i + ") = " + factorial(i))
}
Observe that the inner tailRec function calls the second argument by name. for which the #tailRec annotation still does NOT throw a compile-time error!
I've been playing around with different values for the ITERS variable, and for a value of 100,000, I receive a... StackOverflowError!
(The result of zero is there because of overflow of Int.)
So I went ahead and changed the signature of factorialTailRec/2, to:
def factorialTailRec(n: Int, f: Int): Int
i.e call by value for the argument f. This time, the portion of main that runs factorialTailRec finishes absolutely fine, whereas, of course, factorial/1 crashes at the exact same integer.
Very, very interesting. It seems as if call by name in this situation maintains the stack frames because of the need of computation of the products themselves all the way back to the call chain.
I am very new to Scala. I have been assigned the task of coding the Fast Fibonacci algorithm. I am finding it difficult when it comes to actually calling the function. The function takes a tuple of two and returns a tuple of two as a result. I don't know if my logic for fibStep is correct but I will get to that as soon as I can actually test the function. The following is what I have so far:
def fastFib(x: Long ): Long = {
def fibStep(x:(Long, Long)): (Long, Long) = {
//setting temporary variables a and b
def a = x._1
def b = x._2
//applying the fast Fibonacci algorithm
def c = a * (b * 2 - a)
def d = a * a + b * b
if (c+d % 2 == 0) return (c,d)
else return (d, c+d)
}
def tuple = (x-1,x-2)
return fibStep(tuple)
}
I need to pass the tuple (x-1,x-2) to fibStep. How do I do it? Thanks
The problem is in return statement. You trying to return tuple, instead of Long.
Fix:
def fastFib(x: Long ): Long = {
...
return fibStep(tuple)._1 // or ._2
}
Note: I'm not sure if your algorithm is correct
You've got a number of problems here.
def is used to define functions
val should be used to define variables
return should not be used. You 'return' a result simply by it being the last value in an expression.
A tuple is defined simply using parenthesis:
val myTuple = (1,2)
With this information you should be able to make a better attempt at it.
I am learning currying in scala and trying to apply my knowledge on the following piece of code.
object excercise {
def sqrt2(input : Double) : ((Double, Double) => Double, Double) => Double = {
def iter(guessFxn : (Double, Double) => Double, initial : Double) : Double = {
if (isGoodEnough(initial)) initial
else {
val newGuess: Double = guessFxn(initial, input)
iter(guessFxn, newGuess)
}
}
iter
def isGoodEnough(guess: Double): Boolean = {
math.abs(guess * guess - input ) / input < 0.001
}
}
println(sqrt2(2) ( (g: Double, c: Double) => (g + c / g) / 2, 1))
}
What i want to achieve is that sqrt2 should return a function which takes as 2 arguments
1. fxn(that takes 2 doubles as arg and return a double val) 2. double val
When i am trying to run the worksheet it is giving me error
Error: missing arguments for method iter;
follow this method with `_' if you want to treat it as a partially applied function
iter
^
Error: type mismatch;
found : Unit
required: ((Double, Double) => Double, Double) => Double
}
^
Error: missing arguments for method iter;
follow this method with `_' if you want to treat it as a partially applied function
iter
^
You just have to inverse the order of those piece of codes:
iter
def isGoodEnough(guess: Double): Boolean = {
math.abs(guess * guess - input ) / input < 0.001
}
becomes:
def isGoodEnough(guess: Double): Boolean = {
math.abs(guess * guess - input ) / input < 0.001
}
iter
Indeed, ending with an inner declared method involves a return type of Unit...that's not what you want.
Besides, you had this advice:
follow this method with `_' if you want to treat it as a partially applied function
iter
because as explains before, iter method is not returned (since its call is not made at the end of the method) and thus compiler expects it to be executed.
Of course, to be executed, it needs its compulsory parameters, that you didn't provide.
So the compiler "thinks" that you expected to partially apply the function but badly. Note than a partially applied function is not the same concept than a partial function, that has a different meaning ... ).
It would allow to defer the call, and it's mostly used when dealing standard function (not curried), where we might need to provide only the first parameter and later the following.
Example of partially applied function:
def sum(i: Int, j: Int){...}
calls:
sum 1 _ //just the second parameter needs to be applied later.
sum _ //none parameter is specified, would need to specify both later.
sum 1 2 //complete call, not partially applied so
You can find a good use case of partially applied function here.
Note: this is a theoretical question, I am not trying to fix anything, nor am I trying to achieve any effect for a practical purpose
When creating a lambda in Scala using the (arguments)=>expression syntax, can the return type be explicitly provided?
Lambdas are no different than methods on that they both are specified as expressions, but as far as I understand it, the return type of methods is defined easily with the def name(arguments): return type = expression syntax.
Consider this (illustrative) example:
def sequence(start: Int, next: Int=>Int): ()=>Int = {
var x: Int = start
//How can I denote that this function should return an integer?
() => {
var result: Int = x
x = next(x)
result
}
}
You can always declare the type of an expression by appending : and the type. So, for instance:
((x: Int) => x.toString): (Int => String)
This is useful if you, for instance, have a big complicated expression and you don't want to rely upon type inference to get the types straight.
{
if (foo(y)) x => Some(bar(x))
else x => None
}: (Int => Option[Bar])
// Without type ascription, need (x: Int)
But it's probably even clearer if you assign the result to a temporary variable with a specified type:
val fn: Int => Option[Bar] = {
if (foo(y)) x => Some(bar(x))
else _ => None
}
Let say you have this function:
def mulF(a: Int, b: Int): Long = {
a.toLong * b
}
The same function can be written as lambda with defined input and output types:
val mulLambda: (Int, Int) => Long = (x: Int, y: Int) => { x.toLong * y }
x => x:SomeType
Did not know the answer myself as I never had the need for it, but my gut feeling was that this will work. And trying it in a worksheet confirmed it.
Edit: I provided this answer before there was an example above. It is true that this is not needed in the concrete example. But in rare cases where you'd need it, the syntax I showed will work.
Does anyone know the type of => Unit in scala? I don't know the meaning of => Unit and how to use it. I defined a function like below:
def test(code: => Unit){
print("start ...")
code
print("end ....")
}
test(print(1))
Does it means a function with any arguments returning Unit?
Thanks
This kind of parameter are called by-name parameter
=> B represents a block a of code which return a B value, their purpose is that they are evaluated only when you call the parameter.
def foo(code: => Int) {
println("Not yet evaluated")
val result = code
println("parameter evaluated %s, is it an int ? %s " format (
result, result.isInstanceOf[Int]) )
}
And you can call foo in the following way :
foo(1)
or
val a = 3
val b = 5
foo {
val c = a * a
c * b
}
The other style of passing parameter is by-value : parameters are evaluated before they are sent to the method
def foo(code : Int) {
println("Parameter already evaluated")
val result = code
println("parameter evaluated : " + result)
}
References
Extract from the Book Functionnal Programming in Scala
More differences between by-name parameter and by-value parameter illustrated
In x: => Type the x is a call by name parameter. That's different than taking an argument which is a function taking no arguments: x: () => Type
This is called a by name parameter, as related to call-by-name parameter evaluation strategy. Please see the linked wikipedia article for similar, but not identical, ways of passing parameters.
To explain it better, let's consider first the two most common parameter evaluation strategies: call by value and call by reference.
Call by value is by far the most common evaluation strategy. It is the sole strategy in Java, for instance, and the default strategy in C. Consider, for instance, this simple Java program:
public class ByValue {
static public void inc(int y) {
y++;
}
static public void main(String... args) {
int x = 0;
inc(x);
System.out.println(x);
}
}
It will print 0, because x's value is copied to y, so that when y is incremented it doesn't change the original value in x. Contrast this with this C++ program with call-by-reference:
#include <stdio.h>
void inc(int &y) {
y++;
}
int main() {
int x = 0;
inc(x);
printf("%d\n", x);
}
This will print 1, because the reference to x is passed to inc, instead of x's value.
Note that Java passes objects references by value, which leads some to claim it does call by reference. This is not true, to the extent that if you were to assign a new object to a parameter of a function, it would not be reflected in the function's caller.
So, what does a call by name looks like? In a call by name, neither value nor reference is passed. Instead, the whole code is passed, and everywhere the parameter is used, the code is executed and its result used. For example:
object ByName {
def incIfZero(y: => Int): Int = if (y == 0) y + 1 else y
def main(args: Array[String]) {
var x = 0
x = incIfZero( { val tmp = x; x += 1; tmp } )
println(x)
}
}
This example prints 2 instead of 1, because the block of code passed as parameter is evaluted twice. When executing, it's as if the second line in the main was written like this:
x = if ({ val tmp = x; x += 1; tmp }) { val tmp = x; x += 1; tmp } + 1 else { val tmp = x; x += 1; tmp }
Now, by name parameters have at least three interesting uses:
It can be used to delay the execution of something until the proper time.
It can be used to avoid the execution in some situations.
It can be used to execute some block of code multiple times.
The first and last cases are pretty obvious, I think. Here's an example of the second case:
implicit def fromBoolean(b: Boolean) = new {
def and(that: => Boolean): Boolean = if (b) that else b }
val x = 0
(x > 0) and (10 / x > 0)
If that was not a by name parameter, there would be an exception thrown at the last line. As it is, it will just return false.
It means call-by-name, which basically means that the value is calculated when used in your function. As opposed to call-by-value which is default in Java (and Scala with regular type syntax), where the value is calculated before the method is called. A Unit type would not make much sense in call-by-value I guess..
This is typically used to create functions that behave as custom control structures, or things like timing or logging as in your example. Stuff you often use AOP to do in Java.