Clojure'un bir sınıfı tanımlamak için neden tek bir sınıf yerine 5 yolu var?


84

Clojure, yeni sınıf benzeri veri türlerini tanımlamak için gen sınıfı, reify, proxy ve ayrıca deftype ve defrecord'a sahiptir. Sözdizimsel sadeliğe değer veren ve gereksiz karmaşıklığı reddeden bir dil için bu bir sapma gibi görünüyor. Birisi neden böyle olduğunu açıklayabilir mi? Common Lisp tarzı defclass yeterli olabilir mi?

Yanıtlar:


91

Bu, üç farklı faktörün bir karışımıdır:

  1. Jvm'nin belirli tip sistemi
  2. Türleri tanımlarken farklı kullanım durumları için biraz farklı anlambilim ihtiyacı
  3. Dil geliştikçe bunlardan bazılarının daha önce ve bazılarının daha sonra geliştirildiği gerçeği.

İlk önce bunların ne işe yaradığını düşünelim. deftype ve gen-class , önceden derleme için adlandırılmış bir sınıf tanımlaması açısından benzerdir. Gen sınıfı önce geldi, ardından clojure 1.2'de deftype geldi. Deftype tercih edilir ve daha iyi performans özelliklerine sahiptir, ancak daha kısıtlayıcıdır. Deftype sınıfı bir arabirime uyabilir ancak başka bir sınıftan miras alamaz.

Reify ve proxy , çalışma zamanında anonim bir sınıfın bir örneğini dinamik olarak oluşturmak için kullanılır. Proxy önce geldi, reify deftype ile geldi ve clojure 1.2'de defrecord. Reify, tıpkı deftype gibi, anlambilimin fazla kısıtlayıcı olmadığı durumlarda tercih edilir.

Bu, aynı anda ortaya çıktıkları ve benzer bir role sahip oldukları için neden hem deftype hem de defrecord sorusunu bırakıyor. Çoğu amaç için defrecord kullanmak isteyeceğiz: bildiğimiz ve sevdiğimiz tüm çeşitli clojure iyiliğine, sıralanabilirliğe ve benzerlerine sahip. Deftype, diğer veri yapılarının uygulanması için düşük seviyeli bir yapı taşı olarak kullanılmak üzere tasarlanmıştır. Normal clojure arayüzlerini içermez, ancak değiştirilebilir alanlar seçeneğine sahiptir (ancak bu varsayılan değildir).

Daha fazla okumak için kontrol edin:

Clojure.org veri türleri sayfası

Deftype ve reify'ın tanıtıldığı google grup dizisi


1
Google grup dizisi çok değerliydi. Anladığım kadarıyla java-interop proxy, gen-class'ın yerini çoğunlukla reify ve deftype alıyor. Şu anda türleri tanımlamak için daha az 'önerilen' yolumuz olmasına sevindim.
Salil

2
@ Trylks: Nesneyi bir anahtar-değer çiftleri dizisi olarak işleme yeteneği. Clojure için doğal olan hemen hemen her şey, çok güçlü bir sekans olarak ele alınabilir.
Rob Lachlan

proxyçalışma zamanında yöntemlerin değiştirilmesine izin verdiği için bazen tercih edilir. (örneğin The Joy of Clojure , 2. baskı, bunun bir web işleyicisindeki geri aramaları değiştirmek için kullanışlı olabileceğini öne sürüyor.)
Mars

52

Kısa cevap, hepsinin farklı ve faydalı amaçları olduğudur. Karmaşıklık, temeldeki JVM'nin farklı özellikleriyle etkili bir şekilde birlikte çalışma ihtiyacından kaynaklanmaktadır.

Herhangi bir Java birlikte çalışmasına ihtiyacınız yoksa , zamanın% 99'unda defrecord veya basit bir Clojure haritasına bağlı kalmaktan en iyisi olur.

  • Protokolleri kullanmak istiyorsanız defrecord kullanın
  • Aksi takdirde, normal bir Clojure haritası muhtemelen en basit ve anlaşılırdır

İhtiyaçlarınız daha karmaşıksa, aşağıdaki akış şeması neden bu seçeneklerden birini diğerlerine göre seçeceğinizi açıklamak için harika bir araçtır:

http://cemerick.com/2011/07/05/flowchart-for-choosing-the-right-clojure-type-definition-form/

Doğru clojure türü tanımlama formunu seçmek için akış şeması


1
akış şemasına bağlantı için çok teşekkürler. Blogun O'reilly's - Programming Clojure'un ortak yazarı olmasına yardımcı olur. Bence bu karar verme süreci oldukça karmaşık. Arayüz ve somut sınıf arasındaki farklar ya da statik yöntemler tanımlama ihtiyacı ya da tanımlanmamış ya da adlandırılmış tür ya da anonim tür o kadar büyük ki farklı bir dil yapısına ihtiyaç duyuyorlar mı?
Salil

4
farklılıklar çok büyük değildir, ancak başarmaya çalıştığınız şey açısından felsefi olarak farklıdırlar . Clojure'daki çoklu yaklaşımların bu temel farklılıkları yansıttığını düşünüyorum, bu da onlara farklı adlar verilmesinin iyi bir nedenidir.
mikera

Akış şeması harika, ancak bir veya daha fazla seçeneği veya bunların kombinasyonlarını kullanmak için tüm olasılıkları veya nedenleri kapsamıyor. Basit bir çizelge yapamaz.
Mars
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.