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