Scala 的“神奇”函数列表

在哪里可以找到 Scala 的“魔法”函数列表,例如 applyunapplyupdate+=等等?

我所说的魔法函数是指那些被编译器的某些语法所使用的函数,例如

o.update(x,y) <=> o(x) = y

我谷歌了一些 scala magicfunctions的同义词的组合,但我没有找到任何东西。

我对标准库中魔法函数的 用途不感兴趣,但对魔法函数存在的 用途感兴趣。

10016 次浏览

它们是在 Scala 语言规范中定义的。 据我所知,正如你所提到的,只有三个“神奇”的功能。

Scalas Getter 和 Setter 可能也与你的“魔法”有关:

scala> class Magic {
|     private var x :Int = _
|     override def toString = "Magic(%d)".format(x)
|     def member = x
|     def member_=(m :Int){ x = m }
| }


defined class Magic


scala> val m = new Magic


m: Magic = Magic(0)


scala> m.member


res14: Int = 0


scala> m.member = 100


scala> m


res15: Magic = Magic(100)


scala> m.member += 99


scala> m


res17: Magic = Magic(199)

除了 updateapply,还有一些一元运算符(我相信)具有魔力:

  • unary_+
  • unary_-
  • unary_!
  • unary_~

再加上常规的中缀/后缀操作符(几乎可以是任何操作符) ,您就得到了完整的包。

您真的应该看看 Scala 语言规范。它是这方面唯一权威的资料来源。它并不难阅读(只要你对上下文无关的语法感到舒服) ,而且非常容易搜索。它唯一没有很好地指定的是 XML 支持。

据我所知:

接收器/接收器相关:

apply
update
identifier_=

模式匹配

unapply
unapplySeq

理解:

map
flatMap
filter
withFilter
foreach

前缀营办商:

unary_+
unary_-
unary_!
unary_~

除此之外,任何从 A 到 B 的隐式 Scala 也会将 A <op>= B转换成 A = A <op> B,如果前者没有定义,“ op”不是字母数字,而 <op>=不是 !===<=>=

而且我不相信有任何一个地方列出了 Scala 的所有语法糖。

对不起,如果它没有准确地回答你的问题,但是到目前为止,我最喜欢的卧槽是@作为模式匹配中的赋值操作符。多亏了《 Scala 编程》的软拷贝,我很快就发现了它的功能。

使用@,我们可以将模式的任何部分绑定到一个变量,如果模式匹配成功,该变量将捕获子模式的值。下面是来自 Scala 编程(15.2节-变量绑定)的例子:

expr match {
case UnOp("abs", e @ UnOp("abs", _)) => e
case _ =>
}

如果整个模式匹配成功, 那么匹配 UnOP (“ abs”,_)部分可用 作为变量 e。

编程 Scala是这么说的。

那个链接不再有效。 给你就是有效的链接。

我还将为 任意数量的参数的模式匹配添加 _*

case x: A(_*)

算符结合性算符结合性规则,来自 Odersky-Spoon-Venners 的书:

Scala 中运算符的结合性是由它的最后一个 字符。正如在 < ... > 中提到的,任何结束 在“ :”字符中,对其右操作数调用,并传入 以任何其他字符结尾的方法是另一个 它们在其左操作数上调用,并传入 所以 a * b 产生 a * (b) ,而 a: : : b 产生 b: : : (a)。


也许我们还应该提到 表达方式的句法去糖化,它可以在 给你中找到


(当然!) ,对的替代语法

a -> b //converted to (a, b), where a and b are instances

(正如正确指出的,这只是一个通过库完成的 隐式转换,所以它可能不符合条件,但我发现它是一个常见的新手难题)


我想补充的是,还有一个“神奇”的特征—— scala.Dynamic:

启用动态调用的标记特性。这个 trait 的实例 x允许对任意方法名称 meth和参数列表 args进行方法调用 x.meth(args),以及对任意字段名称 field进行字段访问 x.field

如果 x本身不支持某个调用(例如,如果类型检查失败) ,则根据以下规则重写该调用:

foo.method("blah")      ~~> foo.applyDynamic("method")("blah")
foo.method(x = "blah")  ~~> foo.applyDynamicNamed("method")(("x", "blah"))
foo.method(x = 1, 2)    ~~> foo.applyDynamicNamed("method")(("x", 1), ("", 2))
foo.field           ~~> foo.selectDynamic("field")
foo.varia = 10      ~~> foo.updateDynamic("varia")(10)
foo.arr(10) = 13    ~~> foo.selectDynamic("arr").update(10, 13)
foo.arr(10)         ~~> foo.applyDynamic("arr")(10)

从 Scala 2.10开始,只有在启用了语言特性动态的情况下,定义这个 trait 的直接或间接子类才是可能的。

这样你就可以

import scala.language.dynamics


object Dyn extends Dynamic {
def applyDynamic(name: String)(a1: Int, a2: String) {
println("Invoked " + name + " on (" + a1 + "," + a2 + ")");
}
}


Dyn.foo(3, "x");
Dyn.bar(3, "y");