0

I'm trying to write a function that returns another function based on a string input. I think I want matchfun("X") to be a (Double, Double) => Double:

def matchfun(foo: String) = {
    foo match {
        case "X" => (x: Double, y: Double) => x + y
        case "Y" => (x: Double) => x + 2
        case "Z" => (x: Double, y: Double) => x * y
    }
}
matchfun("X")
matchfun("X")(1,2)
matchfun: (foo: String)Object
res116: Object = <function2>
<console>:173: error: Object does not take parameters
       matchfun("X")(1,2)
                    ^
3
  • What are you trying to accomplish by returning different functions? They have different signatures, that's why you get Object that doesn't have apply() method. I need to understand your use case in order to change your code design. Commented May 12, 2017 at 20:13
  • @Oleksandr.Bezhan I'm trying to define a function that returns a deviance function for various distributions. foo here would represent the distribution family, and since distributions have different number of parameters their deviance functions have different domains. Commented May 12, 2017 at 20:23
  • do you need to have the specific signature? if you would have all functions with the same signature: e.g. (x: Seq[Double) => Double then you wouldn't have this issue Commented May 12, 2017 at 21:01

4 Answers 4

1

When foo is "X" your return a Function2[Double,Double,Double] when foo is "Y" you return a Function1[Double,Double] Object (anyref) is the most specific common supertype available. Change your code so that all branches return the same type (or at least a useful common supertype). In the case of returning functions that means you need to have the same number of parameters for each function.

Sign up to request clarification or add additional context in comments.

1 Comment

same number and types of parameters and the same return type.
0

You return functions that accept different inputs, so it's hard to push the input without knowing what parameters are needed. So instead of pushing the input, let the function pull the input on its own.

So we need some sort of source object, let's call it Point:

case class Point(x: Double, y: Double)

def matchfun(foo: String)(point: Point) = {
  foo match {
    case "X" => point.x + point.y
    case "Y" => point.x + 2
    case "Z" => point.x * point.y
  }
}

val point = Point(2, 5)
matchfun("X")(point) // 7.0
matchfun("Y")(point) // 4.0
matchfun("Z")(point) // 10.0

Comments

0

Try this:

trait A extends ((Int,Int) => Int) with (Int => Int)

class B extends A {
   def apply(a: Int, b: Int) = a + b
   def apply(a: Int) = a
}

val b = new B

b(1) // 1
b(2,3) // 5

Read about function type inheritance.

EDIT

to handle the case mentioned in the comment:

trait A extends ((Int,Int,String) => Int) with (Int => Int)

class B extends A {

  override def apply(a:Int,b:Int,x:String) = x match {
         case "add" => a+b
         case "mul" => a*b
  }
  override def apply(x:Int) = x
}

val b = new B
b(1) // 1
b(1,2,"add") // 3
b(1,2,"mul") // 2

2 Comments

I could also have another case where I want to map (x, y) to x * y so this wouldn't work.... will update OP to clarify
@kevinykuo check my edit. Not the neatest way but does the work.
0

Your problem is that you have to help the compiler, and all the branches in the "match" statement should return the same type. You break those constraints in the second case "Y", because you return a function Double=>Double and not a function (Double,Double)=>Double.

Help the compiler

def matchfun(foo: String):(Double,Double)=>Double = {
  foo match{
  case "X"=> (a,b)=> a+b
  case "Y"=> (a,b)=> a+2
  case "Z"=> (a,b)=> a*b
  }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.