如何在Scala中取消导入字符串“+”运算符?

15

我正在编写一种DSL,其中“+”运算符严格为数字类型,就像其他一些流行的语言一样。这很接近目标,但是字符串“+”运算符正在破坏我的隐式转换。有没有方法可以取消导入String类中的运算符?

为了更加清晰,假设现在有如下代码:

scala> var x = "2" + 3;
x: java.lang.String = 23

我希望得到的结果是 x: Int = 5

我想我只需要两个步骤就可以实现:

  • 从Strings中移除(在我的作用域内取消导入)"+"的定义
  • 定义一个String到Int的隐式转换

我卡在了第一步上。

谢谢


3
我想"import scala.Predef.{any2stringadd => _}"会起作用。 但它没有。我肯定是漏了什么。 - Eastsun
4
any2stringadd 被用在左操作数不支持 + 运算符,但右操作数是字符串的情况下。(要查看示例,请运行 scala -Xprint:typer 并执行 new Object + "ZZZZZ")相比之下,"ZZZZZ" + new Object 可以使用已定义在 String 上的 + 运算符,所以不会使用 any2stringadd - Ken Bloom
3个回答

9
根据Scala规范第12.3.1节的规定,String+方法在编译器中有特殊处理。我不确定,但我认为这意味着您无法“取消导入”,这很遗憾,因为它确实破坏了类型系统(就像相关的toString方法一样)。
您是否可以在DSL中使用不同的运算符名称,例如++&

2
+ 方法受编译器特殊处理与其是否可以被导入或未导入无关。该语言应该非常正交,对所有类方法在语义上都进行相同的处理,无论它们是由编译器合成还是由运行时库提供。 - Ken Bloom
如果+确实在String类上明确指定,我会同意你所说的话,但规范只是暗示了这一点,并且在我看来可以被解释为存在一种隐式转换(编译器内置,因此无法“取消导入”)到某种类型(例如StringAdd),它允许客户端将String视为使用+方法定义的。我很乐意在这里被证明是错误的,但即使通过对String(和RichString)进行运行时反射,我也找不到+(即$plus)方法。 - Kristian Domagala
2
谢谢,听起来又是一种“编译器魔法”,它实际上破坏了正交性,并与其他语言特性和库产生了意想不到的交互作用。 - Alex R
是的,我不确定为什么它不能像Predef.any2stringadd一样实现,例如Predef.string2stringadd:String => StringAdd - Kristian Domagala
在现代scala中,可以取消导入String并使用自定义的插值器来生成自定义类型。目前不可能的是为字符串字面量语法提供自定义的“空”插值器。 - som-snytt

4

+方法是字符串的一个方法,它属于String类(因此属于每个字符串对象),因此不能取消导入。


1

你不能取消导入它,但是你可以使用 +: 并在 int 类中定义它。最好的方法是像这样编写代码:"2".toInt + 3。


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