Konkret: Ich versuche, Julias DataFrames-Paket zu verwenden, insbesondere die Funktion readtable () mit der Option names, aber dafür ist ein Vektor von Symbolen erforderlich.
- Was ist ein Symbol?
- warum sollten sie das einem Vektor von Strings vorziehen?
Bisher habe ich nur eine Handvoll Hinweise auf das Wortsymbol in der Julia-Sprache gefunden. Es scheint, dass Symbole durch ": var" dargestellt werden, aber mir ist alles andere als klar, was sie sind.
Nebenbei: Ich kann rennen
df = readtable( "table.txt", names = [symbol("var1"), symbol("var2")] )
Meine zwei Fragen mit Aufzählungszeichen stehen noch.
Antworten:
Die Symbole in Julia sind dieselben wie in Lisp, Scheme oder Ruby. Die Antworten auf diese verwandten Fragen sind meiner Meinung nach jedoch nicht wirklich zufriedenstellend . Wenn Sie diese Antworten lesen, scheint der Grund, warum sich ein Symbol von einer Zeichenfolge unterscheidet, darin zu liegen, dass Zeichenfolgen veränderbar sind, während Symbole unveränderlich sind, und Symbole auch "interniert" werden - was auch immer das bedeutet. Saiten sind in Ruby und Lisp zwar veränderlich, aber in Julia nicht, und dieser Unterschied ist eigentlich ein roter Hering. Die Tatsache, dass Symbole interniert werden, dh von der Sprachimplementierung für schnelle Gleichheitsvergleiche gehasht werden, ist ebenfalls ein irrelevantes Implementierungsdetail. Sie könnten eine Implementierung haben, die keine Symbole interniert, und die Sprache wäre genau dieselbe.
Was ist eigentlich ein Symbol? Die Antwort liegt in etwas, das Julia und Lisp gemeinsam haben - der Fähigkeit, den Code der Sprache als Datenstruktur in der Sprache selbst darzustellen. Einige Leute nennen dies "Homoikonizität" ( Wikipedia ), andere scheinen nicht zu glauben, dass allein eine Sprache ausreicht, um homoikonisch zu sein. Aber die Terminologie spielt keine Rolle. Der Punkt ist, dass eine Sprache, wenn sie ihren eigenen Code darstellen kann, eine Möglichkeit benötigt, Dinge wie Zuweisungen, Funktionsaufrufe, Dinge, die als Literalwerte geschrieben werden können usw. darzustellen. Sie benötigt auch eine Möglichkeit, ihre eigenen Variablen darzustellen. Das heißt, Sie benötigen eine Möglichkeit, die Daten
foo
auf der linken Seite als Daten darzustellen :Jetzt kommen wir zum Kern der Sache: Der Unterschied zwischen einem Symbol und einer Zeichenfolge ist der Unterschied zwischen
foo
auf der linken Seite dieses Vergleichs und"foo"
auf der rechten Seite. Auf der linken Seitefoo
befindet sich ein Bezeichner, der den Wert auswertet, derfoo
im aktuellen Bereich an die Variable gebunden ist . Auf der rechten Seite"foo"
befindet sich ein Zeichenfolgenliteral, das den Zeichenfolgenwert "foo" ergibt. Ein Symbol in Lisp und Julia ist, wie Sie eine Variable als Daten darstellen. Eine Zeichenfolge repräsentiert nur sich selbst. Sie können den Unterschied erkennen, indem Sie sicheval
bei ihnen bewerben :Was das Symbol
:foo
ergibt, hängt davon ab, an was - wenn überhaupt - die Variablefoo
gebunden ist, während es"foo"
immer nur "foo" ergibt . Wenn Sie in Julia Ausdrücke erstellen möchten, die Variablen verwenden, verwenden Sie Symbole (unabhängig davon, ob Sie sie kennen oder nicht). Beispielsweise:Was das abgelegte Zeug zeigt, ist unter anderem, dass sich
:foo
innerhalb des Ausdrucksobjekts ein Symbolobjekt befindet, das Sie durch Zitieren des Codes erhaltenfoo = "bar"
. Hier ist ein weiteres Beispiel für die Erstellung eines Ausdrucks mit dem:foo
in der Variablen gespeicherten Symbolsym
:Wenn Sie dies versuchen, wenn
sym
es an die Zeichenfolge gebunden ist,"foo"
funktioniert es nicht:Es ist ziemlich klar, warum dies nicht funktioniert - wenn Sie versucht haben,
"foo" = "bar"
von Hand zuzuweisen , funktioniert es auch nicht.Dies ist die Essenz eines Symbols: Ein Symbol wird verwendet, um eine Variable in der Metaprogrammierung darzustellen. Sobald Sie Symbole als Datentyp haben, wird es natürlich verlockend, sie für andere Zwecke zu verwenden, beispielsweise als Hash-Schlüssel. Dies ist jedoch eine zufällige, opportunistische Verwendung eines Datentyps, der einen anderen Hauptzweck hat.
Beachten Sie, dass ich vor einiger Zeit aufgehört habe, über Ruby zu sprechen. Das liegt daran, dass Ruby nicht homoikonisch ist: Ruby repräsentiert seine Ausdrücke nicht als Ruby-Objekte. Rubys Symboltyp ist also eine Art Überrestorgan - eine übrig gebliebene Adaption, die von Lisp geerbt wurde, aber nicht mehr für den ursprünglichen Zweck verwendet wird. Ruby-Symbole wurden für andere Zwecke kooptiert - als Hash-Schlüssel, um Methoden aus Methodentabellen zu ziehen -, aber Symbole in Ruby werden nicht zur Darstellung von Variablen verwendet.
Der Grund, warum Symbole in DataFrames anstelle von Zeichenfolgen verwendet werden, liegt darin, dass in DataFrames häufig Muster verwendet werden, um Spaltenwerte an Variablen innerhalb von vom Benutzer bereitgestellten Ausdrücken zu binden. Daher sind Spaltennamen natürlich Symbole, da Symbole genau das sind, was Sie zur Darstellung von Variablen als Daten verwenden. Derzeit müssen Sie schreiben,
df[:foo]
um auf diefoo
Spalte zuzugreifen. In Zukunft können Sie jedoch möglicherweise stattdessen darauf zugreifendf.foo
. Wenn dies möglich wird, können mit dieser praktischen Syntax nur auf Spalten zugegriffen werden, deren Namen gültige Bezeichner sind.Siehe auch:
quelle
eval(:foo)
und an einem andereneval(sym)
. Gibt es einen bedeutenden Unterschied zwischeneval(:foo)
undeval(foo)
?eval(:foo)
Gibt einen Wert an, an den die Variablefoo
gebunden ist, währendeval(foo)
Aufrufe diesen Wert aufrufen. Schreibeneval(:foo)
entspricht nurfoo
(im globalen Bereich) , soeval(foo)
ist wieeval(eval(:foo))
.