I have the following function
scala> def f1 = (prefix: String) => prefix + ".field"
f1: String => java.lang.String
And I'd like to define another function from f1, that fixed the value of prefix to p1, like this
def f2: () => String = () => f1("p1")
or more shortly
def f2 = () => f1("p1")
I think that the same could be achieved using Function.curried or f.curried and partialy applied functions, but I still couldn't do it...
--
Having a look a this article I found a more verbose way of defining it. I guess the above syntax is just suger for this longer form...
scala> object f2 extends Function0[String] {
| override def apply = f1("p1")
| }
defined module f2
scala> f2
res37: f2.type = <function0>
scala> f2()
res38: java.lang.String = p1.field
You can only "curry" functions with more than one argument. At least with the methods that Scala provides by default. With two parameters it works like this:
val f2 = (prefix: String, foo:String) => prefix + ".field"
val f1 = f2.curried("p1")
If you want to do the same with Function1, you can "pimp" the class to add a new method:
implicit def addCurry[A,B](f:Function[A,B]) = new Function1WithCurried(f)
class Function1WithCurried[-A,+B](f:Function1[A,B]) {
def curried:Function1[A,Function0[B]] = (x:A) => { () => f(x) }
}
def f1 = (prefix: String) => prefix + ".field"
val f0 = f1.curried
val f2 = f1.curried("p1")
Extending #Kim Stebel's answer bit further. You can do this:
scala> val f2 = (prefix: String, foo:String) => prefix + ".field"
f2: (String, String) => java.lang.String = <function2>
scala> val f1 = f2("p1",_:String)
f1: String => java.lang.String = <function1>
And to make it clear, what we are doing here it not currying, it's 'partial application'.
If what you're looking for is currying, you could do it even more verbose like this:
scala> def f1(f: String => String)(s: String) = f(s)
f1: (f: String => String)(s: String)String
scala> def f2 = () => f1(p => p + ".field")("p1")
f2: () => String
scala> f2()
res4: String = p1.field
Related
Lets say I want to store a Map[String, Function1] where the parameter and return type of the Function1 can vary. How would I go about storing a Function1[String, String] and Function1[Int, Int] in the same Map.
I've tried Function1[AnyRef, AnyRef] but Function1[String, String] isn't a Function1[AnyRef, AnyRef] so it fails to compile.
If you have only two possible value types, you can wrap values in Either:
val m = Map[String, Either[Int => Int, String => String]]()
If you want to store more than two different types, create your own wrapper, or use something like Coproduct from shapeless.
Does this look like what you're after?
scala> val m = Map[String, Function1[_,_]]()
m: scala.collection.immutable.Map[String,Function1[_, _]] = Map()
scala> val f1 = (i:Int) => i*3
f1: Int => Int = <function1>
scala> val f2 = (b: Boolean) => if (b) "YES" else "NO"
f2: Boolean => String = <function1>
scala> m + ("xcx" -> f2) + ("rtr" -> f1)
res59: scala.collection.immutable.Map[String,Function1[_, _]] = Map(xcx -> <function1>, rtr -> <function1>)
There are some discussions here about this, but I have some specific questions I wasn't able to find an answer for. So, by call-by-name, I mean =>T type, and by 0-arity function I mean () => T
I understand (I think) the conceptual difference, but probably I am missing something as I still have lots of questions:
Why do we have the concept of =>T at all if we could always use () => T?
Is there any syntax/functional limitations of each? For now I found only that => cannnot be used as a class field. Is this the only limitation?
Is the generated code always the same for both?
Should I always prefer =>T? And why?
Is it correct to call =>T a type? It looks for me like it does not have any type representation in scala.
1) It's just more handy to use it, especially inside DSLs:
def printAndGet[T](f: => T) = {
val res = f
println(res + " printed")
res
}
scala> :paste
// Entering paste mode (ctrl-D to finish)
val k = printAndGet {
val a = 5
5 * a
}
// Exiting paste mode, now interpreting.
25 printed
k: Int = 25
2) => T can only be a parameter of method or function. And actually => T and () => T aren't interchangable:
scala> def aaa(f: => String) = f
aaa: (f: => String)String
scala> val a: Function1[() => String, String] = aaa _
<console>:8: error: type mismatch;
found : (=> String) => String
required: (() => String) => String
val a: Function1[() => String, String] = aaa _
^
Thanks to #som-snytt, fоund this one:
scala> object O { def f(i: Int) = i; def f(i: => Int) = i + 1 }
defined object O
scala> O.f(5)
res12: Int = 5
scala> O.f(5: (=> Int))
<console>:1: error: no by-name parameter type allowed here
O.f(5: (=> Int))
^
Even this which should work if it compiles - but it doesn't (scala 2.11.2, 2.11.5 REPL just crashes):
scala> val k: (=> Int) => Int = O.f _
k: (=> Int) => Int = <function1>
scala> k(5) //should be 6
res18: Int = 5 //WTF?
Last one seems like a bug
3) Not exactly, if you want the same, just convert => T into () => T:
scala> def aaa(f: => String) = {f _}
aaa: (f: => String)() => String
Bytecode may also differ. For instance, compiler will more likely inline code from => T without generating lambda for it. So, the key difference is that () => T is actually an object (first class citizen), => T isn't.
4) see 1, but sometimes you may need to ensure that user knows that computation might be delayed - () => T is better then.
5) It's part of a type signature, just look at eta-expansion of:
scala> def aaa(f: => String) = {f}
aaa: (f: => String)String
scala> aaa _ //convert method into a function
res7: (=> String) => String = <function1>
scala> val a: ( => String) => String = aaa _
a: (=> String) => String = <function1>
However scala doesn't recognize it as independent type:
scala> val a: Function1[( => String), String] = aaa _
<console>:1: error: no by-name parameter type allowed here
val a: Function1[( => String), String] = aaa _
^
Given for instance a Tuple2 of the form
type Duple = (String,Int)
this function errs to extract and label the duple's items in the arguments,
def f( (s,n): Duple ): String = s*n
However this works,
def f( d: Duple ): String = {
val (s,n) = d
s*n
}
Is there a shorter form to extract and label a tuple's items in a function than this declarative approach ?
Start with a regular 2 arg function:
scala> val f: (String, Int) => String = (a, b) => a * b
f: (String, Int) => String = <function2>
convert it to single arg function that accepts tuples:
scala> val tf = f tupled
tf: ((String, Int)) => String = <function1>
call it with a tuple arg:
scala> tf("a" -> 2)
res0: String = aa
or if you going the opposite direction:
start with a function that takes a tuple:
scala> tf
res2: ((String, Int)) => String = <function1>
convert it to function that takes 2 args:
scala> val uf = Function.untupled(tf)
uf: (String, Int) => String = <function2>
call it with 2 args:
scala> uf("b", 3)
res3: String = bbb
def f(d: Duple): String = d._1 * d._2
def f(d: Duple): String = d match { case (x, y) => x * y }
I am trying to define a Map literal with key: String, value: (Any)=>String. I tried the following, but get a syntax error:
def foo(x: Int): String = /...
def bar(x: Boolean): String = /...
val m = Map[String, (Any) => String]("hello" -> foo, "goodbye" -> bar)
Funny that no one actually gave a type that would work. Here's one such:
def foo(x: Int): String = x.toString
def bar(x: Boolean): String = x.toString
val m = Map[String, (Nothing) => String]("hello" -> foo, "goodbye" -> bar)
The reason why it works this way is because Function1 is contra-variant on the input, so (Nothing) => String is a superclass of (Int) => String. It is also co-variant on the output, so (Nothing) => Any would be a superclass to any other Function1.
Of course, you can't use it like that. Without manifests, you can't even uncover what the original type of Function1 is. You could try something like this, though:
def f[T : Manifest](v: T) = v -> manifest[T]
val m = Map[String, ((Nothing) => String, Manifest[_])]("hello" -> f(foo), "goodbye" -> f(bar))
val IntManifest = manifest[Int]
val BooleanManifest = manifest[Boolean]
val StringManifest = manifest[String]
m("hello")._2.typeArguments match {
case List(IntManifest, StringManifest) =>
m("hello")._1.asInstanceOf[(Int) => String](5)
case List(BooleanManifest, StringManifest) =>
m("hello")._1.asInstanceOf[(Boolean) => String](true)
case _ => "Unknown function type"
}
Int => String is not a subclass of Any => String, rather, the contrary. You can't put (replace) an Int => String function when a code expects Any => String, since that code can apply the function with, say, "hi".
#Ben suggestion works, but how is it useful? you can't invoke the function once you get it from the Map.
If you really want to do this, maybe define foo as a partial function:
val foo: PartialFunction[Any, String] = {case i: Int => ....}
Obviously, this will fail at runtime if you pass it a string, but you can always test if the function is ok for use with your parameter by using isDefinedAt. (another alternative may be manifests, but I don't see the value here)
If I let the compiler infer it I seem to get an illegal type:
scala> val m = Map("hello" -> foo _, "goodbye" -> bar _)
m: scala.collection.immutable.Map[java.lang.String,(Boolean with Int) => String] =
Map((hello,<function1>), (goodbye,<function1>))
scala> m("hello")(8)
<console>:9: error: type mismatch;
found : Int(8)
required: Boolean with Int
m("hello")(8)
scala> var q = new Boolean with Int
<console>:5: error: illegal inheritance from final class Boolean
var q = new Boolean with Int
Anyway, what you want is not the type Any but a generic of "any type" which is _:
scala> val mm = Map[String, (_) => String]("hello" -> foo _, "goodbye" -> bar _)
mm: scala.collection.immutable.Map[String,Function1[_, String]] =
Map((hello,<function1>), (goodbye,<function1>))
I just posted a question about how to invoke such functions because I don't actually know.
Trait Function1 is contravariant for parameter, so def foo(x: Int): String is not a (Any) => String. So the following would work:
scala> def baz(x: Any): String = "baz"
baz: (x: Any)String
scala> val m2 = Map[String, (String) => String]("hello" -> baz)
m2: scala.collection.immutable.Map[String,(String) => String] = Map((hello,<function1>))
This is how I did it to fulfill a similar requirement.
object MapToMethods {
private def increment(x: Int): Int = x+1
private def decrement(x: Int): Int = x-1
val m: Map[String, Int => Int] =Map("increment" -> increment, "decrement" ->decrement)
println(m("increment")(2)) //prints 3
println(m("decrement")(3)) //prints 2
}
I know this question has come up many times in different ways. But it is still not clear to me. Is there a way to achieve the following.
def foo(a:Int, b:Int) = {}
foo(a,b) //right way to invoke foo
foo(getParams) // is there a way to get this working without explicitly unpacking the tuple??
def getParams = {
//Some calculations
(a,b) //where a & b are Int
}
It's a two step procedure. First turn foo into a function, then call tupled on it to make it a function of a tuple.
(foo _).tupled(getParams)
#dave-griffith is dead on.
You can also call:
Function.tupled(foo _)
If you want to wander into "way more information than I asked for" territory, there are also methods built into partially applied functions (and on Function) for currying. A few input/output examples:
scala> def foo(x: Int, y: Double) = x * y
foo: (x: Int,y: Double)Double
scala> foo _
res0: (Int, Double) => Double = <function2>
scala> foo _ tupled
res1: ((Int, Double)) => Double = <function1>
scala> foo _ curried
res2: (Int) => (Double) => Double = <function1>
scala> Function.tupled(foo _)
res3: ((Int, Double)) => Double = <function1>
// Function.curried is deprecated
scala> Function.curried(foo _)
warning: there were deprecation warnings; re-run with -deprecation for details
res6: (Int) => (Double) => Double = <function1>
Wherein the curried version is invoked with multiple argument lists:
scala> val c = foo _ curried
c: (Int) => (Double) => Double = <function1>
scala> c(5)
res13: (Double) => Double = <function1>
scala> c(5)(10)
res14: Double = 50.0
Finally, you can also uncurry/untuple if needed. Function has builtins for this:
scala> val f = foo _ tupled
f: ((Int, Double)) => Double = <function1>
scala> val c = foo _ curried
c: (Int) => (Double) => Double = <function1>
scala> Function.uncurried(c)
res9: (Int, Double) => Double = <function2>
scala> Function.untupled(f)
res12: (Int, Double) => Double = <function2>
Function.tupled(foo _)(getParams) or the one suggested by Dave.
EDIT:
To respond to your comment:
What if foo happens to be the
constructor of some class?
In that case, this trick won't work.
You can write a factory method in the companion object of your class and then obtain the tupled version of its apply method using one of the aforementioned techniques.
scala> class Person(firstName: String, lastName: String) {
| override def toString = firstName + " " + lastName
| }
defined class Person
scala> object Person {
| def apply(firstName: String, lastName: String) = new Person(firstName, lastName)
| }
defined module Person
scala> (Person.apply _).tupled(("Rahul", "G"))
res17: Person = Rahul G
With case classes you get a companion object with an apply method for free, and thus this technique is more convenient to use with case classes.
scala> case class Person(firstName: String, lastName: String)
defined class Person
scala> Person.tupled(("Rahul", "G"))
res18: Person = Person(Rahul,G)
I know that's a lot of code duplication but alas... we don't have macros (yet)! ;)
I appreciate some of the other answers which were closer to what you asked for, but I found it easier for a current project to add another function which converts tuple parameters into the split parameters:
def originalFunc(a: A, b: B): C = ...
def wrapperFunc(ab: (A, B)): C = (originalFunc _).tupled(ab)
Now, you can implement foo and make it take a param of the Tuple2 class like so.
def foo(t: Tuple2[Int, Int]) = {
println("Hello " + t._1 + t._2)
"Makes no sense but ok!"
}
def getParams = {
//Some calculations
val a = 1;
val b = 2;
(a, b) //where a & b are Int
}
// So you can do this!
foo(getParams)
// With that said, you can also do this!
foo(1, 3)