【问题标题】:Implicit conversions, type parameters, overloading, and anonymous functions syntax隐式转换、类型参数、重载和匿名函数语法
【发布时间】:2016-03-17 06:09:45
【问题描述】:

所以,我试图用这样的东西“拉皮条”我的Futures(除其他外):

implicit class Pimp[T](val x: T) extends AnyVal  {
  def ->>[R](f: T => R): R = f(x)
  def ->>[R](r: => R): R = r
  def <<-(f: T => Unit): T = f.andThen(_ => x).apply(x)
  def <<-(f: => Unit): T = <<- { _ => f }
}

由于某种原因,当我现在尝试这样做时:

Future(1) ->> { Await.result(_, 1 seconds) }

error: missing parameter type for expanded function ((x$1) =&gt; Await.result(x$1, 1.seconds)) 失败

但这有效:

Future(1) <<- { Await.result(_, 1 seconds) }

所以,问题是第一种情况有什么问题。我做错了什么,以及如何使它工作。 我什至试过这个(根本不是我想要的,因为它太冗长了):Future(1) --&gt; { case x: Future[Int] =&gt; Awayt.result(_, 1 seconds) },但即使这样也由于某种原因失败了(仍然说参数类型未知 - 如果我明确指定它怎么会未知???)

我怀疑,第一种情况和第二种情况的区别在于-&gt;&gt; 有一个类型参数,而&lt;&lt;- 没有......但即使这个Future(1) -&gt;&gt;[Int] { Await.result(_, 1 seconds) } 仍然不起作用:(

更新好的,所以,我找到了一种工作方式:

Future(1) ->> { (f:Future[Int]) => Await.result(f, 1 seconds) }

这有点违背了我隐含的目的,因为它是多么冗长:( 有没有办法让它推断出参数类型而不像在其他情况下那样拼写出来?

更新 2 还有一件事。从Pimp 中删除-&gt;&gt; 的重载“风味”使其他情况起作用。即,如果我只离开

def ->>[R](f: T => R): R = f(x)

Pimp的定义中,那么

Future(1) ->> { Await.result(_, 1 seconds) }

按预期完美运行。

我想了一会儿,问题是在重载的情况下foo -&gt;&gt; { _ =&gt; bar } 是模棱两可的:它可能意味着“返回 bar”或“返回函数 foo => bar”。然而,这并不能解释为什么 foo -&gt;&gt;[Bar] { _ =&gt; bar } 不起作用。

【问题讨论】:

  • Future(1) -&gt;&gt; {f =&gt; Await.result(f, 1 seconds) } 是正确的,但类型推断无法处理。
  • 令我惊讶的是&lt;&lt;- 有效;在评论中留下我的理解,因为它显然不完整:因为有重载,没有单一的“预期类型”,所以参数{ Await.result(_, 1 seconds) } 需要自行检查类型在选择重载之前和在这种情况下,它显然不知道参数类型。
  • @AlexeyRomanov 对,但是 -&gt;&gt;[Int] 应该可以工作,因为预期的类型是明确的,不是吗?
  • 查看更新后的答案。
  • @AlexeyRomanov 就在我头顶飞过 :) 但无论哪种方式,我都不想争论,这不是根据规范实现的......我更像是“为什么规范不是允许它在这样的情况下推断类型,当它清楚应该是什么时”:) FWIW,我希望-&gt;&gt;[Int] 应该让它像没有重载一样工作......

标签: scala implicit-conversion implicit implicits


【解决方案1】:

您可以缩短通话至Future(1) -&gt;&gt; { Await.result(_: Future[Int], 1 seconds) }。不完美,但比您的 Update 1 更好。更好的是避免在“拉皮条”方法中重载:不出所料,它会使类型推断复杂化。

仔细阅读http://www.scala-lang.org/files/archive/spec/2.11/06-expressions.html后,似乎指定[Int] 不应该工作:

  1. 整个表达式是一个函数应用程序 (6.6)。

  2. 由于Future(1).-&gt;&gt; 超载,我们转到6.23。

    1. 备选集A是-&gt;&gt;引用的成员集;不考虑[Int],因为该部分谈到“标识符或选择e”,而选择是Future(1).-&gt;&gt;

    2. shape({ Await.result(_, 1 seconds) })Any =&gt; Nothing

    3. “令 B 为 A 中适用于类型 (shape(e1),...,shape(en)) 的表达式 (e1,...,en) 的备选集”。 A中的两种方法适用于Any =&gt; Nothing(正如你所说,“它可能意味着“返回bar”或“返回函数foo => bar”)。所以我们去“否则,让 S1,...,Sm 是通过将每个参数键入一个未定义的预期类型而获得的类型向量”,并且这种键入失败。

    4. 对于&lt;&lt;- 的情况,=&gt; Unit 不适用(因为预期的类型不是Unit在这一步,不会发生值丢弃)。 p>

但这很微妙,以至于我在编写此更新时两次改变了主意;我认为我现在明白了。

【讨论】:

  • 是的,我正在删除重载,似乎它是“较小的邪恶”,但不幸的是:我的意图是避免输入像 doSomething() -&gt;&gt; { _ =&gt; "Success" } 这样的东西,而只支持 doSomething() -&gt;&gt; "Success" :(
猜你喜欢
  • 2021-01-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-11
  • 1970-01-01
  • 2014-05-22
  • 1970-01-01
相关资源
最近更新 更多