I am getting the following error on Scala:
scala> :pas
// Entering paste mode (ctrl-D to finish)
// sum takes a function that takes an integer and returns an integer then
// returns a function that takes two integers and returns an integer
def sum(f: Int => Int): (Int, Int) => Int =
def sumf(a: Int, b: Int): Int = f(a) + f(b)
sumf
// Exiting paste mode, now interpreting.
<pastie>:4: error: illegal start of simple expression
def sumf(a: Int, b: Int): Int = f(a) + f(b)
^
I am not understanding why def is an illegal start of simple expression. I am simply trying to declare a function. Am I violating any syntax requirements in the declaration? Thank you.
UPDATE: This is my version of Scala:
sbt:jaime> console
[info] Starting scala interpreter...
Welcome to Scala 2.12.10 (OpenJDK 64-Bit Server VM, Java 11.0.14).
Type in expressions for evaluation. Or try :help.
scala>
Two ways to make it work, as Luis Miguel Mejía Suárez mentioned in the comment to this question.
scala> :pas
// Entering paste mode (ctrl-D to finish)
def sum(f: Int => Int): (Int, Int) => Int = {
def sumf(a: Int, b: Int): Int = f(a) + f(b)
sumf
}
// Exiting paste mode, now interpreting.
sum: (f: Int => Int)(Int, Int) => Int
scala> :pas
// Entering paste mode (ctrl-D to finish)
def sum(f: Int => Int): (Int, Int) => Int = (a, b) => f(a) + f(b)
// Exiting paste mode, now interpreting.
sum: (f: Int => Int)(Int, Int) => Int
scala>
Related
I'm trying to write a tail recursive function in the below way, but the compiler is throwing an error:
Too many arguments for method apply: (v1: Int)Int in trait Function1
else factorial(x-1, x*acc)
I had tried replacing Function1 with Function2 and gave Function2[Int, Int, Int] = new Function2[Int, Int, Int]
But it still threw me the same error. Can someone point out where i'm going wrong?
import scala.annotation.tailrec
var factorial: Function1[Int, Int] = new Function1[Int, Int] {
#tailrec override def apply (x:Int, acc:Int=1): Int = {
if (x<=1) acc
else factorial(x-1, x*acc)
}
}
factorial(5)
You apply inside Function1 must take only one param, when you are passing two.
You can rewrite it as follows:
var factorial: Function1[Int, Int] = new Function1[Int, Int] {
def apply (x:Int): Int = {
#tailrec def loop(x: Int, acc: Int = 1): Int = {
if (x<=1) acc
else loop(x-1, x*acc)
}
loop(x)
}
}
Function1 represents a function with a single parameter (the second one is for the output)
So you need to define your apply method with a single parameter, and then, inside it, do the recursion using a nested function:
import scala.annotation.tailrec
var factorial: Function1[Int, Int] = new Function1[Int, Int] {
override def apply(x: Int): Int = {
#tailrec
def go (x: Int, acc: Int = 1) : Int = {
if (x<=1) acc
else go(x-1, x*acc)
}
go(x)
}
}
factorial(5)
You can see this answer which is a great explanation of your issue. Your problem is you are trying to define apply as tail-recursive but you are not calling itself in the recursive call, you are calling factorial instead.
First off, you should use Function2 as your type for apply likewise:
import scala.annotation.tailrec
import scala.annotation.tailrec
var factorial: Function2[Int, Int, Int] = new Function2[Int, Int, Int] {
#tailrec override def apply (x:Int, acc:Int=1): Int = {
if (x<=1) acc
else apply(x-1, x * acc)
}
}
And then, if you get the error could not optimize #tailrec annotated method apply: it contains a recursive call targeting a supertype, you should call apply recursively as for a function to be tail recursive it always should be called exactly itself as the last statement.
scala> factorial(5, 1)
res3: Int = 120
Function2 take 3 type parameters. Last one is the output type.
Scala REPL
scala> :paste
// Entering paste mode (ctrl-D to finish)
val fac: Function2[Int, Int, Int] = new Function2[Int, Int, Int] {
def apply(v1: Int, v2: Int): Int = if (v1 == 1) v2 else apply(v1 - 1, v1 * v2)
}
// Exiting paste mode, now interpreting.
fac: (Int, Int) => Int = <function2>
scala> fac(5, 1)
res1: Int = 120
You can syntactic sugar (function syntax in scala using =>) instead of using interface/trait Function2.
scala> :paste
// Entering paste mode (ctrl-D to finish)
val fac: (Int, Int) => Int = (acc, c) => if (c == 1) acc else fac(acc * c, c - 1)
// Exiting paste mode, now interpreting.
fac: (Int, Int) => Int = $$Lambda$1092/1204822967#5c83ae01
scala> fac(1, 5)
res0: Int = 120
Or, if you like some syntactic sugar, you can write it:
val f: (Int) => BigInt = (x) => {
if (x <= 1) 1
else x * f(x - 1)
}
println(f(30))
Or true tail-recursive function:
val f: (Int) => BigInt = (x) => {
#tailrec
def helper(x: Int, acc: BigInt = 1): BigInt = {
if (x <= 1) acc
else helper(x - 1, x * acc)
}
helper(x)
}
println(f(30))
This question already has answers here:
Currying syntax in scala
(2 answers)
Closed 5 years ago.
In the course of funcional programming with Scala, I saw two form of declaration of a def. But I don't know the diferences between them, and the name given for this. How I can get more information about this?
Declaration 1
def sum(f: Int => Int)(a: Int, b: Int): Int = ???
Declaration 2
def sum(f: Int => Int, a: Int, b: Int): Int = ???
First one is called the curried syntax.
You can apply the function partially, then results in returning of a new function.
scala> def sum(f: Int => Int)(a: Int, b: Int): Int = f(a) + f(b)
sum: (f: Int => Int)(a: Int, b: Int)Int
scala> sum({x: Int => x + 1}) _
res10: (Int, Int) => Int = $$Lambda$1115/108209958#474821de
Second one is uncurried syntax but still we can apply the function partially even in this case.
scala> def sum(f: Int => Int, a: Int, b: Int): Int = f(a) + f(b)
sum: (f: Int => Int, a: Int, b: Int)Int
scala> sum({x: Int => x + 1}, _: Int, _: Int)
res11: (Int, Int) => Int = $$Lambda$1116/1038002783#1a500561
Again new function returned when applied partially.
There is no difference between above two declaration, Its just the syntactic sugar.
I'm fairly new to Scala and functional programming in general so I'm having a bit trouble wrapping my head around the concept of partially applied functions and function currying. There's also a pretty high chance that I'm gonna mix up some terminology, so all corrections are appreciated.
Note: I'm using the Scala Play framework but this is more of a Scala problem than a Play problem.
Given a function like this
def create(id: Long, userId: Long, label: String)
I get the userId and label as a (Int, String) tuple and the id as a Long. Basically what I'm trying to do is passing the id and the tuple to the function at the same time.
Now, I've read that passing a tuple to a function can be done something like this
scala> def f(a: Int, b: String) = 0
f: (a: Int, b: String)Int
scala> (f _).tupled((2, "Hello"))
res0: Int = 0
and that it is also possible to partially apply a function like this
scala> def f(a: Int, b: String) = 0
f: (a: Int, b: String)Int
scala> val ff = f(_: Int, "Hello")
ff: Int => Int = <function1>
scala> ff(2)
res1: Int = 0
So my initial idea was to combine these two concepts something like this
scala> def g(a: Long, b: Int, c: String) = 0
g: (a: Long, b: Int, c: String)Int
scala> val h = g(1, _: Int, _: String)
h: (Int, String) => Int = <function2>
scala> (h _).tupled((2, "Hello"))
However this results in an error
<console>:10: error: _ must follow method; cannot follow h.type
(h _).tupled((1, "Hello"))
^
So my question is first of all why doesn't this work because to me this makes sense. And secondly how would I go about achieving this effect?
Thanks for your help!
Just don't abstract it twice: don't do redundand underscore to the h as it's already a function after partial-applying:
scala> def create(a: Long, b: Int, c: String) = 0
create: (a: Long, b: Int, c: String)Int
scala> val h = create(1, _: Int, _: String)
h: (Int, String) => Int = <function2>
scala> h.tupled((1, "Hello"))
res0: Int = 0
More deeply, tupled is defined on functions (means object of Function, like Int => String), not on methods (like def f(i: Int): String) - so sometimes you need to convert a method to the function - it's called eta-expansion (or eta-abstraction more generally). When you do partial applying - eta-expansion is done automatically (you already have a (Int, String) => Int) - so you don't have to do it twice.
See The differences between underscore usage in these scala's methods, Difference between method and function in Scala for more information.
def readf(value_name: String, operator:operand, compared_value:Int f:()=>Unit) {
I want to look up an Int in a HashMap based on the value_name String passed in. Taking that value I want to compare it
value operator compared_value
if that statement is true I want to execute f.
How do I pass in a comparator and evaluate this logic? Preferably without writing my own classes.
The result from the HashMap can be as an Option which you can then filter with the operand/compared_value. Then it should be just a map on the resulting option. It would look something like:
yourMap.get(value_name).filter(_ operator compared_value).map(f)
This does assume that operator is (Int, Int) => Boolean as asked in the comment
It's kind of hard to help with the editorial issues your question has, but I'll try. Assuming you have a myMap: Map[String, Int] in scope (which your question does not show) and assuming your operator is really of type (Int, Int) => Boolean, you could do:
scala> val myMap = Map("test" -> 8)
myMap: scala.collection.immutable.Map[String,Int] = Map(test -> 8)
scala> :paste
// Entering paste mode (ctrl-D to finish)
def readf(value_name: String, operator: (Int, Int) => Boolean, compared_value:Int, f:()=>Unit) {
myMap.get(value_name).filter(operator(_, compared_value)).foreach(_ => f())
}
// Exiting paste mode, now interpreting.
readf: (value_name: String, operator: Int => (Int => Boolean), compared_value: Int, f: () => Unit)Unit
scala> val eqComparator = ((_: Int) == (_: Int))
eqComparator: (Int, Int) => Boolean = <function2>
scala> val f = () => println("success")
f: () => Unit = <function0>
scala> readf("test", eqComparator, 8, f)
success
scala> readf("test", eqComparator, 5, f)
scala> readf("other", eqComparator, 8, f)
(Edited to remove the curried operator. It's probably clearer this way.)
I have two set methods defined as follows:
def set(value: Any) : Unit = {
val (a, b, c, d) = value.asInstanceOf[(Int, Int, Int, Int)]
set(a, b, c, d)
}
def set(aValue: Int, bValue: Int, cValue: Int, dValue: Int) = {
...
}
I also have a method that generates a tuple:
def getResults() = (1,2,3,4)
I would like to give the getResults() as an input to the set method.
((set _).tupled)(getResults())
The issue is that this code does not compile as set is defined twice. How can I resolve this issue?
The presentation compiler of your IDE appears to be more confused than it should be.
If you try the code in a REPL it will work. Unfortunately, though, the resolution of set depends on the definition order.
Here's a scala REPL session demonstrating this fact:
scala> :paste
// Entering paste mode (ctrl-D to finish)
def set(value: Any) : Unit = {
val (a, b, c, d) = value.asInstanceOf[(Int, Int, Int, Int)]
set(a, b, c, d)
}
def set(aValue: Int, bValue: Int, cValue: Int, dValue: Int) = println("ok")
// Exiting paste mode, now interpreting.
set: (value: Any)Unit <and> (aValue: Int, bValue: Int, cValue: Int, dValue: Int)Unit
set: (value: Any)Unit <and> (aValue: Int, bValue: Int, cValue: Int, dValue: Int)Unit
scala> (set _).tupled((1, 2, 3, 4))
ok
scala> :paste
// Entering paste mode (ctrl-D to finish)
def set(value: Any) : Unit = {
val (a, b, c, d) = value.asInstanceOf[(Int, Int, Int, Int)]
set(a, b, c, d)
}
// Exiting paste mode, now interpreting.
set: (value: Any)Unit
scala> (set _).tupled((1, 2, 3, 4))
<console>:9: error: value tupled is not a member of Any => Unit
(set _).tupled((1, 2, 3, 4))
Generally speaking, the confusion comes from overloading mixed with partially applied function.
Overloaded methods are disambiguated using their parameter list, but, when you partially apply them, you're throwing this information away, and you can only hope that the compiler will see the "right" set before the wrong one.
However, I doubt this is specified anywhere, so you're basically binding the semantic of your program to a compiler implementation detail: bad idea, isn't it?
As Travis Brown already suggested in the comments, why don't you just avoid overloading and make your life (and the compiler) happier?