Julia'da "sembol" nedir?


132

Spesifik olarak: Julia'nın DataFrames paketini, özellikle de names seçeneğiyle readable () işlevini kullanmaya çalışıyorum, ancak bu, bir simge vektörü gerektirir.

  • sembol nedir?
  • neden bunu bir dizi vektörü yerine seçsinler?

Şimdiye kadar Julia dilinde kelime sembolüne sadece birkaç referans buldum. Görünüşe göre semboller ": var" ile temsil ediliyor, ancak ne oldukları bana açık değil.

Kenara: koşabilirim

df = readtable( "table.txt", names = [symbol("var1"), symbol("var2")] )

İki madde işaretli sorum hala geçerli.


3
Bu konuyla ilgili bazı konuşmalar burada bulunabilir: groups.google.com/d/msg/julia-users/MS7KW8IU-0o/cQ-yDOs_CQEJ
jverzani

Yanıtlar:


232

Julia'daki semboller Lisp, Scheme veya Ruby'deki ile aynıdır. Bununla birlikte, ilgili soruların cevapları bence pek tatmin edici değil . Bu cevapları okursanız, bir sembolün bir dizeden farklı olmasının nedeni, dizelerin değişebilirken sembollerin değişmez olması ve sembollerin de "iç içe geçmiş" olmasıdır - bu ne anlama geliyorsa. Dizeler Ruby ve Lisp'te değiştirilebilir, ancak Julia'da değiller ve bu fark aslında bir kırmızı ringa balığı. Sembollerin iç içe geçmesi - yani hızlı eşitlik karşılaştırmaları için dil uygulaması tarafından karma hale getirilmesi - aynı zamanda alakasız bir uygulama ayrıntısıdır. İç semboller içermeyen bir uygulamaya sahip olabilirsiniz ve dil tamamen aynı olacaktır.

Peki sembol nedir, gerçekten? Cevap Julia ve Lisp'in ortak bir noktasında yatıyor - dilin kodunu dilin kendisinde bir veri yapısı olarak gösterme yeteneği. Bazı insanlar buna "homoikoniklik" ( Wikipedia ) diyorlar , ancak diğerleri, bir dilin homoikonik olması için tek başına yeterli olduğunu düşünmüyor. Ancak terminoloji gerçekten önemli değil. Mesele şu ki, bir dil kendi kodunu temsil edebildiğinde, atamalar, işlev çağrıları, değişmez değerler olarak yazılabilen şeyler gibi şeyleri temsil etmek için bir yola ihtiyaç duyar. Ayrıca kendi değişkenlerini temsil etmenin bir yoluna ihtiyaç duyar. Yani, foobunun sol tarafındaki verileri - veri olarak - temsil etmenin bir yoluna ihtiyacınız var :

foo == "foo"

Şimdi konunun özüne geliyoruz: bir sembol ile bir dizi arasındaki fark foo, bu karşılaştırmanın sol tarafı ile "foo"sağ taraf arasındaki farktır . Solda foobir tanımlayıcı var ve foogeçerli kapsamdaki değişkene bağlı değeri değerlendiriyor . Sağda, "foo"bir dize değişmezidir ve "foo" dize değeri olarak değerlendirilir. Hem Lisp hem de Julia'daki bir sembol, bir değişkeni veri olarak nasıl temsil ettiğinizdir. Bir dize sadece kendini temsil eder. evalOnlara uygulayarak farkı görebilirsiniz :

julia> eval(:foo)
ERROR: foo not defined

julia> foo = "hello"
"hello"

julia> eval(:foo)
"hello"

julia> eval("foo")
"foo"

Sembolün neyi :foodeğerlendireceği, değişkenin foobağlı olduğu şeye bağlıdır - eğer varsa - , oysa "foo"her zaman sadece "foo" olarak değerlendirilir. Julia'da değişkenler kullanan ifadeler oluşturmak istiyorsanız, o zaman semboller kullanıyorsunuz (bilseniz de bilmeseniz de). Örneğin:

julia> ex = :(foo = "bar")
:(foo = "bar")

julia> dump(ex)
Expr
  head: Symbol =
  args: Array{Any}((2,))
    1: Symbol foo
    2: String "bar"
  typ: Any

Dışarı atılan şey, diğer şeylerin yanı sıra :foo, kodu alıntı yaparak elde ettiğiniz ifade nesnesinin içinde bir sembol nesnesi olduğunu gösterir foo = "bar". İşte :foodeğişkende depolanan sembolle bir ifade oluşturan başka bir örnek sym:

julia> sym = :foo
:foo

julia> eval(sym)
"hello"

julia> ex = :($sym = "bar"; 1 + 2)
:(begin
        foo = "bar"
        1 + 2
    end)

julia> eval(ex)
3

julia> foo
"bar"

Bunu symdizeye bağlıyken yapmaya çalışırsanız "foo", işe yaramaz:

julia> sym = "foo"
"foo"

julia> ex = :($sym = "bar"; 1 + 2)
:(begin
        "foo" = "bar"
        1 + 2
    end)

julia> eval(ex)
ERROR: syntax: invalid assignment location ""foo""

Bunun neden işe yaramayacağını görmek oldukça açık - "foo" = "bar"elle atamayı denediyseniz , işe yaramayacak.

Bu, bir sembolün özüdür: Bir sembol, meta programlamada bir değişkeni temsil etmek için kullanılır. Veri türü olarak sembollere sahip olduğunuzda, elbette, bunları karma anahtarlar gibi başka şeyler için kullanmak cazip hale gelir. Ancak bu, başka bir birincil amacı olan bir veri türünün tesadüfi, fırsatçı bir kullanımıdır.

Bir süre önce Ruby hakkında konuşmayı bıraktığımı unutmayın. Bunun nedeni, Ruby'nin homoiconic olmamasıdır: Ruby, ifadelerini Ruby nesneleri olarak temsil etmez. Yani Ruby'nin sembol türü, bir tür körelmiş organdır - Lisp'ten miras kalan, ancak artık orijinal amacı için kullanılmayan artık bir uyarlama. Ruby sembolleri, metot tablolarından metotları çıkarmak için hash anahtarları olarak başka amaçlar için birlikte seçilmiştir, ancak Ruby'deki semboller değişkenleri temsil etmek için kullanılmaz.

Sembollerin neden dizeler yerine DataFrames'te kullanıldığına gelince, bunun nedeni DataFrames'te sütun değerlerini kullanıcı tarafından sağlanan ifadelerin içindeki değişkenlere bağlamak için yaygın bir model olmasıdır. Bu nedenle sütun adlarının sembol olması doğaldır, çünkü semboller tam olarak değişkenleri veri olarak temsil etmek için kullandığınız şeydir. Şu anda, sütuna df[:foo]erişmek için yazmak zorundasınız foo, ancak gelecekte df.foobunun yerine ona erişmeniz mümkün olabilir . Bu mümkün olduğunda, yalnızca adları geçerli tanımlayıcılar olan sütunlara bu uygun sözdizimi ile erişilebilir.

Ayrıca bakınız:


6
Interning: Bilgisayar biliminde, string interning, her bir farklı dize değerinin yalnızca bir kopyasını saklamanın bir yöntemidir ve bu, değişmez olmalıdır. Interning stringler, bazı string işleme görevlerini daha fazla zaman veya alan açısından verimli hale getirirken, string oluşturulduğunda veya interned olduğunda daha fazla zaman gerektirir. en.wikipedia.org/wiki/String_interning
xiaodai

Bir noktada yazarsın eval(:foo), diğerinde eval(sym). eval(:foo)Ve arasında anlamlı bir fark var mı eval(foo)?
Grayscale

1
Çok fazla: eval(:foo)değişkenin foobağlı eval(foo)olduğu değeri verirken, çağrılar bu değer üzerinden değerlendirilir. Yazmak eval(:foo)sadece foo(küresel kapsamda) eval(foo)ile aynıdır eval(eval(:foo)).
StefanKarpinski
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.