在Scala中转义下划线以实现与Java的互操作性

18

假设我有一些Scala代码调用了使用_作为标识符的Java库(确实如此——这是一个漫长的故事)。下面是一个简化的示例:

public class StupidUnderscore {
  public static String _() { return "Please give me a real name!"; }
}

没问题,对吧?只需转义它:

scala> StupidUnderscore.`_`
res0: String = Please give me a real name!

一直以来都能正常运行,但我今天尝试升级到Scala 2.10.2后出了问题:

scala> StupidUnderscore.`_`
<console>:1: error: wildcard invalid as backquoted identifier
       StupidUnderscore.`_`
                        ^
这是因为2.10.1中出现了一个更改,修复了这个问题。从提交信息中可以看到:

禁止将_用作标识符,它只会带来不良影响。

好吧,但我不知道为什么这意味着我不能转义它——我以为这就是反引号的作用。

我是否需要编写Java包装器才能让其正常工作?还有其他办法可以在Scala中引用Java库的_方法吗?


作为附注,我已经确认在不编写任何新Java代码的情况下可以解决此问题:

object AwfulMacroHack {
  import scala.language.experimental.macros
  import scala.reflect.macros.Context

  def _impl(c: Context) = {
    import c.universe._
    c.Expr[String](
      Select(Ident(newTermName("StupidUnderscore")), newTermName("_"))
    )
  }

  def `I'm not named _!` = macro _impl
}

然后:

scala> AwfulMacroHack.`I'm not named _!`
res0: String = Please give me a real name!

我不确定这比Java辅助程序解决方案更少可怕,虽然。


1
似乎反引号 . 是可以接受的。显然没有任何问题…(如果在SO评论中可以出现反引号,我不知道如何操作)。 - Randall Schulz
1
每一次变更都会破坏某些人的工作流程。你应该报告这个错误,或者重新打开旧的错误,因为修复是有问题的。在我看来,他们需要修复别名代码,而不是禁止“_”作为标识符。正如你所指出的那样,这会破坏Java iterop,这肯定比修复原始问题更糟糕... - DaoWen
@RandallSchulz ``` ← 我有一个!请看这个元问题:在注释中的代码区域中使用反斜杠转义 - DaoWen
1个回答

1

既然反引号是Java标识符互操作的机制(例如Thread.yield()),我怀疑没有其他方法可以不使用Reflection。在问题得到解决之前,我建议您最好写一个静态的Java帮助程序方法来访问_

我知道这完全荒谬,但这可能仍然比使用反射更好。他们用那个补丁破坏了Java互操作性,所以他们必须最终解决这个问题。但在他们解决之前,我认为它只是有问题的。


1
是的,这正是我担心的。我已经在问题上发表了评论,并将在听到回复后重新打开。同时,我已经编辑了问题,添加了另一个(同样荒谬)的临时解决方案(它确实使用了反射,但只是编译时反射)。 - Travis Brown
@TravisBrown - 我很惊讶宏解决方案能够工作。我本以为编译器所做的更改也会禁止newTermName("_")。虽然看起来有点hackish,但这可能比编写Java类更好。也许你甚至可以使用隐式值类将\I'm not named _!``属性添加到相关的Java对象中。 - DaoWen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接