Clojure ad alanını birden çok dosyaya bölme


91

İle önceden derleme yaparken bir Clojure ad alanını birden çok kaynak dosyaya bölmek mümkün müdür :gen-class? Nasıl oynanır (:main true)ve (defn- ...)devreye girer?

Yanıtlar:


138

Genel Bakış

Kesinlikle yapabilirsiniz, aslında clojure.coread alanının kendisi bu şekilde bölünmüştür ve içine bakarak takip edebileceğiniz iyi bir model sağlar src/clj/clojure:

core.clj
core_deftype.clj
core_print.clj
core_proxy.clj
..etc..

Tüm bu dosyalar, tek clojure.coread alanını oluşturmak için katılır .

Birincil Dosya

Bunlardan biri, ad alanı adıyla eşleşecek şekilde adlandırılan birincil dosyadır, böylece birisi bir :useveya içinde ondan bahsettiğinde bulunacaktır :require. Bu durumda ana dosya olur clojure/core.cljve bir nsformla başlar . Bu, diğer dosyalarınızın hangisine ihtiyaç duyduğuna bakılmaksızın, tüm ad alanı yapılandırmanızı koymanız gereken yerdir . Bu, normalde aşağıdakileri :gen-classde içerir , yani aşağıdaki gibi bir şey

(ns my.lib.of.excellence
  (:use [clojure.java.io :as io :only [reader]])
  (:gen-class :main true))

Daha sonra, birincil dosyanızın uygun yerlerinde (en yaygın olarak tümü sonunda) loadyardımcı dosyalarınızı getirmek için kullanın . Şöyle clojure.coregörünüyor:

(load "core_proxy")
(load "core_print")
(load "genclass")
(load "core_deftype")
(load "core/protocols")
(load "gvec")

Önek olarak geçerli dizine veya .cljson eke ihtiyacınız olmadığını unutmayın .

Yardımcı dosyalar

Yardımcı dosyaların her biri, yardım ettikleri ad alanını bildirerek başlamalı, ancak bunu in-nsişlevi kullanarak yapmalıdır . Dolayısıyla, yukarıdaki örnek ad alanı için yardımcı dosyaların tümü şununla başlar:

(in-ns 'my.lib.of.excellence)

Tüm gereken bu.

gen sınıfı

Tüm bu dosyalar tek bir ad alanı oluşturduğundan, tanımladığınız her işlev birincil veya yardımcı dosyalardan herhangi birinde olabilir. Bu, elbette, istediğiniz gen-classherhangi bir dosyada işlevlerinizi tanımlayabileceğiniz anlamına gelir :

(defn -main [& args]
  ...)

Clojure'un normal tanımlama sırası kurallarının hala tüm işlevler için geçerli olduğuna dikkat edin, bu nedenle, o işlevi kullanmaya çalışmadan önce , bir işlevi tanımlayan dosya ne olursa olsun , yüklendiğinden emin olmanız gerekir .

Özel Vars

Ayrıca (defn- foo ...)bir ad-alanı-özel işlevi tanımlayan formu da sordunuz . Bunun gibi tanımlanan işlevler ve diğer :privatedeğişkenler, tanımlandıkları ad alanı içinden görülebilir, bu nedenle birincil ve tüm yardımcı dosyalar, şimdiye kadar yüklenen dosyalardan herhangi birinde tanımlanan özel değişkenlere erişebilir.


3
Çok güzel, eksiksiz cevap! BTW, The Joy of Clojure'den ilk geçişimi neredeyse bitirdim . Harika kitap!
Ralph

Bu cevabı paylaştığınız için teşekkürler. 2 yıl sonra hala iyi bir uygulama olarak kabul ediliyor mu? (İşlerin hızlı değiştiğini biliyorum.) Clojure'un hala bu tekniği kullandığını görüyorum.
David J.

9
Birden çok dosyanın tek bir ad alanı oluşturmasını istediğinizden eminseniz, bugün itibariyle bu hala en iyi uygulamadır. Ancak, bu artık eskisinden daha az yaygın olabilir. Bir alternatif, n'lerinizin tüm genel değişkenlerini tek bir dosyada tanımlamak ve tüm yardımcı değişkenleri ve işlevleri ayrı bir "uygulama" ad alanına taşımak olabilir. İmpl'deki değişkenler teknik olarak herkese açık olacaktır, ancak belgelenen API'nin parçası olmadıklarını belirten bir ns dokümanı yaygındır ve yeterli olmalıdır.
Chouser

1
Herhangi bir yaygın Clojure aracının çok dosyalı ad alanlarını anlamada sorun yaşayıp yaşamadığını biliyor muyuz? Lein? Çizme? Elmadan yapılan bir içki? NREPL? Kibit? Eastwood? Örtü mü? Etc ...
Didier A.
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.