Список "волшебных" функций Scala
Где я могу найти список "волшебных" функций Scala, таких как apply
, unapply
, update
, +=
, так далее.?
Под магическими функциями я подразумеваю функции, которые используются, например, некоторым синтаксическим сахаром компилятора.
o.update(x,y) <=> o(x) = y
Я погуглил какую-то комбинацию scala
magic
и синонимы 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)