Список "волшебных" функций Scala

Где я могу найти список "волшебных" функций Scala, таких как apply, unapply, update, +=, так далее.?

Под магическими функциями я подразумеваю функции, которые используются, например, некоторым синтаксическим сахаром компилятора.

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

Я погуглил какую-то комбинацию scalamagic и синонимы functions, но я ничего не нашел.

Меня не интересует использование магических функций в стандартной библиотеке, но существуют магические функции.

6 ответов

Решение

Насколько я знаю:

Геттеры / сеттеры, связанные:

apply
update
identifier_=

Сопоставление с образцом:

unapply
unapplySeq

For-постижений:

map
flatMap
filter
withFilter
foreach

Префиксные операторы:

unary_+
unary_-
unary_!
unary_~

Кроме того, любой неявный от A до B. Scala также преобразует A <op>= B в A = A <op> B, если первый оператор не определен, "op" не является буквенно-цифровым, и <op>= не !=, ==, <= или же >=,

И я не верю, что есть какое-то единственное место, где перечислены все синтаксические сахара в Scala.

В дополнение к update а также applyЕсть также ряд унарных операторов, которые (я считаю) квалифицируются как магические:

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

Добавьте к этому обычные инфиксные / суффиксные операторы (которые могут быть практически любыми), и вы получите полный пакет.

Вы действительно должны взглянуть на спецификацию языка Scala. Это единственный авторитетный источник по этому поводу. Это не так сложно для чтения (если вам удобны грамматики без контекста), и его очень легко найти. Единственное, что он не определяет хорошо, - это поддержка XML.

Извините, если он не совсем отвечает на ваш вопрос, но мой любимый момент в WTF - это @ как оператор присваивания внутри сопоставления с шаблоном. Благодаря мягкой копии "Программирование в Scala" я быстро узнал, что это было.

Используя @, мы можем связать любую часть шаблона с переменной, и, если совпадение с шаблоном выполнено успешно, переменная захватит значение подшаблона. Вот пример из программирования в Scala (Раздел 15.2 - Привязка переменных):

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

Если полное сопоставление с шаблоном выполнено успешно, то часть, которая соответствует части UnOp("abs", _), становится доступной как переменная e.

И вот что говорит Программирование Scala об этом.

Эта ссылка больше не работает. Вот тот, который делает.

Я также добавлю _* для сопоставления с образцом на произвольном числе параметров, таких как

case x: A(_*)

И правило ассоциативности операторов, из книги Одерского-Ложки-Веннерса:

Ассоциативность оператора в Scala определяется его последним символом. Как упомянуто в <...>, любой метод, заканчивающийся символом ':', вызывается с правым операндом, передавая левый операнд. Методы, которые заканчиваются на любом другом символе, наоборот. Они вызываются на их левом операнде, передавая правый операнд. Таким образом, a * b дает a.*(B), но a::: b дает b.:::(a).


Может быть, мы должны также упомянуть синтаксическое десагеринг выражений, которые можно найти здесь


И (конечно!) Альтернативный синтаксис для пар

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

(как правильно указано, это просто неявное преобразование, выполняемое через библиотеку, поэтому оно, вероятно, не подходит, но я считаю, что это обычная головоломка для новичков)


Я хотел бы добавить, что есть и "волшебная" черта - scala.Dynamic:

Черта маркера, которая позволяет динамические вызовы. Инстансы x этой черты позволяют вызовы методов x.meth(args) для произвольных имен методов meth и списки аргументов args а также доступ к полю x.field для произвольных имен полей 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, определение прямых или косвенных подклассов этой черты возможно только в том случае, если включена динамическая функция языка.

Так что вы можете делать такие вещи, как

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");

Они определены в Спецификации языка 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)
Другие вопросы по тегам