简体   繁体   English

我的函数的扩展函数缺少参数类型; 不是另一个有相同签名的人

[英]missing parameter type for expanded function for my function; not for another with same signature

Short form : I have a method with the same signature as Future.recover . 简短形式 :我有一个与Future.recover具有相同签名的方法。 Passing a partial function to Future 's version works. 将部分函数传递给Future的版本。 Passing the same PF to my version results in a missing parameter type for expanded function. The argument types of an anonymous function must be fully known. (SLS 8.5) 将相同的PF传递给我的版本会导致missing parameter type for expanded function. The argument types of an anonymous function must be fully known. (SLS 8.5) missing parameter type for expanded function. The argument types of an anonymous function must be fully known. (SLS 8.5) missing parameter type for expanded function. The argument types of an anonymous function must be fully known. (SLS 8.5) error. missing parameter type for expanded function. The argument types of an anonymous function must be fully known. (SLS 8.5)错误。 What's the difference? 有什么不同?

Longer form : I'm trying to implement the TracingFuture class discussed here in an attempt to trace errors across future boundaries. 更长的形式 :我正在尝试实现此处讨论的TracingFuture类,以尝试跟踪未来边界的错误。 The basic technique is to wrap the Future in another class, TracingFuture , while adding a pseudo-stacktrace. 基本技术是将Future包装在另一个类TracingFuture ,同时添加伪TracingFuture

The code given in the blog post is missing the recover method from Future , so I've added it with the same signature: 博客文章中给出的代码缺少Futurerecover方法,所以我添加了相同的签名:

class TracingFuture[+T](underlying: Future[T], val trace: Vector[FutureTraceElement]) extends Future[T] {

  def recover[U >: T](pf: PartialFunction[Throwable, U]
                     )(implicit ec: ExecutionContext, enclosing: sourcecode.Enclosing, file: sourcecode.File,
                       line: sourcecode.Line): TracingFuture[U] = {
    val recovered = underlying.recover(pf)
    new TracingFuture[U](recovered, trace :+ FutureTraceElement(enclosing.value, "recover", file.value, line.value))

  }

}

For comparison, here's the equivalent chunk of code out of Future . 为了比较,这里是Future的等效代码块。 Note that aside from the extra implicit parameters the signatures are the same. 请注意,除了额外的隐式参数外,签名是相同的。

trait Future[+T] extends Awaitable[T] {

  def recover[U >: T](pf: PartialFunction[Throwable, U])(implicit executor: ExecutionContext): Future[U] =
    transform { _ recover pf }
}

Finally, my code that produces the compile error: 最后,我的代码产生编译错误:

val x: TracingFuture[Vector[Maintainer]] = ... // code producing a TracingFuture
val fMaintainers = x.recover {
  case err: Throwable ⇒
    logger.error("Failed to get list of user maintainers.", err)
    Vector.empty[Maintainer]
}

And the error message: 并且错误消息:

[error] /Users/bwbecker/oat/src/oat3/modules/wapp/app/oat/wapp/dao/CronJobDAO.scala:273: missing parameter type for expanded function
[error] The argument types of an anonymous function must be fully known. (SLS 8.5)
[error] Expected type was: ?
[error]     val fMaintainers = x.recover {
[error]                                  ^

Once again, this code works with the Future.recover but I get a compile error with TracingFuture.recover . 再次,这个代码工作与Future.recover ,但我得到一个编译错误TracingFuture.recover I don't understand why. 我不明白为什么。

This SO question explains that the compiler knows the argument to the partial function must be a supertype of T but can't guarantee that. 这个SO问题解释了编译器知道部分函数的参数必须是T的超类型但不能保证。 But why doesn't it run into that issue with Future.recover ? 但是为什么它与Future.recover不会遇到这个问题呢?

And, of course, I'd like to know if there's anything I do about it other than rewriting the anonymous partial function to make the types explicit. 当然,除了重写匿名部分函数以使类型显式化之外,我想知道是否有任何关于它的事情。

The problem is that TracingFuture has two overloaded recover methods: the one you added and the one you inherited from Future . 问题是TracingFuture有两个重载的recover方法:你添加的方法和你从Future继承的方法。 When you only have one, it provides the expected type which is crucial for type inference, but with overloaded methods it doesn't work, as you see from Expected type was: ? 当你只有一个时,它提供了对类型推断至关重要的预期类型,但是使用重载方法它不起作用,正如你在Expected type was: ?看到的那样Expected type was: ? .

You may think the compiler should notice types of function parameters are the same and so can still provide the expected type. 您可能认为编译器应该注意到函数参数的类型是相同的,因此仍然可以提供预期的类型。 And you would be right, but it was only fixed in Scala 2.12 . 你会是对的,但它只在Scala 2.12中得到修复

Of course, then you'll run into trouble that the compiler has no way to tell which overload you want when only the implicit arguments are different. 当然,那么当遇到隐式参数不同时,编译器无法告诉您需要哪个重载会遇到麻烦。

Try to replace 尝试更换

val fMaintainers = x.recover {
  case err: Throwable ⇒
    logger.error("Failed to get list of user maintainers.", err)
    Vector.empty[Maintainer]
}

with

val fMaintainers = x.recover(PartialFunction[Throwable, Vector[Maintainer]] { 
  case err: Throwable ⇒
    logger.error("Failed to get list of user maintainers.", err)
    Vector.empty[Maintainer]
})

Why do I get a "missing parameter for expanded function" in one case and not the other? 为什么我在一个案例中获得“扩展函数的缺失参数”而不是另一个案例?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM