Каковы все экземпляры синтаксического сахара в Scala?
каковы все экземпляры синтаксического сахара в Scala?
их трудно найти, так как большинство/все они являются чисто символами и поэтому трудно искать, не зная названия понятия.
TODO:
- неявные преобразования
 - 
_синтаксис для анонимных функций - другие вещи я забываю
 
6 ответов:
основные:
a bэквивалентноa.ba b cэквивалентноa.b(c), за исключениемbзаканчивается в:. В таком случае,a b cэквивалентноc.b(a)
a(b)эквивалентноa.apply(b)вот почему следующие определения анонимных функций идентичны: val square1 = (x: Int) => xx val square2 = новая функция 1[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в классе/объекте Scala создает методы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, где<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
в дополнение к ответу Джаксона:
type F[A,B]может использоваться какA F B.например:
type ->[A,B] = (A,B) def foo(f: String -> String)
- используя
 => typeв определении метода делает компилятор обернуть выражения внутри вызова метода в функции thunk.def until(cond: => Boolean)(body: => Unit) = while(!cond) body var a = 0 until (a > 5) {a += 1}
специальные классы: кортежи и символами
как отметил Рахул Г, кортежи и символы получают немного специальный синтаксис.
- символы: синтаксис
 'xсокращенноSymbol("x")- кортежи:
 (p1,p2,..,pn)сокращенно для класса caseTuplen[T1,T2,..,Tn](p1,p2,..,pn)например, следующие два эквивалентны.
val tuple1 = ("Hello",1) val tuple2 = Tuple2[String,Int]("Hello",1)
экстракторы:
есть два метода, используемые для экстракторов,
unapplyиunapplySeq. Они используются в нескольких назначениях переменных и сопоставлении шаблонов.
первый случай использования - это когда 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))честно говоря, я действительно не понимаю цели приведенного выше синтаксиса, так как это можно сделать почти так же легко, просто поставив код в
caseзаявления. Конечно, если у вас есть лучший пример, оставьте комментарий ниже
общий случай, когда
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?") }Примечание:случае классы все это
apply/unapplyопределения для вас (а также другие вещи) так что используйте их, когда это возможно, чтобы сэкономить время и уменьшить код.
unapplySeq. Это работает аналогичноunapplyкак и выше, за исключением того, что он должен вернутьOptionкакой-то последовательности.в качестве быстрого примера,
scala> List.unapplySeq(List(1,2,3)) res2: Some[List[Int]] = Some(List(1, 2, 3))
контекст ограничивает desugar в
implicitпараметры, например, рассмотрим функцию, которая используетMonoidтип класса:def suml[T: Monoid](xs: List[T]) = { val T = implicitly[Monoid[T]] xs.foldLeft(T.mzero)(T.mplus) }здесь
: Monoidчасть является контекстной привязкой, переводится в:def suml[T](xs: List[T])(implicit evidence: Monoid[T]]) = { ... }поэтому следующие компиляции тоже:
def suml[T: Monoid](xs: List[T]) = { val T = evidence ... }