Scala 中的所有语法糖实例是什么?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2662984/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What are all the instances of syntactic sugar in Scala?
提问by Hymanson Davis
What are all the instances of syntactic sugar in Scala?
Scala 中的所有语法糖实例是什么?
They are hard to search for since most/all of them are purely symbols and are thus hard to search for without knowing the name of the concept.
它们很难搜索,因为它们中的大多数/全部都是纯粹的符号,因此在不知道概念名称的情况下很难搜索。
TODO:
去做:
- Implicit conversions
_syntax for anonymous functions- Other things I'm forgetting
- 隐式转换
_匿名函数的语法- 我忘记的其他事情
采纳答案by Hymanson Davis
Basics:
基本:
a bis equivalent toa.b.a b cis equivalent toa.b(c), except whenbends in:. In that case,a b cis equivalent toc.b(a).a(b)is equivalent toa.apply(b)This is why the following definitions for an anonymous functions are identical:val square1 = (x: Int) => x*x val square2 = new Function1[Int,Int] { def apply(x: Int) = x*x }When calling
square1(y), you are actually callingsquare1.apply(y)whichsquare1must have as specified by theFunction1trait (orFunction2, etc...)a(b) = cis equivalent toa.update(b,c). Likewise,a(b,c) = dis equivalent toa.update(b,c,d)and so on.a.b = cis equivalent toa.b_=(c). When you create aval/varxin a Class/Object, Scala creates the methodsxandx_=for you. You can define these yourself, but if you definey_=you mustdefineyor it will not compile, for example:scala> val b = new Object{ def set_=(a: Int) = println(a) } b: java.lang.Object{def set_=(Int): Unit} = $anon@17e4cec scala> b.set = 5 <console>:6: error: value set is not a member of java.lang.Object{def set_=(Int): Unit} b.set = 5 ^ scala> val c = new Object{ def set = 0 ; def set_=(a:Int) = println(a) } c: java.lang.Object{def set: Int; def set_=(Int): Unit} = $anon@95a253 scala> c.set = 5 5-acorresponds toa.unary_-. Likewise for+a,~a, and!a.a <operator>= b, where<operator>is some set of special characters, is equivalent toa = a <operator> bonlyifadoesn't have the<operator>=method, for example:class test(val x:Int) { def %%(y: Int) = new test(x*y) } var a = new test(10) a.x // 10 a %%= 5 // Equivalent to a = a %% 5 a.x // 50
a b相当于a.b。a b c等价于a.b(c),除非b以 结尾:。在那种情况下,a b c相当于c.b(a)。a(b)相当于a.apply(b)这就是为什么一个匿名函数以下定义是相同的:val square1 = (x: Int) => x*x val square2 = new Function1[Int,Int] { def apply(x: Int) = x*x }拨打电话时
square1(y),你实际上是在调用square1.apply(y)它square1必须由已按规定Function1性状(或者Function2,等...)a(b) = c相当于a.update(b,c)。同样,a(b,c) = d等价于a.update(b,c,d)等等。a.b = c相当于a.b_=(c)。当你创建一个val/varx在类/对象,斯卡拉创建方法x和x_=为您服务。您可以自己定义这些,但如果您定义y_=,则必须定义y,否则将无法编译,例如:scala> val b = new Object{ def set_=(a: Int) = println(a) } b: java.lang.Object{def set_=(Int): Unit} = $anon@17e4cec scala> b.set = 5 <console>:6: error: value set is not a member of java.lang.Object{def set_=(Int): Unit} b.set = 5 ^ scala> val c = new Object{ def set = 0 ; def set_=(a:Int) = println(a) } c: java.lang.Object{def set: Int; def set_=(Int): Unit} = $anon@95a253 scala> c.set = 5 5-a对应于a.unary_-。同样的+a,~a和!a。a <operator>= b, where<operator>是一些特殊字符集,a = a <operator> b仅当a没有该<operator>=方法时才等效,例如:class test(val x:Int) { def %%(y: Int) = new test(x*y) } var a = new test(10) a.x // 10 a %%= 5 // Equivalent to a = a %% 5 a.x // 50
回答by Hymanson Davis
Special Classes: Tuples and Symbols
特殊类:元组和符号
As mentioned by Rahul G, tuples and symbols get a slightly special syntax.
正如Rahul G所提到的,元组和符号有一个稍微特殊的语法。
- Symbols: the syntax
'xis short forSymbol("x") - Tuples:
(p1,p2,..,pn)is short for a case classTuplen[T1,T2,..,Tn](p1,p2,..,pn)
- 符号:语法
'x的缩写为Symbol("x") - 元组:
(p1,p2,..,pn)是案例类的缩写Tuplen[T1,T2,..,Tn](p1,p2,..,pn)
For example, the following two are equivalent.
例如,以下两个是等价的。
val tuple1 = ("Hello",1)
val tuple2 = Tuple2[String,Int]("Hello",1)
回答by IttayD
In addition to Jaxkson's answer:
除了贾克森的回答:
type F[A,B]can be used asA F B.
type F[A,B]可以用作A F B.
For example:
例如:
type ->[A,B] = (A,B)
def foo(f: String -> String)
- Using
=> typein a method definition makes the compiler wrap expressions inside the method call in a function thunk.
- 使用
=> type方法定义使得函数的thunk方法调用内部编译器包表达式。
For example
例如
def until(cond: => Boolean)(body: => Unit) = while(!cond) body
var a = 0
until (a > 5) {a += 1}
回答by Hymanson Davis
Extractors:
提取器:
There are two methods used for extractors, unapplyand unapplySeq. These are used in multiple variable assignments and pattern matching.
提取器有两种方法,unapply和unapplySeq. 这些用于多变量赋值和模式匹配。
The first use case is where unapply takes the object it is supposed to match and returns a
Booleanbased on whether or not it matches, for example,trait Gender trait Male extends Gender trait Female extends Gender object Male extends Male object Female extends Female class Person(val g: Gender, val age: Int) object Adult { def unapply(p: Person) = p.age >= 18 } def check(p: Person) = p match { case Adult() => println("An Adult") case _ => println("A Child") } //Will print: An Adult since Adult.unapply returns true. check(new Person(Female, 18)) //Will print: A Child as it falls through to the _ case. check(new Person(Male, 17))
第一个用例是 unapply 获取它应该匹配的对象并
Boolean根据它是否匹配返回一个,例如,trait Gender trait Male extends Gender trait Female extends Gender object Male extends Male object Female extends Female class Person(val g: Gender, val age: Int) object Adult { def unapply(p: Person) = p.age >= 18 } def check(p: Person) = p match { case Adult() => println("An Adult") case _ => println("A Child") } //Will print: An Adult since Adult.unapply returns true. check(new Person(Female, 18)) //Will print: A Child as it falls through to the _ case. check(new Person(Male, 17))
Honestly, I don't really get the purpose of the above syntax since it can be done almost just as easily by just putting the code in the casestatements. Of course if you have a better example, leave a comment below
老实说,我并没有真正理解上述语法的目的,因为只需将代码放在case语句中就可以轻松完成。当然,如果你有更好的例子,请在下方留言
The general case where
unapplytakes some fixed-number of parameters and returns either anOption[T]for a single parameter or aOption[(p1,p2,...)]for multiple, i.e. a Tuple with the matched values, for example, continuing from the above code:object Person { def apply(g: Gender, age: Int) = new Person(g, age) def unapply(p: Person) = if(p.age < 0) None else Some((p.g, p.age)) } //Using Person.apply as described in the Basics section val alice = Person(Female, 30) val bob = Person(Male, 25) //This calls Person.unapply(alice), which returns Some((Female, 30)). //alice_gender is assigned Female and alice_age 30. val Person(alice_gender, alice_age) = alice bob match { //Calls Person.unapply(bob), but sees that g is Male, so no match. case Person(Female, _) => println("Hello ma'am") //Calls Person.unapply(bob) and assigns age = bob.age, but it doesn't pass //the 'if' statement, so it doesn't match here either. case Person(Male, age) if age < 18 => println("Hey dude") //So bob falls through to here case _ => println("Hello Sir") } Person(Male,-1) match { //Person.unapply(Person.apply(Male,-1)) returns None because p.age < 0. //Therefore this case will not match. case Person(_, _) => println("Hello person") //Thus it falls through to here. case _ => println("Are you Human?") }
一般情况下,
unapply接受一些固定数量的参数并返回Option[T]单个参数或Option[(p1,p2,...)]多个参数,即具有匹配值的元组,例如,从上面的代码继续:object Person { def apply(g: Gender, age: Int) = new Person(g, age) def unapply(p: Person) = if(p.age < 0) None else Some((p.g, p.age)) } //Using Person.apply as described in the Basics section val alice = Person(Female, 30) val bob = Person(Male, 25) //This calls Person.unapply(alice), which returns Some((Female, 30)). //alice_gender is assigned Female and alice_age 30. val Person(alice_gender, alice_age) = alice bob match { //Calls Person.unapply(bob), but sees that g is Male, so no match. case Person(Female, _) => println("Hello ma'am") //Calls Person.unapply(bob) and assigns age = bob.age, but it doesn't pass //the 'if' statement, so it doesn't match here either. case Person(Male, age) if age < 18 => println("Hey dude") //So bob falls through to here case _ => println("Hello Sir") } Person(Male,-1) match { //Person.unapply(Person.apply(Male,-1)) returns None because p.age < 0. //Therefore this case will not match. case Person(_, _) => println("Hello person") //Thus it falls through to here. case _ => println("Are you Human?") }
Note:Case classesdo all those apply/unapplydefinitions for you (as well as other stuff) so use them whenver possible to save time and reduce code.
注意:案例类为您完成所有这些apply/unapply定义(以及其他内容),因此请尽可能使用它们以节省时间并减少代码。
unapplySeq. This works similarly tounapplyas above, except it must return anOptionof some kind of sequence.
unapplySeq. 这unapply与上面的工作方式类似,但它必须返回Option某种序列。
As a quick example,
举个简单的例子,
scala> List.unapplySeq(List(1,2,3))
res2: Some[List[Int]] = Some(List(1, 2, 3))
回答by vadipp
Anonymous functions:
匿名函数:
_ + _is short for (a, b) => a + b
_ + _是简称 (a, b) => a + b
回答by Erik Kaplun
Context bounds desugar into implicitparameters, e.g. consider a function that leverages the Monoidtype class:
上下文将 desugar 绑定到implicit参数中,例如考虑一个利用Monoid类型类的函数:
def suml[T: Monoid](xs: List[T]) = {
val T = implicitly[Monoid[T]]
xs.foldLeft(T.mzero)(T.mplus)
}
where the : Monoidpart is a context bound, gets translated to:
其中: Monoid部分是上下文绑定,被翻译为:
def suml[T](xs: List[T])(implicit evidence: Monoid[T]]) = {
...
}
therefore the following compiles, too:
因此,以下也编译:
def suml[T: Monoid](xs: List[T]) = {
val T = evidence
...
}

