从 scala 中部分应用的函数获取参数

发布于 2024-10-22 04:22:46 字数 403 浏览 0 评论 0原文

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

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

示例:

<代码> def doStuff(下:Int,上:Int,b:字符串)= for(turn <- 从下到上) println(turn +": "+b) 想象一下

,在某一时刻我知道“lower”参数,并且我得到了一个将其应用于“doStuff”的函数

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

我有办法拿回 3 吗? (为了举例,假设我在一个只接收“lowerDoStuff”的函数中,现在需要知道第一个参数)

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

Is there a way in scala to get the arguments back from a already partially applied function?

Does this even make sense, should be done, or fits into any use case?

example:


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

Imagine that at one point I know the 'lower' argument and I get a function of applying it to 'doStuff'


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

Is there a way for me to get that 3 back ?
(for the sake of example, imagine that I am inside a function which only received 'lowerDoStuff' and now needs to know the first argument)

Idiomatic scala is prefered to introspection/reflection (if possible).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

西瓜 2024-10-29 04:22:46

惯用的 Scala:不,你不能。您已经明确表示第一个论点不再相关。如果编译器可以让它完全消失,那就最好了:你说你有一个依赖于 int 和字符串的函数,并且你没有对生成它的内容做出任何承诺。如果您确实需要该值,但您也确实需要传递一个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 所在的地方——它消失在字节码中。甚至不再有包含该值的隐藏私有字段。

Idiomatic Scala: no, you can't. You have specifically said that the first argument is no longer relevant. If the compiler can make it disappear entirely, that's best: you say you have a function that depends on an int and a string, and you haven't made any promises about what generated it. If you really need that value, but you also really need to pass a 2-argument function, you can do it by hand:

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)

Now when you get the function later on, you can pattern match to see if it's a Function2From3, and then read the value:

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.")
}

(if it's important to you that it be an integer, you can remove A as a generic parameter and make _1 be an integer--and maybe just call it lower while you're at it).

Reflection: no, you can't (not in general). The compiler's smarter than that. The generated bytecode (if we wrap your code in class FuncApp) is:

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

Notice the iconst_3? That's where your 3 went--it disappeared into the bytecode. There's not even a hidden private field containing the value any more.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文