Clojure'un "sembollere" ek olarak neden "anahtar kelimeleri" var?


130

Geçmişten beri diğer Lisps (özellikle Scheme) hakkında geçici bir bilgim var. Son zamanlarda Clojure hakkında okuyorum . Hem "semboller" hem de "anahtar kelimeler" içerdiğini görüyorum. Bildiğim semboller, ancak anahtar kelimelerle değil.

Diğer Lisp'lerin anahtar kelimeleri var mı? Anahtar sözcükler, farklı gösterime (yani iki nokta üst üste) sahip olmaktan başka sembollerden nasıl farklıdır?


Yanıtlar:


139

Anahtar Kelimeler ve Semboller için Clojure belgeleri burada .

Anahtar kelimeler, kendilerini değerlendiren sembolik tanımlayıcılardır. Çok hızlı eşitlik testleri sağlarlar ...

Semboller, normalde başka bir şeye atıfta bulunmak için kullanılan tanımlayıcılardır. Program formlarında fonksiyon parametrelerine, let bağlamalarına, sınıf isimlerine ve global değişkenlere atıfta bulunmak için kullanılabilirler ...

Anahtar kelimeler genellikle hafif "sabit dizeler" olarak kullanılır, örneğin bir karma haritanın anahtarları veya bir çoklu yöntemin gönderme değerleri için. Semboller genellikle değişkenleri ve işlevleri adlandırmak için kullanılır ve makrolar ve benzeri durumlar dışında bunları doğrudan nesne olarak değiştirmek daha az yaygındır. Ancak, bir anahtar kelimeyi kullandığınız her yerde bir sembolü kullanmaktan sizi alıkoyan hiçbir şey yoktur (eğer her zaman alıntı yapmaktan çekinmezseniz).

Farkı görmek için en kolay yolu okumaktır Keyword.javave Symbol.javaClojure kaynağındaki. Birkaç bariz uygulama farkı vardır. Örneğin, Clojure'daki bir Sembol meta veriye sahip olabilir ve bir Anahtar Sözcük olamaz.

Tek iki nokta üst üste sözdizimine ek olarak, ad alanı nitelikli bir anahtar sözcük oluşturmak için çift iki nokta üst üste kullanabilirsiniz.

user> :foo
:foo
user> ::foo
:user/foo

Common Lisp, Ruby ve diğer dillerde olduğu gibi anahtar kelimelere sahiptir. Elbette bu dillerde biraz farklılar. Common Lisp anahtar kelimeleri ve Clojure anahtar kelimeleri arasındaki bazı farklılıklar:

  1. Clojure'daki anahtar kelimeler Sembol değildir.

    user> (symbol? :foo)  
    false
  2. Özel olarak nitelendirmediğiniz sürece anahtar kelimeler herhangi bir ad alanına ait değildir:

    user> (namespace :foo)
    nil
    user> (namespace ::foo)
    "user"

( Bakmam gereken şeyler hakkında bana fikir verdiği için Rainer Joswig'e teşekkürler .)


10
Bu , farklılıkların ne olduğunu açıklar , ancak neden iki farklı yapıya ihtiyaç duyulduğunu açıklamaz. Clojure, Keyword ve Symbol yeteneklerinin birleşimiyle bir şeyler yaratamaz mıydı?

25
Anahtar kelimeler hafiftir ve uygun bir sözdizimine sahiptir, bence hepsi bu kadar. Dil onlar olmadan da iyi çalışırdı, ancak sahip olmaları güzel ve çok yaygın olarak kullanılıyorlar. Yeteneklerinin bir birleşimine sahip olamazsınız çünkü Anahtar Kelimeler her zaman kendi kendini değerlendirir (yani, onları değişken veya işlev adları olarak kullanamazsınız) ve Semboller genel olarak her zaman kendi kendini değerlendiremez.
Brian Carper

1
: Anahtar kelimeler değerlendirdi kez onlar değişmez olarak hashmaps vb tuşları olarak daha faydalıdır görünüyor (eval (eval ':a))vs (eval (eval ''a)). Başka avantajları var mı? Performans açısından aynılar mı?
kristianlm

5
(aynı?: qwe: qwe) -> doğru. (aynı? 'qwe' qwe) -> yanlış. Semboller iç diziyi kullanır, bu nedenle karşılaştırma da hızlıdır.
desudesudesu

29

Common Lisp anahtar kelime sembollerine sahiptir.

Anahtar kelimeler de sembollerdir.

(symbolp ':foo) -> T

Anahtar kelimeleri özel yapan şey:

  • : foo, Common Lisp okuyucusu tarafından :: foo simge anahtar sözcüğü olarak çözümlenir
  • anahtar kelimeler kendi kendilerine değerlendirilir:: foo ->: foo
  • anahtar kelime sembollerinin ana paketi KEYWORD paketidir: anahtar kelime: foo ->: foo
  • anahtar kelimeler KEYWORD paketinden dışa aktarılır
  • anahtar kelimeler sabittir, farklı bir değer atanmasına izin verilmez

Aksi takdirde anahtar kelimeler sıradan sembollerdir. Böylece anahtar kelimeler işlevleri adlandırabilir veya özellik listelerine sahip olabilir.

Unutmayın: Common Lisp'de semboller bir pakete aittir. Bu şu şekilde yazılabilir:

  • foo, sembol geçerli pakette erişilebilir olduğunda
  • foo: bar, FOO sembolü BAR paketinden dışa aktarıldığında
  • foo :: bar, FOO sembolü BAR paketinde olduğunda

Anahtar kelime sembolleri için bunun anlamı: foo, anahtar kelime: foo ve anahtar kelime :: foo aynı semboldür. Bu nedenle, son iki gösterim genellikle kullanılmaz.

Yani: foo, sembol adından önce paket adı verilmemesinin varsayılan olarak KEYWORD paketi anlamına geldiği varsayılarak KEYWORD paketinde olacak şekilde ayrıştırılır.


6

Anahtar kelimeler kendi kendilerine değerlendirilen sembollerdir, bu yüzden onlardan alıntı yapmayı hatırlamanız gerekmez.


5
Öyle mi? Yazmak: '' yerine büyük bir kazanç gibi görünmüyor, özellikle çünkü: çoğu klavyede fazladan bir tuşa basılmasıdır.
Laurence Gonsalves

11
Aslında, karakterden çok daha fazlası. Anahtar kelimeler değerlendirmeden sonra anahtar kelimeler olarak kalır, semboller ise bağlandıkları şeyle değerlendirilir. Daha çok anlamsal bir farklılık gibidir, çünkü bunlar genellikle farklı amaçlar için kullanılır.
Greg Hewgill

13
Clojure'da anahtar kelimeler sembol değildir
David Plumpton

4

: Anahtar sözcükler ayrıca koleksiyonların çoğu tarafından özel olarak ele alınır ve gerçekten kullanışlı bir söz dizimi sağlar.

(:user-id (get-users-map))

aynıdır

((get-users-map) :user-id)

bu işleri biraz daha esnek hale getirir


21
Bu aynı zamanda semboller için de geçerlidir, ('a {' a 1 'b 2}) => 1 ve ({' a 1 'b 2}' b) => 2.
Jonas

4

Anahtar kelimeler için, anahtar kelime ilk oluşturulduğunda hash değerleri hesaplanır ve önbelleğe alınır. Bir anahtar kelimeyi karma anahtar olarak ararken, önceden hesaplanmış karma değeri döndürür. Dizeler ve semboller için, karma her aramada yeniden hesaplanır.

Aynı adlandırılmış anahtar kelimelerin neden her zaman aynı olduğu, kendi hash değerlerini içerirler. Haritalarda ve kümelerde arama, karma anahtarlardan yapıldığından, bu, aramanın kendisinde değil, çok sayıda arama durumunda daha iyi arama verimliliğini kapsar.


0

Anahtar kelimeler geneldir , semboller değildir .

Bu örnek JavaScript'te yazılmıştır, ancak umarım bu noktayı taşımanıza yardımcı olur.

const foo = Symbol.for(":foo") // this will create a keyword
const foo2 = Symbol.for(":foo") // this will return the same keyword
const foo3 = Symbol(":foo") // this will create a new symbol
foo === foo2 // true
foo2 === foo3 // false

SymbolFonksiyonu kullanarak bir sembol oluşturduğunuzda, her seferinde ayrı / özel bir sembol elde edersiniz. Symbol.forFonksiyon aracılığıyla bir sembol istediğinizde, her seferinde aynı sembolü geri alacaksınız.

(println :foo) ; Clojure
System.out.println(RT.keyword(null, "foo")) // Java
console.log(System.for(":foo")) // JavaScript

Bunların hepsi aynı.


İşlev bağımsız değişken adları yereldir. yani anahtar kelimeler değil.

(def foo (fn [x] (println x))) ; x is a symbol
(def bar (fn [x] (println x))) ; not the same x (different symbol)
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.