Scala :Returning a Function with variable argument from another function - scala

My requirement is to return a function from another function in scala which takes variable argument i.e while executing the returned function , i can pass multiple argument at runtime.
My code looks like :
object VarArgTest {
def getFunction(): (Map[String, String],Map[String, Any]*) => Any={
(arg:Map[String,String], arg2:Map[String,Any]*) => "random"//this gives compilation error
}
}
In code , i want to return a function which take , Map[String,String] as one argument ,while the other Map[String,Any] should be optional to it.
But i get compilation error in return statement as follow:
type mismatch; found : (Map[String,String], Map[String,Any]) required: (Map[String,String], Map[String,Any]*) ⇒ Any
Can anyone help , what have i missed here?
Note: My requirement is that returned function can take either one argument (Map[String,String]) or it can take two arguments max (Map[String,String], Map[String,Any])
Thanks

It's impossible to use varargs in anonymous function.
You can get your piece of code working by making the returned function nested instead of anonymous like this:
object VarArgTest {
def getFunction(): (Map[String, String],Map[String, Any]*) => Any = {
def nestedFunction(arg:Map[String,String], arg2:Map[String,Any]*) = "random"
nestedFunction
}
}
However since you don't need multiple instances of Map[String, Any] but either none or one, you would be better off using Option[Map[String, Any]], providing None when it is not needed.

Related

Scala how to reference a method that with an implicit parameter

The method have a implicit parameter can not be reference as argument ?
In my code ,i create a method that have a implicit parameter. Some time i just want to transfer it to other method . In this time Scala give me error. See below:
case class ComplicatedSalesTaxData(baseRate: Float,isTaxHoliday: Boolean)
def calcText(amount: Float,rate : (ComplicatedSalesTaxData) => Float ) : Float = amount * rate(ComplicatedSalesTaxData(0.06F,false))
def rate(implicit cstd:ComplicatedSalesTaxData) = {
if(cstd.isTaxHoliday)
cstd.baseRate
else
0.01F }
calcText(100F,rate) // will get error : could not find implicit value for parameter cstd: ComplicatedSalesTaxData
You have to say that you want to pass the parameter explicitly:
calcText(100F,rate(_))
The error message that you have posted says that the compiler cannot find an implicit ComplicatedSalesTaxData in the current scope. Therefore you have to define one.
Then the call should look like this calcText(100F,rate(_)) instead of the wildcard _ you can also pass the value explictely.

Trying to skip implicit parameter list

I'd like to call a function returned by a function with an implicit parameter, simply and elegantly. This doesn't work:
def resolveA(implicit a: A): String => String = { prefix =>
s"$prefix a=$a"
}
case class A(n: Int)
implicit val a = A(1)
println(resolveA("-->")) // won't compile
I've figured out what's going on: Scala sees the ("-->") and thinks it's an attempt to explicitly fill in the implicit parameter list. I want to pass that as the prefix argument, but Scala sees it as the a argument.
I've tried some alternatives, like putting an empty parameter list () before the implicit one, but so far I've always been stopped by the fact that Scala thinks the argument to the returned function is an attempt to fill in the implicit parameter list of resolveA.
What's a nice way to do what I'm trying to do here, even if it's not as nice as the syntax I tried above?
Another option would be to use the apply method of the String => String function returned by resolveA. This way the compiler won't confuse the parameter lists, and is a little shorter than writing implicltly[A].
scala> resolveA[A].apply("-->")
res3: String = --> a=A(1)

Right associative functions with two parameter list

I was looking at the FoldLeft and FoldRight methods and the operator version of the method was extremely peculiar which was something like this (0 /: List.range(1,10))(+).
For right associative functions with two parameter lists one would expect the syntax to be something like this((param1)(param2) op HostClass).
But here in this case it is of the syntax (param1 op HostClass)(param2). This causes ambiguity with another case where a right associative function returns another function that takes a single parameter.
Because of this ambiguity the class compiles but fails when the function call is made as shown below.
class Test() {
val func1:(String => String) = { (in) => in * 2 }
def `test:`(x:String) = { println(x); func1 }
def `test:`(x:String)(y:String) = { x+" "+y }
}
val test = new Test
(("Foo") `test:` test)("hello")
<console>:10: error: ambiguous reference to overloaded definition,
both method test: in class Test of type (x: String)(y: String)String
and method test: in class Test of type (x: String)String => String
match argument types (String)
(("Foo") `test:` test)("hello")
so my questions are
Is this an expected behaviour or is it a bug?
Why the two parameter list right associative function call has been designed the way it is, instead of what I think to be more intuitive syntax of ((param1)(param2) op HostClass)?
Is there a workaround to call either of the overloaded test: function without ambiguity.
The Scala's Type System considers only the first parameter list of the function for type inference. Hence to uniquely identify one of the overloaded method in a class or object the first parameter list of the method has to be distinct for each of the overloaded definition. This can be demonstrated by the following example.
object Test {
def test(x:String)(y:Int) = { x+" "+y.toString() }
def test(x:String)(y:String) = { x+" "+y }
}
Test.test("Hello")(1)
<console>:9: error: ambiguous reference to overloaded definition,
both method test in object Test of type (x: String)(y: String)String
and method test in object Test of type (x: String)(y: Int)String
match argument types (String)
Test.test("Hello")(1)
Does it really fail at runtime? When I tested it, the class compiles, but the call of the method test: does not.
I think that the problem is not with the operator syntax, but with the fact that you have two overloaded functions, one with just one and the other with two parameter lists.
You will get the same error with the dot-notation:
test.`test:`("Foo")("hello")
If you rename the one-param list function, the ambiguity will be gone and
(("Foo") `test:` test)("hello")
will compile.

Why in Scala function defined without empty parentheses doesn't behave like function?

Consider the following 2 objects
object TestObj1 {
def testMethod = "Some text"
}
object TestObj2 {
def testMethod() = "Some text"
}
and if I call those methods directly, they do what I expect
scala> TestObj1.testMethod
res1: String = Some text
scala> TestObj2.testMethod
res2: String = Some text
But now if we define following function
def functionTakingFunction(callback: () => String) {
println("Call returns: " + callback())
}
and try to call it, the method defined without () is not accepted.
scala> functionTakingFunction(TestObj1.testMethod)
<console>:10: error: type mismatch;
found : String
required: () => String
functionTakingFunction(TestObj1.testMethod)
^
scala> functionTakingFunction(TestObj2.testMethod)
Call returns: Some text
I also noticed that you can't call the TestObj1.testMethod using parentheses, since it already is a String. But what is causing this behavior?
You are not passing the method, you're invoking it and then passing its result into the call.
If you want to pass the method, you first have to convert it into a function, and pass that:
functionTakingFunction(TestObj1.testMethod _)
Here the testMethod is converted into a partially applied function (said to be "tied").
The reason you have to do that is because TestObj1.testMethod does not evaluate to function0 (which is what need to be passed to functionTakingFunction), but to a String because of the way it is declared (without parentheses).
It works on TestObj2 because the testMethod is defined with parentheses and thus just typing TestObj2.testMethod does not invoke it.
functionTakingFunction(TestObj1.testFunction) is called as functionTakingFunction("Some text") - it is evaluated rather than passed
Here, you are not passing the function. What you are trying to do is evaluate TestObj1.testFunction and then pass that result to functionTakingFunction
But if you see the definition of functionTakingFunction, it says clearly
def functionTakingFunction(callback: () => String)
means this function expects a function with Return Type as Unit. But TestObj1.testFunction is having no return type.
The difference between Unit Return Type and No Return Type is:
No Return Type means this method will not return anything
Unit Return Type means this method will return something which is having no meaningful value.
Hope it helps you now. Happy coding and enjoy Scala.

When is a scala partial function not a partial function?

While creating a map of String to partial functions I ran into unexpected behavior. When I create a partial function as a map element it works fine. When I allocate to a val it invokes instead. Trying to invoke the check generates an error. Is this expected? Am I doing something dumb? Comment out the check() to see the invocation. I am using scala 2.7.7
def PartialFunctionProblem() = {
def dream()() = {
println("~Dream~");
new Exception().printStackTrace()
}
val map = scala.collection.mutable.HashMap[String,()=>Unit]()
map("dream") = dream() // partial function
map("dream")() // invokes as expected
val check = dream() // unexpected invocation
check() // error: check of type Unit does not take parameters
}
For convenience, Scala lets you omit empty parens when calling a method, but it's clever enough to see that the expected type in the first case is ()=>Unit, so it doesn't remove all the parens for you; instead, it converts the method into a function for you.
In the val check case, however, it looks just like a function call result getting assigned to a variable. In fact, all three of these do the exact same thing:
val check = dream
val check = dream()
val check = dream()()
If you want to turn the method into a function, you place _ after the method in place of the argument list(s). Thus,
val check = dream() _
will do what you want.
Well, the problem is that you got it all wrong. :-)
Here are some conceptual mistakes:
def dream()() = {
println("~Dream~");
new Exception().printStackTrace()
}
This is not a partial function. This is a curried method with two empty parameter lists which returns Unit.
val map = scala.collection.mutable.HashMap[String,()=>Unit]()
The type of the values in this map is not partial function, but function. Specifically, Function0[Unit]. A partial function would have type PartialFunction[T, R].
map("dream") = dream() // partial function
What happens here is that Scala converts the partially applied method into a function. This is not a simple assignment. Scala does the conversion because the type inferencer can guess the correct type.
val check = dream() // unexpected invocation
Here there's no expected type to help the type inferencer. However, empty parameter lists can be ommitted, so this is just a method call.