Практические примеры использования символов в Scala?
Scala имеет символы-имена, которые начинаются с одной кавычки ' и которые являются своего рода строковыми константами.
Я знаю символы из Ruby (где они начинаются с двоеточия). В Ruby они используются для некоторых задач метапрограммирования, таких как генерация геттеров и сеттеров для переменных-членов (например,attr_reader :name
создать геттер для name
).
Я еще не видел много использования символов в коде Scala. Каковы практические применения символов в Scala?
8 ответов
действительно ли символы вписываются в Scala?
в чудесной стране Lisp код представлен как вложенные списки литеральных объектов, которые обозначают себя (строки, числа и т. д.), и символы, которые используются в качестве идентификаторов для таких вещей, как классы, функции и переменные. Поскольку код Lisp имеет очень простую структуру, Lisp позволяет программисту управлять им (как во время компиляции, так и во время выполнения). Очевидно, что при этом программист неизбежно столкнется с такими символами, как объекты-данные.
таким образом, символы являются (и должны быть) объектами в Lisp в любом случае, так почему бы не использовать их как ключи хэш-таблицы или как перечисления? Это естественный способ делать вещи, и он сохраняет язык простым, так как вам не нужно определять специальный тип перечисления.
обобщить, символы обычно используются для манипуляции с кодом, подсчет и манипуляция. Но люди Java не используют identity в качестве отношения эквивалентности между хэш-ключами по умолчанию (который ваш традиционный Лисп делает), поэтому они могут просто использовать строки в качестве ключей. Типы перечислений определяются отдельно в Scala. И, наконец, код как данные вообще не поддерживается языком.
Так что нет, мое впечатление, что символы не принадлежат к языку Scala. Тем не менее, я собираюсь следить за ответами на этот вопрос. Они все еще могут продемонстрировать подлинное использование символов в Scala, о которых я сейчас не могу думать.
(дополнение: в зависимости от диалект Lisp, символы Lisp также могут быть определены пространством имен, что, конечно, является чрезвычайно полезной функцией при манипулировании кодом и функцией, которой нет у строк.)
Поиск немного по сети кажется, что смысл символов (символьных литералов) в (таком языке, как) Scala по сравнению со строками является вопросом семантики, и, возможно, даже осознания компилятора.
'String' - это тип данных, состоящий из последовательности символов. Вы можете оперировать струнами и манипулировать ими. Строки могут семантически быть любыми текстовыми данными, от имени файла до сообщения для печати на экране, строки в CSV-файле или что угодно.
для компилятора - и, таким образом, IDE-строки являются значениями строки типа данных, как числа (последовательности цифр) являются значениями типа данных, скажем: Integer . На программном уровне нет разницы между" foo "и"bar".
OTOH символы являются идентификаторами, т. е. семантически идентифицирующими элемент в программе. В этом вопросе они похожи на имена классов, имена методов или атрибутов. Но в то время как имя класса идентифицирует класс -т. е. набор свойств объявление структуры и поведения класса-и имя метода идентифицирует метод-т. е. параметры и операторы- , имя символа идентифицирует символ-т. е. его самого, ничего больше- .
таким образом, компилятор может явно различать символы " foo " и " bar, как он различает классы Foo и Bar. Как часть таблицы символов компилятора, вы можете применить те же механизмы в IDE, например, для поиска использования ' foo (т. е. ссылок на это символ), как вы ищете для использования класса Foo.
для сравнения, поиск строки " foo " потребует различных подходов, таких как полнотекстовое сканирование. Он следует той же семантике, что и поиск всех вхождений 4711 в программном коде.
вот как я понимаю, кто-то может поправить меня, если я ошибаюсь.
согласно Книге Scala, символы интернированы:"если вы пишете один и тот же символ дважды, оба выражения будут относиться к одному и тому же
Я думаю, Scala добавил их, потому что функциональные языки используют их.
они забыли, однако, добавить способность ссылаться на идентификатор через символ, который является своего рода центральной точкой их существования. В Scala 2.8 есть экспериментальная функция, которая дает некоторые из них. Я приведу соответствующую часть документации API в полном объеме:
@experimental
object Invocation
extends AnyRef
более удобный синтаксис для вызова светоотражающие. Пример использования:
class Obj { private def foo(x: Int, y: String): Long = x + y.length }
вы можете назвать это рефлексивно одним из двух способов:
import scala.reflect.Invocation._
(new Obj) o 'foo(5, "abc") // The 'o' method returns Any
val x: Long = (new Obj) oo 'foo(5, "abc") // The 'oo' method casts to expected type.
если вы называете oo
метод и не дают типу inferencer достаточно помощи, он, скорее всего, выведет Nothing
, что приведет к ClassCastException
.
автор Пол Филлипс!--7-->
Я считаю, что сравнение между символами быстрее. Если вы использовали Erlang, символы используются тонну при передаче сообщений, и вы хотите что-то дешевое и быстрое, что хорошо работает через границы машины. Я не уверен, в каком состоянии находятся удаленные актеры в Scala, IIRC, они были довольно изворотливы, но в будущем, когда они на месте, символы могут быть очень полезны во многом так же, как и в Эрланге. Кроме того, классы case, некоторые из преимуществ не так очевидны, а затем снова, символы по-прежнему дешевле.
Я полагаю, вы будете использовать их, когда захотите сослаться на имя вещи, которая не является существующим идентификатором в коде. В книге Scala приведен пример ссылки на имя столбца базы данных-это не произвольная строка, это на самом деле имя вещи.
Это немного шатко, хотя я не совсем убежден.
Я могу назвать один случай, когда символы используются в Scala. Играть 2.2 использует anorm для доступа к базе данных. Вот пример кода для простого метода add entity:
def add(e:Entity): Option[Long] = {
DB.withConnection {implicit conn =>
SQL("insert into ENTITY(name, description) values({name}, {description})").on('name -> e.name, 'description -> e.description).executeInsert()
}
}
таким образом, вы можете увидеть использование символов в .(бла-бла-бла!)) Также абсолютно допустимо использовать строковые литералы вместо символов, и некоторые ребята делают это, но в исходном коде anorm соответствующая сигнатура метода действительно использует символ типа paremeter.
Как уже отмечалось, символы переносятся с других (более) функциональных языков. Что-то другие не упоминали, что они не только заполняют роль символов, но они также являются ближайшим эквивалентом ключевых слов (минус преимущество производительности, возможно). На мой взгляд, они более полезны в качестве ключевых слов, что означает явные идентификаторы.
ниже я включу описание суда из Clojure docs ключевых слов и символов.
символы
символы являются идентификаторами, которые обычно используются для обозначения чего-то другого. Они могут использоваться в формах программ для ссылки на параметры функций, привязки let, имена классов и глобальные vars. Они имеют имена и необязательные пространства имен, оба из которых являются строками. Символы могут иметь метаданные (см. с-мета).
ключевые слова
ключевые слова являются символьными идентификаторами, которые оценивают сами по себе. Они обеспечивают очень быстрые тесты равенства. Как Символы, они имеют имена и необязательные пространства имен, оба из которых являются строками. Ведущее": "не является частью пространства имен или имени.
символы Scala не так сильны, как символы в некоторых языках. Поэтому они тоже не столь полезны. Однако я не понимаю, почему они не могут предложить те же преимущества метапрограммирования и производительности, что и ключевые слова. По крайней мере, они могут сделать ваш код более легким для чтения.