【问题标题】:Issue with applying partially-applied functions in-line内联应用部分应用函数的问题
【发布时间】:2013-10-03 20:42:39
【问题描述】:

作为 Scala 的新手,我在 sbt 控制台上玩弄部分应用的函数语法。我遇到了一个非常奇怪的问题,我不理解 Scala 的行为。

这个例子是人为的,在现实中不太可能遇到。就是说,就是这样。假设我定义了以下函数:

scala> def f(x: Int, y: Int) = "%d %d".format(x, y)

现在如果我输入

scala> f(1, _:Int)(2)
res: Int => Char = <function1>

结果是一个Int =&gt; Char 函数,这很不寻常。换句话说,Scala 在应用参数(即 2)时(暂时)将 f(1, _:Int) 视为字符串(相对于其实际类型:Int =&gt; String)。

如果使用括号,我期望发生的事情发生:

scala> (f(1, _:Int))(2)
res: String = 1 2

但是,这似乎不是操作顺序问题,因为我找不到添加括号以实现意外行为的方法(即,结果为 Int =&gt; Char 类型)。

有什么想法吗?

【问题讨论】:

  • 这让我很吃惊,并且似乎与我对language specification 的第 6.23 节的阅读不一致,后者说下划线受包含它的最小表达式的约束。

标签: scala


【解决方案1】:

首先关于结果类型:

scala> f(1, _:Int)(2)
res: Int => Char = <function1>

看看这个:

scala> val str = "hello"
str: String = hello

scala> str(2)
res12: Char = l

我认为这很清楚。

对函数本身不,因为它也很容易。当您将其提升到带有下划线的函数时,您不仅提升了f,而且还提升了对字符串的调用(2)(第一个结果),这就是您得到的原因:

res: Int => Char = <function1>

已添加

更明确的版本。您的函数f 的类型为(Int, Int) =&gt; String,当您编写f(1, _: Int) 时,您将其部分应用于参数一并返回Int =&gt; String 类型的函数,其中Int 是第二个参数。然后你的参数(2) 调用来自函数Int =&gt; String 的结果字符串上的apply 方法,它返回一个Char,从这里你得到Int =&gt; Char 类型的函数,其中Int 是你的第二个参数f 函数和 Char 是结果字符串中的一个字符

在第二种情况下,你有:

scala> (f(1, _:Int))(2)
res: String = 1 2

通过括号,您将其拆分为多个事物,第一个是函数Int =&gt; String(2) 调用此函数,您将参数2 传递给此函数Int =&gt; String

val ff = f(1, _: Int)
val res = ff(2)

【讨论】:

  • 所以我明白为什么如果f(1, _:Int) 是一个字符串,f(1, _:Int)(2) 将是一个Char。但是,我不明白为什么f(1, _:Int) 被视为一个字符串,而它的类型是Int =&gt; Char
  • @bacchuswng 你自己写的:def f(x: Int, y: Int) = "%d %d".format(x, y) f 接受两个整数并返回一个字符串
  • @bacchuswng 我已经更新了答案,以便在这一刻更清楚
  • 感谢您的解释。
  • 这对我来说似乎仍然违反直觉,为什么当在 f(1, _: Int) 的结果上调用 apply(2) 时,Scala 将其视为 apply(2) 在应用 String 结果上的 f(1, _: Int)Int =&gt; String 本身的 f(1, _: Int) 结果。也许我只需要接受 Scala 就是这样的:)。
猜你喜欢
  • 1970-01-01
  • 2019-05-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-08
相关资源
最近更新 更多