Just wanted to know question w.r.t Currying
If we have defined the curried function curriedNewSum
scala> def curriedNewSum(x : Int)(y : Int) = x + y
curriedNewSum: (x: Int)(y: Int)Int
scala> curriedNewSum(10)(20)
res5: Int = 30
scala> var tenPlus = curriedNewSum(10)_
tenPlus: (Int) => Int = <function1>
scala> tenPlus(20)
res6: Int = 30
scala> var plusTen = curriedNewSum(_)(20)
<console>:6: error: missing parameter type for expanded function ((x$1) => curri
edNewSum(x$1)(20))
var plusTen = curriedNewSum(_)(20)
^
So why does curriedNewSum(10)_ works & curriedNewSum(_)(10) not?
I'm not 100% sure what exactly is the problem, but I strongly suspect this isn't doing what you think it is.
Try, for instance,
var plusTen = curriedNewSum(_)
You'll see it will return a Function1[Int, Function1[Int, Int]]. Now try this:
var plusTen = (curriedNewSum(_))(10)
And see it work! Well, that translates into:
var plusTen = ((x: Int) => curriedNewSum(x))(10)
While the other way translates into:
var plusTen = (x) => curriedNewSum(x)(10)
Something about how the function is expanding is screwing up with the type inference.
I am not exactly sure why it doesn't work. But this seems to work:
curriedNewSum(_:Int)(20)
After I thought about this more, it might be that the possibility exists of having an overloaded curriedNewSum methods
curriedNewSum(x:Double)(y:Int)
curriedNewSum(x:Float)(y:Int)
which one would be chosen? Defining the type explicitly says which method you want.
I suspect the type should be inferred where there is no ambiguity and that this is a bug or deliberately omitted.
Related
So, suppose, I want to provide a "catch all" fall back for a PartialFunction:
val foo: PartialFunction[Int, String] = { case 1 => "foo" }
val withDefault = foo orElse { _.toString }
This does not compile: missing parameter type for expanded function ((x$1) => x$1.toString).
This:
val withDefault = foo orElse { case x: Int => x.toString }
Does not compile either (same error).
This:
val withDefault = foo orElse { (x: Int) => x.toString }
fails with type mismatch; found : Int => String; required: PartialFunction[?,?]
The only way I could find to make it work is to spell out the whole thing:
val withDefault = foo orElse PartialFunction[Int, String] { _.toString }
Is there any better syntax for this? I mean, one without having to tell it that I am passing a partial function from int to string to where it expects to receive a partial function from in to string. This is not ambiguous at all, why do I have to do this?
Maybe you need applyOrElse:
val withDefault = foo.applyOrElse(_: Int, (_: Int).toString)
Or maybe you would like something like this:
implicit class PartialFunToFun[A,B](val f: PartialFunction[A,B]) extends AnyVal {
def withDefault(bar: A => B) = f.applyOrElse[A,B](_: A, bar)
}
and use it: foo.withDefault(_.toString)(1)
Also if you want to get just another PartialFunction you can use the next syntax:
val withDefault = foo.orElse[Int, String]{case x => x.toString}
The errors you encountered for the first two are not specific to orElse. They also occur when you attempt to define the same functions separately.
scala> { _.toString }
<console>:12: error: missing parameter type for expanded function ((x$1: <error>) => x$1.toString)
{ _.toString }
scala> { case x: Int => x.toString }
<console>:12: error: missing parameter type for expanded function
The argument types of an anonymous function must be fully known. (SLS 8.5)
Expected type was: ?
{ case x: Int => x.toString }
^
For the last one, you are defining a function rather than a PartialFunction, thus leading to the "type mismatch" since orElse expects a PartialFunction to be passed.
scala> { (x: Int) => x.toString }
res3: Int => String = $$Lambda$1127/2044272973#3d5790ea
The final thing I'll add is that orElse is meant as a way to union two PartialFunctions. _.toString in itself is not a PartialFunction, though you could create a PartialFunction that uses it. To me it sounds like you want to have a "default" result for all the values that foo is not defined for, so I think you actually want applyOrElse instead since that is its use case. See the API to learn more.
I have the following two methods in Scala:
def myFunc: Int => String = { age =>
"Here " + age
}
def myFunc2 (age: Int) : String = {
"Here" + age
}
Is there any difference in these two methods? (other than the names of course). The syntax looks quite different to me. Is it just a matter of style? Is one prefered over the other?
Yes, there is a difference. The former is a method which takes no arguments and returns a function of type Function1[Int, String]. The latter is a method taking a String and returning an Int.
In Scala, methods with arity-0 can be declared and invoked without parenthesis, so invoking myFunction(1) and myFunction2(1) looks the same.
If we'd convert both methods to functions, you'd see the difference in the fact that the former would take the shape of Function0[Function1[Int, String]], while the latter would be Function1[Int, String]:
myFunc: Int => String
myFunc2: (age: Int)String
scala> myFunc _
res6: () => Int => String = <function0>
scala> myFunc2 _
res7: Int => String = <function1>
I'm trying to figure out the difference between def and var/val when declaring a function in Scala.
Say we have a function:
scala> def f(x: Int) = { x * 2 }
f: (x: Int)Int
And another function g:
scala> var g = (x:Int) => x*2
g: Int => Int = <function1>
Apparently they are the same in the following way:
scala> f(2)
res0: Int = 4
scala> g(2)
res1: Int = 4
However, I could do
g = f
g: Int => Int = <function1>
but not
scala> f = g
<console>:13: error: missing arguments for method f;
follow this method with `_' if you want to treat it as a partially applied function
val $ires6 = f
^
<console>:10: error: reassignment to val
f = g
^
Question 1: why does this happen? I'm guessing that def maps to val.
Question 2: if I use val instead of var in declare g, are they equivalent? If not, what is the difference then?
I then try:
scala> def three( timetwo:(Int) => Int ) = { timetwo(3) }
three: (timetwo: Int => Int)Int
scala> three(g)
res47: Int = 6
scala> three(f)
res48: Int = 6
Question 3: does it mean (x: Int)Int is the same as Int => Int = <function1>? If so, is there some situation that we should favor one over the other?
Things is getting wired with the _ (underscore),
scala> three(f _)
res49: Int = 6
scala> three(g _)
<console>:11: error: type mismatch;
found : () => Int => Int
required: Int => Int
three(g _)
^
Question 4: why does this happen? What's the usage of _(underline) in Scala?
why does this happen? I'm guessing that def maps to val.
def is a method (in JVM terms) so it doesn't make sense to assign it.
The parser is then confused and it ultimately tries to save the day by interpreting the assignment f = g as
val $ires6 = f
f = g
Both statements are illegal, so you get two errors:
you can't assign a method to a val without an explicit type annotation or a _ expansion - see below)
you can't reassign a val (in case you are wondering, $ires6 is a fresh val introduced by the REPL)
if I use val instead of var in declare g, are they equivalent? If not, what is the difference then?
The difference is that val cannot be reassigned (i.e. it's a constant reference), whereas var can (i.e. it's a mutable reference).
More on the subject here: What is the difference between a var and val definition in Scala?
does it mean (x: Int)Int is the same as Int => Int = ? If so, is there some situation that we should favor one over the other?
Methods and functions are not the same, although the compiler does its best to make you believe they are, through a transformation called eta-expansion. In some cases such transformation can be performed automatically, in some others you need to be explicit and trigger it with a trailing _.
In your specific example (passing a method where a function is expected) the expansion can been performed automatically.
You can read this Q/A for a more in-depth discussion about which style to prefer.
why does this happen? What's the usage of _(underline) in Scala?
The underscore (_) has many uses in scala, one of which is the one I mentioned before, i.e. triggering the eta expansion of a method into a function.
That's a special syntax for methods, so you simply can't apply it to a function, as it would make no sense.
That's why you can do f _ (which will turn the f method into a function), but you can't do g _ (since g it's already a function).
If I define a simple stringToInt function and store it as a val, everything works as expected, e.g.
scala> def stringToInt1: (String => Int) = _.toInt
stringToInt1: String => Int
scala> stringToInt1("1")
res0: Int = 1
However, if I then make that implicit, it causes a stack overflow:
scala> implicit def stringToInt2: (String => Int) = _.toInt
stringToInt2: String => Int
scala> stringToInt2("1")
java.lang.StackOverflowError
at .stringToInt2(<console>:7)
at $anonfun$stringToInt2$1.apply(<console>:7)
at $anonfun$stringToInt2$1.apply(<console>:7)
...
At first I suspected that this was because the underscore wasn't resolving to what I expected, but that's not the case, as this style of implicit val works fine for the following simple function:
scala> implicit def plusTwo: (Int => Int) = _ + 2
plusTwo: Int => Int
scala> plusTwo(2)
res2: Int = 4
If I define the parameter explicitly, no stack overflow:
scala> implicit def stringToInt3(s: String) = s.toInt
stringToInt3: (s: String)Int
scala> stringToInt3("1")
res3: Int = 1
(If trying this yourself and this last case stack overflows, restart the scala console and redo this last step)
So my question is, why is the original implicit not correctly resolving?
Edit
Ok digging a little deeper here, it seems that the problem is with the implicit conversion from String to StringOps. If we cut that out, it works fine:
scala> import scala.collection.immutable.StringOps
import scala.collection.immutable.StringOps
scala> implicit def stringToInt4: (String => Int) = new StringOps(_).toInt
stringToInt4: String => Int
scala> stringToInt4("1")
res4: Int = 1
But why would that implicit conversion be causing the issue?
Adding to the other replies.
There is no toInt method on String. Scala has to find an implicit conversion that will yield a type that has a toInt method.
Usually the StringOps conversion provides this toInt.
However Int has a toInt too, so scala finds your conversion from String => Int and decides that it has precedence over the StringOps conversion, thus applying it recursively.
This is why StringToInt4 works, as you explicitly tell the compiler what conversion you want. Maybe you could write it as: implicit def stringToInt5: (StringOps => Int) = _.toInt or check how implicits are resolved and how one takes precedence over the other.
Note what you are doing here:
scala> def stringToInt1: (String => Int) = _.toInt
stringToInt1: String => Int
You are defining a method (using def) that takes no parameters and returns a function from String to Int. Are you doing it this way on purpose, or is it just because you don't exactly understand the syntax?
You could have created a val instead:
val stringToInt1: (String => Int) = _.toInt
Now, stringToInt1 is a val that contains a function to convert String to Int.
With your stringToInt2, Scala is recursively applying the method. I don't know why it does that in the case of stringToInt2 but not with plusTwo.
Note that stringToInt3 is not the same thing as stringToInt1 and stringToInt2. It's a method that takes a String and returns an Int, not a method that takes no parameters and returns a function from String to Int.
Is there a syntax to allow generic type parameters on function literals? I know I could wrap it in a method such as:
def createLongStringFunction[T](): (T) => Boolean = {
(obj: T) => obj.toString.length > 7
}
but then I end up needing to invoke the method for every type T and getting a new function. I looked through the language reference, and while I see that the function literal syntax is translated by the compiler to an instance of a Functionn object that itself has generic input types, it looks like the compiler magic realizes those parameters at the time of creation. I haven't found any syntax that allows me to, in effect, "leave one or more of the type parameters of Functionn unbound". What I would prefer is something along the lines of:
// doesn't compile
val longStringFunction: [T](T) => Boolean = (obj: T) => obj.toString.length > 7
Does any such thing exist? Or for that matter, what is the explicit type of an eta-expansion function when the method being expanded has generic parameters?
This is a purely contrived and useless example. Of course I could just make the function use Any here.
No, type parameters only apply to methods and not function objects. For example,
def f[T](x: T) = x //> f: [T](x: T)T
val g = f _ //> g: Nothing => Nothing = <function1>
// g(2) // error
val h: Int=>Int = f _ //> h : Int => Int = <function2>
h(2) //> res0: Int = 2
The method f cannot be converted to a polymorphic function object g. As you can see, the inferred type of g is actually Function1[Nothing, Nothing], which is useless. However, with a type hint we can construct h: Function1[Int,Int] that works as expected for Int argument.
As you say, in your example all you're requiring is the toString method and so Any would be the usual solution. However, there is call for being able to use higher-rank types in situations such as applying a type constructor such as List to every element in a tuple.
As the other answers have mentioned, there's no direct support for this, but there's a relatively nice way to encode it:
trait ~>[A[_],B[_]] {
def apply[X](a : A[X]) : B[X]
}
type Id[A] = A //necessary hack
object newList extends (Id ~> List) {
def apply[X](a : Id[X]) = List(a)
}
def tupleize[A,B, F[_]](f : Id ~> F, a : A, b : B) = (f(a), f(b))
tupleize(newList, 1, "Hello") // (List(1), List(Hello))
Since longStringFunction defined as followed is a value, which must have some given type.
val longStringFunction: (T) => Boolean = (obj: T) => obj.toString.length > 7
However, you can reuse a function object with a method:
scala> val funObj: Any => Boolean = _.toString.size > 7
funObj: Any => Boolean = <function1>
scala> def typedFunction[T]: T => Boolean = funObj
typedFunction: [T]=> T => Boolean
scala> val f1 = typedFunction[String]
f1: String => Boolean = <function1>
scala> val f2 = typedFunction[Int]
f2: Int => Boolean = <function1>
scala> f1 eq f2
res0: Boolean = true
This works because trait Function1[-T1, +R] is contravariant of type T1.
In scala, Function values are parametrically monomorphic(while methods are polymorphic)
Shapeless library introduces polymorphic function values which may be mapped over HLists and many more other features.
Please consider the following refs:
http://www.chuusai.com/2012/04/27/shapeless-polymorphic-function-values-1/
http://www.chuusai.com/2012/05/10/shapeless-polymorphic-function-values-2/