【问题标题】:Get arguments back from partially applied function in scala从scala中的部分应用函数获取参数
【发布时间】:2011-03-16 17:16:57
【问题描述】:

在 scala 中有没有办法从已经部分应用的函数中取回参数?

这是否有意义、应该这样做或适合任何用例?

示例:

def doStuff(lower:Int,upper:Int,b:String)= for(turn <- lower to upper) println(turn +": "+b)

想象一下,有一次我知道“lower”参数,并获得了将其应用于“doStuff”的函数

val lowerDoStuff = doStuff(3,_:Int,_:String)

有没有办法让我把那 3 拿回来? (举例来说,假设我在一个只收到“lowerDoStuff”的函数中,现在需要知道第一个参数)

惯用的 scala 优于自省/反思(如果可能的话)。

【问题讨论】:

  • 我认为如果你需要这样做,那么需要更改以 lowerDoStuff 作为参数的函数的参数。如果一个函数将(Int, String) =&gt; Unit 作为其参数类型,那么该类型的 any 函数应该是一个合适的参数。除了由其类型声明的参数之外,您不能安全地对参数做出任何其他假设。

标签: scala currying partial-application


【解决方案1】:

惯用的 Scala: 不,你不能。您已明确表示第一个论点不再相关。如果编译器可以让它完全消失,那是最好的:你说你有一个依赖于 int 和 string 的函数,而你没有对生成它的内容做出任何承诺。如果你真的需要那个值,但你也真的需要传递一个 2 参数函数,你可以手动完成:

class Function2From3[A,B,C,Z](f: (A,B,C) => Z, val _1: A) extends Function2[B,C,Z] {
  def apply(b: B, c: C) = f(_1, b, c)
}
val lowerDoStuff = new Function2From3(doStuff _, 3)

现在当你稍后获取函数时,你可以进行模式匹配以查看它是否是 Function2From3,然后读取值:

val f: Function2[Int,String,Unit] = lowerDoStuff
f match {
  case g: Function2From3[_,_,_,_] => println("I know there's a "+g._1+" in there!")
  case _ => println("It's all Greek to me.")
}

(如果它是一个整数对您很重要,您可以将A 作为一个通用参数删除,并使_1 成为一个整数——也许在您使用它的时候直接调用它lower) .

反思:不,你不能(一般情况下)。编译器比这更聪明。生成的字节码(如果我们将您的代码包装在class FuncApp 中)是:

public final void apply(int, java.lang.String);
  Signature: (ILjava/lang/String;)V
  Code:
   0:   aload_0
   1:   getfield    #18; //Field $outer:LFuncApp;
   4:   iconst_3
   5:   iload_1
   6:   aload_2
   7:   invokevirtual   #24; //Method FuncApp.doStuff:(IILjava/lang/String;)V
   10:  return

注意到iconst_3了吗?那就是你的 3 去的地方——它消失在字节码中。甚至没有隐藏的私有字段包含该值。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-31
    • 1970-01-01
    • 1970-01-01
    • 2013-10-04
    • 2011-12-02
    相关资源
    最近更新 更多