W szczególności: próbuję użyć pakietu DataFrames Julii, a konkretnie funkcji readtable () z opcją names, ale wymaga to wektora symboli.
- co to jest symbol?
- dlaczego mieliby wybrać to zamiast wektora ciągów?
Jak dotąd znalazłem tylko kilka odniesień do słowa symbol w języku Julia. Wydaje się, że symbole są reprezentowane przez „: var”, ale nie jest dla mnie jasne, czym one są.
Na bok: mogę biec
df = readtable( "table.txt", names = [symbol("var1"), symbol("var2")] )
Moje dwa pytania z punktorami wciąż są aktualne.
Odpowiedzi:
Symbole w Julii są takie same jak w Lisp, Scheme czy Ruby. Jednak moim zdaniem odpowiedzi na te pytania nie są do końca satysfakcjonujące . Jeśli przeczytasz te odpowiedzi, wydaje się, że powodem, dla którego symbol różni się od łańcucha, jest to, że łańcuchy są zmienne, podczas gdy symbole są niezmienne, a symbole są również „internowane” - cokolwiek to znaczy. Tak się składa, że ciągi znaków są zmienne w Rubim i Lispie, ale nie ma ich w Julii, a ta różnica to tak naprawdę czerwony śledź. Fakt, że symbole są internowane - tj. Haszowane przez implementację języka w celu szybkiego porównania równości - jest również nieistotnym szczegółem implementacji. Możesz mieć implementację, która nie internuje symboli, a język byłby dokładnie taki sam.
Więc czym tak naprawdę jest symbol? Odpowiedź tkwi w czymś, co łączy Julię i Lisp - umiejętność reprezentowania kodu języka jako struktury danych w samym języku. Niektórzy nazywają to „homoikonicznością” ( Wikipedia ), ale inni nie uważają, że sam język wystarczy, aby język był homoikoniczny. Ale terminologia tak naprawdę nie ma znaczenia. Chodzi o to, że jeśli język może reprezentować swój własny kod, potrzebuje sposobu reprezentowania rzeczy, takich jak przypisania, wywołania funkcji, rzeczy, które można zapisać jako wartości dosłowne itp. Potrzebny jest również sposób reprezentowania własnych zmiennych. Oznacza to, że potrzebujesz sposobu, aby przedstawić - jako dane -
foo
po lewej stronie tego:Teraz dochodzimy do sedna sprawy: różnica między symbolem a łańcuchem to różnica między
foo
po lewej stronie tego porównania a"foo"
po prawej stronie. Po lewej stroniefoo
znajduje się identyfikator, którego wynikiem jest wartość powiązana ze zmiennąfoo
w bieżącym zakresie. Po prawej stronie"foo"
znajduje się literał łańcuchowy, którego wynikiem jest wartość ciągu „foo”. Symbol w Lisp i Julia to sposób, w jaki reprezentujesz zmienną jako dane. Ciąg po prostu reprezentuje siebie. Możesz zobaczyć różnicę, stosując sięeval
do nich:To, do czego
:foo
szacowany jest symbol, zależy od tego, do czego - jeśli w ogóle -foo
jest przypisana zmienna , podczas gdy"foo"
zawsze wylicza się jako „foo”. Jeśli chcesz konstruować wyrażenia w Julii, które używają zmiennych, to używasz symboli (czy o tym wiesz, czy nie). Na przykład:To, co wyrzucone rzeczy, pokazuje, między innymi, to, że
:foo
wewnątrz obiektu wyrażenia znajduje się obiekt symbolu, który uzyskuje się poprzez cytowanie kodufoo = "bar"
. Oto kolejny przykład konstruowania wyrażenia z symbolem:foo
przechowywanym w zmiennejsym
:Jeśli spróbujesz to zrobić, gdy
sym
jest powiązany z łańcuchem"foo"
, to nie zadziała:Jest całkiem jasne, dlaczego to nie zadziała - jeśli spróbujesz przypisać
"foo" = "bar"
ręcznie, również nie zadziała.To jest istota symbolu: symbol jest używany do reprezentowania zmiennej w metaprogramowaniu. Kiedy już masz symbole jako typ danych, kuszące staje się użycie ich do innych celów, takich jak klucze mieszające. Ale jest to przypadkowe, oportunistyczne użycie typu danych, które ma inny główny cel.
Zwróć uwagę, że jakiś czas temu przestałem mówić o Rubim. Dzieje się tak, ponieważ Ruby nie jest homoiconic: Ruby nie reprezentuje swoich wyrażeń jako obiektów Rubiego. Tak więc typ symbolu Ruby jest rodzajem szczątkowego organu - pozostałej adaptacji, odziedziczonej po Lispie, ale nie jest już używana do swojego pierwotnego celu. Symbole Rubiego zostały dokooptowane do innych celów - jako klucze haszujące, aby wyciągnąć metody z tabel metod - ale symbole w Rubim nie są używane do reprezentowania zmiennych.
Jeśli chodzi o to, dlaczego symbole są używane w DataFrames, a nie w łańcuchach, to dlatego, że jest to powszechny wzorzec w DataFrames, który wiąże wartości kolumn ze zmiennymi wewnątrz wyrażeń dostarczonych przez użytkownika. Dlatego naturalne jest, że nazwy kolumn są symbolami, ponieważ symbole są dokładnie tym, czego używasz do przedstawiania zmiennych jako danych. Obecnie musisz pisać,
df[:foo]
aby uzyskać dostęp dofoo
kolumny, ale w przyszłości możesz mieć do niej dostęp jakodf.foo
zamiast tego. Kiedy stanie się to możliwe, tylko kolumny, których nazwy są prawidłowymi identyfikatorami, będą dostępne przy użyciu tej wygodnej składni.Zobacz też:
źródło
eval(:foo)
aw innymeval(sym)
. Czy istnieje znacząca różnica międzyeval(:foo)
ieval(foo)
?eval(:foo)
podaje wartość, do którejfoo
jest przypisana zmienna, podczas gdyeval(foo)
wywołuje eval na tej wartości. Pisanieeval(:foo)
jest równoważne z justfoo
(w zakresie globalnym), więceval(foo)
jest jakeval(eval(:foo))
.