В частности: я пытаюсь использовать пакет Julia DataFrames, в частности функцию readtable () с параметром names, но для этого требуется вектор символов.
- что такое символ?
- почему они выбрали это вместо вектора строк?
Пока что я нашел лишь несколько ссылок на слово «символ» в языке Julia. Кажется, что символы представлены как ": var", но мне далеко не ясно, что это такое.
В сторону: я могу бежать
df = readtable( "table.txt", names = [symbol("var1"), symbol("var2")] )
Два моих вопроса, отмеченных списком, все еще в силе
Ответы:
Символы в Julia такие же, как в Lisp, Scheme или Ruby. Однако, на мой взгляд , ответы на эти вопросы не совсем удовлетворительны . Если вы читаете эти ответы, кажется, что причина, по которой символ отличается от строки, заключается в том, что строки являются изменяемыми, в то время как символы неизменны, и символы также «интернированы» - что бы это ни значило. Строки действительно могут быть изменяемыми в Ruby и Lisp, но их нет в Julia, и это различие на самом деле отвлекает. Тот факт, что символы интернированы, то есть хешируются реализацией языка для быстрого сравнения на равенство, также является несущественной деталью реализации. У вас может быть реализация, в которой не используются внутренние символы, и язык будет точно таким же.
Так что же такое символ на самом деле? Ответ кроется в том, что у Julia и Lisp общее - в способности представлять код языка как структуру данных на самом языке. Некоторые люди называют это «гомоиконностью» ( Википедия ), но другие, похоже, не думают, что одного этого достаточно для того, чтобы язык был гомоиконным. Но терминология особого значения не имеет. Дело в том, что когда язык может представлять свой собственный код, ему нужен способ представления таких вещей, как присваивания, вызовы функций, вещи, которые могут быть записаны как буквальные значения и т. Д. Ему также нужен способ представления собственных переменных. То есть вам нужен способ представить - как данные -
foo
левую часть этого:Теперь мы подходим к сути вопроса: разница между символом и строкой - это разница между
foo
левой частью этого сравнения и"foo"
правой частью. Слеваfoo
- идентификатор, который оценивает значение, привязанное к переменнойfoo
в текущей области. Справа"foo"
- строковый литерал, оценивающий строковое значение «foo». Символ как в Lisp, так и в Julia - это то, как вы представляете переменную как данные. Строка просто представляет себя. Вы можете увидеть разницу, применивeval
к ним:То, что символ
:foo
оценивает, зависит от того, к чему - если вообще что-либо - переменнаяfoo
привязана, тогда как"foo"
всегда просто оценивается как "foo". Если вы хотите создавать выражения в Julia, которые используют переменные, вы используете символы (знаете вы об этом или нет). Например:То, что вываливали, показывает, среди прочего, что есть
:foo
объект символа внутри объекта выражения, который вы получаете, цитируя кодfoo = "bar"
. Вот еще один пример построения выражения с символом,:foo
хранящимся в переменнойsym
:Если вы попытаетесь сделать это, когда
sym
привязан к строке"foo"
, это не сработает:Понятно, почему это не сработает - если вы попытались назначить
"foo" = "bar"
вручную, это тоже не сработает.В этом суть символа: символ используется для представления переменной в метапрограммировании. Если у вас есть символы в качестве типа данных, конечно, возникает соблазн использовать их для других вещей, например, в качестве хеш-ключей. Но это случайное, оппортунистическое использование типа данных, имеющего другую основную цель.
Обратите внимание, что я перестал говорить о Ruby некоторое время назад. Это потому, что Ruby не гомоиконичен: Ruby не представляет свои выражения как объекты Ruby. Итак, тип символа Ruby - это своего рода рудиментарный орган - оставшаяся адаптация, унаследованная от Lisp, но больше не используемая по своему первоначальному назначению. Символы Ruby были использованы для других целей - в качестве ключей хеширования для извлечения методов из таблиц методов - но символы в Ruby не используются для представления переменных.
Что касается того, почему символы используются в DataFrames, а не в строках, это потому, что это распространенный шаблон в DataFrames для привязки значений столбцов к переменным внутри предоставленных пользователем выражений. Поэтому естественно, чтобы имена столбцов были символами, поскольку символы - это именно то, что вы используете для представления переменных в виде данных. В настоящее время
df[:foo]
для доступа кfoo
столбцу необходимо писать , но в будущем вы можете получить к нему доступ какdf.foo
вместо этого. Когда это станет возможным, с этим удобным синтаксисом будут доступны только столбцы, имена которых являются допустимыми идентификаторами.Смотрите также:
источник
eval(:foo)
а в другойeval(sym)
. Есть ли значимая разница междуeval(:foo)
иeval(foo)
?eval(:foo)
дает значение, к которомуfoo
привязана переменная , тогда какeval(foo)
вызывает eval для этого значения. Написаниеeval(:foo)
эквивалентно простоfoo
(в глобальном масштабе) такeval(foo)
похожеeval(eval(:foo))
.