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


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

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

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

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

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

6 68

6 ответов:

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

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

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" не является буквенно-цифровым, а <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 говорит об этом.

они определены в спецификации языка 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)

Я также добавлю _* на сопоставление шаблонов по произвольному числу параметров как

case x: A(_*)

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

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


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


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

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