【问题标题】:Scala Case Class with Different Argument Types具有不同参数类型的 Scala 案例类
【发布时间】:2014-11-28 17:00:50
【问题描述】:

我想编写一个案例类,它可以接收一个具有一个或多个 Ints 作为其参数的函数。例如,这些是有效的函数:

def foo(x: Int): String = "foo"
def bar(x: Int, y: Int): String = "bar"
def foobar(x: Int, y: Int, z: Int): String = "foobar"

但这不会:

def nonExample():String = "no"

问题是我无法为我的案例类获取正确的参数类型。

case class Mine(function: ???) {}

我试过了:

case class Mine(function: (Int*) => String)

这不起作用,因为 (Int*) 是 Ints 的序列。我也尝试过使用 Function 和 Function1,但这也不起作用。任何想法(或替代方案,如果这在 Scala 中是不可能的)?

编辑: 正如 Didier Dupont 所提到的,Mine 还需要知道该方法需要多少个参数。上面我过度简化了Mine。它还将接受另一个参数来说明传入的函数。基于此,它将决定将多少个参数传递给函数。但除了那段代码之外,Mine 中的其他所有内容都与功能无关。

【问题讨论】:

  • 我的第一个想法是这是不可能的,但 Scala 总是让我感到惊讶。 :)
  • 顺便说一句,方法不能传递,函数可以。
  • 那你打算怎么使用Mine类呢?由于您不知道该方法需要多少参数,因此很难调用它。
  • case 类通常意味着比任何东西都更有价值的容器,一个完美的例子是Either 类型。它有LeftRight 作为它的可能值,每个值只应该包含一个值。与自身具有多个单参数版本的事物进行模式匹配没有多大意义,因为在擦除后它们最终看起来都一样

标签: scala


【解决方案1】:

我会推荐下一个解决方案(它有一些缺点,但总的来说它可以满足您的需求)

sealed trait FuncRes[F] {
  def resolve : F
}

object FuncRes {
  implicit def func1[T1, R](f : T1 => R) = 
    new FuncRes[(T1 => R)] {
      def resolve = f
    }

  implicit def func2[T1, T2, R](f : (T1, T2) => R) =
    new FuncRes[((T1, T2) => R)] {
      def resolve = f
    }

  implicit def func3[T1, T2, T3, R](f : (T1, T2, T3) => R) = 
    new FuncRes[((T1, T2, T3) => R)] {
      def resolve = f
    }
}

case class Mine[F](private val f : FuncRes[F]) {
  def func[F] = f.resolve
}

及用法示例:

def foo(x: Int): String = "foo"
def bar(x: Int, y: Int): String = "bar"
def foobar(x: Int, y: Int, z: Int): String = "foobar"

val m1 = Mine(foo _)
println { m1.func(10) }              // output: "foo"

val m2 = Mine(bar _)
println { m2.func(10, 20) }          // output: "bar"

val m3 = Mine(foobar _) 
println { m3.func(10, 20, 30) }     // output: "foobar"

【讨论】:

  • 这是一个有趣的解决方案,Yury。其他感兴趣的人请注意:使用 FuncRes,这就是您将 foo、bar 和 foobar 实际传递到 Mine 的方式:val m1 = Mine(FuncRes.func1(foo)),等等。
【解决方案2】:

(Int, Int*) => String 怎么样?您将收到作为Seq[Int] 的第二个参数。

【讨论】:

  • 不幸的是,这不起作用。我在 repl 中尝试过,对于 foo、bar 和 foobar,所有类型都不匹配。
【解决方案3】:

为什么不使用函数Array[Int] => String? Varargs 本质上是数组,所以它应该适合。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多