隐式参数将无法应用.如何隐藏提取器中无处不在的参数? [英] Implicit parameters won't work on unapply. How to hide ubiquitous parameters from extractors?

查看:99
本文介绍了隐式参数将无法应用.如何隐藏提取器中无处不在的参数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

显然,提取器对象中的unapply/unapplySeq不支持隐式参数.假设这里有一个有趣的参数a和一个令人烦恼的无处不在的参数b,在提取c时可以很好地隐藏起来.

Apparently unapply/unapplySeq in extractor objects do not support implicit parameters. Assuming here an interesting parameter a, and a disturbingly ubiquitous parameter b that would be nice to hide away, when extracting c.

[ EDIT ]:在我的intellij/scala-plugin安装中似乎出现了问题,导致了此问题.我无法解释.最近,我的intellij遇到了许多奇怪的问题.重新安装后,我将无法再处理我的问题.确认unapply/unapplySeq确实允许使用隐式参数!感谢您的帮助.

[EDIT]: It appears something was broken in my intellij/scala-plugin installation that caused this. I cannot explain. I was having numerous strange problems with my intellij lately. After reinstalling, I can no longer reprodce my problem. Confirmed that unapply/unapplySeq do allow for implicit parameters! Thanks for your help.

这不起作用(**编辑:是,确实如此):**

This does not work (**EDIT:yes, it does):**

trait A; trait C; trait B { def getC(a: A): C }

def unapply(a:A)(implicit b:B):Option[C] = Option(b.getC(a))

在我对理想的提取器应该是什么样的理解中(Java的人也从直觉上清楚了意图)的理解中,此限制基本上禁止依赖于附加参数的提取器对象.

In my understanding of what an ideal extractor should be like, in which the intention is intuitively clear also to Java folks, this limitation basically forbids extractor objects which depend on additional parameter(s).

您通常如何处理此限制?

到目前为止,我已经有了四种可能的解决方案:

So far I've got those four possible solutions:

1)我要改进的最简单的解决方案:不要隐藏b,将参数b和a一起提供,以元组形式作为unapply的普通参数:

1) The simplest solution that I want to improve on: don't hide b, provide parameter b along with a, as normal parameter of unapply in form of a tuple:

object A1{ 
    def unapply(a:(A,B)):Option[C] = Option(a._2.getC(a._1)) }

在客户代码中:

 val c1 = (a,b) match { case A1(c) => c1 }

我不喜欢它,因为有更多的噪声使a分解为c在这里很重要.另外,由于必须说服Java实际使用此Scala代码的Java人员面临着另一种新的语法新颖性(元组大括号).他们可能会受到反斯卡拉侵略的攻击这是什么?……为什么不首先使用常规方法并进行检查呢?".

I don't like it because there is more noise deviating that deconstruction of a into c is important here. Also since java folks, that have to be convinced to actually use this scala code, are confronted with one additional synthactic novelty (the tuple braces). They might get anti-scala aggressions "What's all this? ... Why then not use a normal method in the first place and check with if?".

2)在封装依赖于特定B的类的类中定义提取器,然后导入该实例的提取器.在导入站点上,对于Java程序员来说有点不寻常,但是在模式匹配站点中,b被很好地隐藏了,并且直观地表明会发生什么.我的最爱.我错过了一些劣势吗?

2) define extractors within a class encapsulating the dependence on a particular B, import extractors of that instance. At import site a bit unusual for java folks, but at pattern match site b is hidden nicely and it is intuitively evident what happens. My favorite. Some disadvantage I missed?

class BDependent(b:B){ 
   object A2{ 
    def unapply(a:A):Option[C] = Option(b.getC(a))
         } }

在客户端代码中的用法:

usage in client code:

val bDeps = new BDependent(someB)
import bDeps.A2 
val a:A = ...
val c2 = a match { case A2(c) => c }
}

3)在客户端代码范围内声明提取器对象. b是隐藏的,因为它可以在本地范围内使用"b".阻碍代码的重用,严重污染了客户端代码(此外,必须在使用代码之前声明它).

3) declare extractor objects in scope of client code. b is hidden, since it can use a "b" in local scope. Hampers code reuse, heavily pollutes client code (additionally, it has to be stated before code using it).

4)具有未应用的函数B => C的Option选项.这允许导入和使用依赖于参数的提取器,而无需直接向提取器提供b,而是在使用时将其提供给结果. Java人士可能对函数值的使用感到困惑,但b并未隐藏:

4) have unapply return Option of function B => C. This allows import and usage of an ubitious-parameter-dependent extractor, without providing b directly to the extractor, but instead to the result when used. Java folks maybe confused by usage of function values, b not hidden:

 object A4{
  def unapply[A,C](a:A):Option[B => C] = Option((_:B).getC(a))
   }

然后输入客户代码:

 val b:B = ...
 val soonAC: B => C = a match { case A4(x) => x }
 val d = soonAC(b).getD ...

更多评论:

  • 按照此答案中的建议,查看范围"可能有助于获取提取器使用隐式转换,但这对隐式参数没有帮助.出于某种原因,我宁愿不使用隐式转换来解决.
  • 查看了上下文范围",但它们似乎有相同的限制,不是吗?
  • As suggested in this answer, "view bounds" may help to get extractors work with implicit conversions, but this doesn't help with implicit parameters. For some reason I prefer not to workaround with implicit conversions.
  • looked into "context bounds", but they seem to have the same limitation, don't they?

推荐答案

第一行代码在什么意义上不起作用?当然,对于提取器方法的隐式参数列表没有任意禁止.

In what sense does your first line of code not work? There's certainly no arbitrary prohibition on implicit parameter lists for extractor methods.

请考虑以下设置(我使用的是普通的旧类,而不是case类,以表明这里没有发生额外的魔术):

Consider the following setup (I'm using plain old classes instead of case classes to show that there's no extra magic happening here):

class A(val i: Int)
class C(val x: String)
class B(pre: String) { def getC(a: A) = new C(pre + a.i.toString) }

现在,我们定义一个隐式的B值,并使用您的unapply方法创建一个提取器对象:

Now we define an implicit B value and create an extractor object with your unapply method:

implicit val b = new B("prefix: ")

object D {
  def unapply(a: A)(implicit b: B): Option[C] = Option(b getC a)
}

我们可以这样使用:

scala> val D(c) = new A(42)
c: C = C@52394fb3

scala> c.x
res0: String = prefix: 42

完全符合我们的预期.我不明白为什么您需要这里的解决方法.

Exactly as we'd expect. I don't see why you need a workaround here.

这篇关于隐式参数将无法应用.如何隐藏提取器中无处不在的参数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆