在scala中是否有办法从已经部分应用的函数中获取参数?
这是否有意义,应该完成,还是适合任何用例?
示例:
def doStuff(lower:Int,upper:Int,b:String)=
for(turn <- lower to upper) println(turn +": "+b)
想象一下,我一度知道'较低'的论点,我得到了将它应用于'doStuff'的功能
val lowerDoStuff = doStuff(3,_:Int,_:String)
我有办法让那3回来吗? (为了举例,假设我在一个只收到'lowerDoStuff'的函数里面,现在需要知道第一个参数)
习惯性scala更倾向于内省/反思(如果可能的话)。
答案 0 :(得分:7)
惯用斯卡拉:不,你不能。你已经明确地说第一个论点不再相关了。如果编译器可以使它完全消失,那就是最好的:你说你有一个依赖于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去了 - 它消失在字节码中。甚至没有隐藏的私有字段包含该值。