Практические примеры использования символов в Scala?


Scala имеет символы-имена, которые начинаются с одной кавычки ' и которые являются своего рода строковыми константами.

Я знаю символы из Ruby (где они начинаются с двоеточия). В Ruby они используются для некоторых задач метапрограммирования, таких как генерация геттеров и сеттеров для переменных-членов (например attr_reader :name создать геттер для name).

Я еще не видел много использования символов в коде Scala. Какое практическое применение имеют символы в Scala?

8 61

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.

автор Пол Филлипс

Я считаю, что сравнение между символами быстрее. Если вы использовали 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 не так сильны, как символы в некоторых языках. Поэтому они тоже не так полезны. Однако я не понимаю, почему они не могут предложить те же преимущества метапрограммирования и производительности, что и ключевые слова. По крайней мере, они могут облегчить чтение вашего кода.