Каковы все экземпляры синтаксического сахара в Scala?

Каковы все экземпляры синтаксического сахара в Scala?

Их трудно искать, так как большинство/все они - просто символы и таким образом твердо искать, не зная название понятия.

TODO:

  • Неявные преобразования
  • _ синтаксис для анонимных функций
  • Другие вещи я забываю
62
задан Peter Mortensen 16 May 2013 в 16:36
поделиться

4 ответа

Основы:

  • ab эквивалентно ab
  • abc эквивалентно ab (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 / var x в классе / объекте, Scala создает методы x и x _ = для ты. Вы можете определить их самостоятельно, но если вы определите y _ = , вы должны определить y , иначе он не будет компилироваться, например,

     scala> val b = новый объект {def set _ = (a: Int) = println (a)} 
    b: java.lang.Object {def set _ = (Int): Unit} = $ anon $ 1 @ 17e4cec {{1} } 
    scala> b.set = 5 
     : 6: error: value set не является членом java.lang.Object {def set _ = (Int): Unit} {{ 1}} 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 $ 1 @ 95a253 
     
    scala> c.set = 5 
    5 
     
  • -a соответствует a.unary _- Аналогично для + a , ~ a и ! a

  • a <оператор> = b , где <оператор > - некоторый набор специальных символов, эквивалентен a = a <оператор> b , только , если a не имеет <оператор> = Метод , например,

     class test (val x: Int) {
    def %% (y: Int) = new test (x * y) 
    } {{ 1}} 
    var a = new test (10) 
    ax // 10 
    a %% = 5 // Эквивалентно a = a %% 5 
    топор // 50 
     
58
ответ дан 24 November 2019 в 16:45
поделиться

Специальные классы: кортежи и символы

Как упоминал Рахул Дж. , кортежи и символы имеют несколько особый синтаксис.

  • Символы: синтаксис 'x является сокращением от Symbol ("x")
  • Кортежи: (p1, p2, .., pn) коротким для класса случая Tuplen [T1, T2, .., Tn] (p1, p2, .., pn)

Например, следующие два эквивалентны.

val tuple1 = ("Hello",1)
val tuple2 = Tuple2[String,Int]("Hello",1)
18
ответ дан 24 November 2019 в 16:45
поделиться

Экстракторы:

Для экстракторов используются два метода: unapply и unapplySeq . Они используются при назначении нескольких переменных и сопоставлении с образцом.

  • Первый вариант использования - unapply берет объект, которому он должен соответствовать, и возвращает ​​логическое значение в зависимости от того, соответствует ли оно, например,

     trait Gender 
    trait Male расширяет Gender 
    trait Female extends Gender 
    объект Male расширяет Male 
    объект Female расширяет женский 
    класс Person (val g: Gender, val age: Int) {{ 1}} 
    объект для взрослых {
    def unapply (p: Person) = p.age> = 18 
    } 
     
    def check (p : Person) = p match {
    case Adult () => println ("Взрослый") 
    case _ => println ("Ребенок") 
    } {{1 }} 
     // Напечатает: Взрослый, поскольку Adult.unapply возвращает true. 
    check (new Person (Female, 18)) 
     
     // Напечатает : Ребенок в случае _. 
    check (new Person (Male, 17)) 
     

Честно говоря, я не совсем понимаю цель приведенного выше синтаксиса, поскольку это можно сделать почти так же легко, просто поместив код в операторы case . Конечно, если у вас есть лучший пример, оставьте комментарий ниже.

  • Общий случай, когда unapply принимает некоторое фиксированное количество параметров и возвращает либо Option [T] для один параметр или Опция [(p1, p2, ...)] для нескольких, то есть кортежа с совпадающими значениями, например, продолжением из приведенного выше кода:

     объект Person {
    def apply (g: Gender, age: Int) = new Person (g, age) 
    def unapply (p: Person) = if (p.age <0) None else Some ((pg, p.age)) 
    } 
     { {1}} // Использование Person.apply, как описано в разделе "Основные сведения" 
    val alice = Person (Female, 30) 
    val bob = Person (Male, 25) 
     { {1}} // Это вызывает Person.unapply (alice), который возвращает Some ((Female, 30)). 
     // alice_gender назначается Female, а alice_age 30. 
    val Person (alice_gender) , alice_age) = alice 
     
    bob match {
     // Вызывает Person.unapply (bob), но видит, что g - Male, поэтому совпадения нет. 
    case Person (Female, _) => println ("Hello ma'am") 
     // Вызывает Person.unapply (bob) и назначает age = bob.age, но не проходит 
     // оператор 'if', поэтому он здесь тоже не соответствует. 
    case Person (Male, age) if age <18 => println ("Hey dude") 
     // Итак Боб попадает сюда 
    case _ => println ("Здравствуйте, сэр") 
    } 
     
    Person (Male, -1) match {
     //Person.unapply(Person.apply(Male,-1)) возвращает None, потому что p .age <0. 
     // Следовательно, этот случай не будет совпадать. 
    case Person (_, _) => println ("Hello person") 
     // Таким образом, он падает сюда. 
    case _ => println ("Вы человек?") 
    } 
     

Примечание: Классы случаев выполняют все эти применить / отменить определения для вас (а также другие вещи), поэтому используйте их, когда это возможно, чтобы сэкономить время и сократить объем кода.

  • unapplySeq . Это работает аналогично unapply , как указано выше, за исключением того, что он должен возвращать Option некоторой последовательности.

В качестве быстрого примера:

scala> List.unapplySeq(List(1,2,3))
res2: Some[List[Int]] = Some(List(1, 2, 3))
14
ответ дан 24 November 2019 в 16:45
поделиться

В дополнение к ответу Джексона:

  • тип F [A, B] может использоваться как A F B .

Например:

type ->[A,B] = (A,B)
def foo(f: String -> String)
  • Использование => type в определении метода заставляет компилятор переносить выражения внутри вызова метода в преобразователь функции.

Например

def until(cond: => Boolean)(body: => Unit) = while(!cond) body

var a = 0
until (a > 5) {a += 1}
19
ответ дан 24 November 2019 в 16:45
поделиться
Другие вопросы по тегам:

Похожие вопросы: