我在哪里可以找到Scala的“魔术”功能列表,例如apply
,unapply
,update
,+=
等?
魔术函数我指的是编译器的一些语法糖使用的函数,例如
o.update(x,y) <=> o(x) = y
我搜索了scala
magic
和functions
的同义词的某种组合,但我没有找到任何内容。
我对标准库中魔术函数的用法不感兴趣,但存在魔法函数。
答案 0 :(得分:77)
据我所知:
Getters / setters相关:
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”不是字母数字,{{1} }不是<op>=
,!=
,==
或<=
。
我不相信有任何一个地方可以列出所有Scala的语法糖。
答案 1 :(得分:16)
除了update
和apply
之外,还有一些一元运算符(我相信)有资格作为魔法:
unary_+
unary_-
unary_!
unary_~
添加常规的中缀/后缀运算符(几乎可以是任何东西),你就可以得到完整的包。
你真的应该看一下Scala语言规范。它是这个东西的唯一权威来源。它并不难读(只要你对无上下文语法感到满意),并且很容易搜索。唯一没有说明的是XML支持。
答案 2 :(得分:11)
很抱歉,如果它没有完全回答你的问题,但到目前为止,我最喜欢的WTF时刻是@作为模式匹配中的赋值运算符。感谢“Scala编程”的软拷贝,我发现它非常快。
使用@我们可以将模式的任何部分绑定到变量,如果模式匹配成功,变量将捕获子模式的值。以下是 Scala编程(第15.2节 - 变量绑定)中的示例:
expr match {
case UnOp("abs", e @ UnOp("abs", _)) => e
case _ =>
}
如果整个模式匹配成功, 然后匹配的部分 UnOp(“abs”,_)部分可用 作为变量e。
here是编程Scala 所说的。
该链接不再有效。 Here就是那个。
答案 3 :(得分:3)
它们在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)
答案 4 :(得分:3)
我还会为模式匹配添加_*
case x: A(_*)
和运营商关联性规则,来自Odersky-Spoon-Venners的书:
Scala中运算符的关联性由其最后一个决定 字符。如在&lt; ...&gt;中提到的,任何结束的方法 在一个':'字符中调用它的右操作数,传入 左操作数。以任何其他字符结尾的方法是另一种 四处走走。它们在左操作数上调用,传入 右操作数。所以a * b产生一个。*(b),但是::: b产生b。:::( a)。
也许我们也应该提到 for expressions 的语法贬义,可以找到here
并且(当然!),对的替代语法
a -> b //converted to (a, b), where a and b are instances
(正确指出,这只是一个通过库完成的隐式转换,所以它可能没有资格,但我觉得这对新手来说是一个普遍的益智者)
答案 5 :(得分:3)
我想补充说还有一个“神奇”的特质 - scala.Dynamic
:
启用动态调用的标记特征。此特征的实例
x
允许方法调用x.meth(args)
用于任意方法名称meth
和参数列表args
以及字段访问x.field
用于任意字段名称{{ 1}}。如果
field
本身不支持某个呼叫(即如果类型检查失败),则会根据以下规则重写:x
从Scala 2.10开始,只有在启用语言特征动态时,才能定义此特征的直接或间接子类。
所以你可以做像
这样的事情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)