close

Palyaço

Navigasyona git Aramaya git
palyaço
Clojure logosu.svg
Geliştirici(ler)
Richard Hickey
https://clojure.org/
Genel bilgi
Ortak Uzantılar clj, cljs, cljc, edn ve cljr
paradigma Fonksiyonel , Çok paradigmalı programlama dili
Ortaya çıkan 2007
Tarafından dizayn edilmiştir zengin hickey
En son kararlı sürüm (2022-03-22)
tip sistemi dinamik , güçlü
uygulamalar JVM , CLR , JavaScript
tarafından etkilenmiş Lisp , ML , Haskell , Erlang Prolog
İşletim sistemi Çoklu platform
Lisans Eclipse Kamu Lisansı

Clojure , Lisp'in genel amaçlı bir programlama dili lehçesidir . Eşzamanlı programlama ile ilişkili karmaşıklığı ortadan kaldırmak amacıyla (diğerlerinin yanı sıra) işlevsel paradigmaya özel bir vurgu yapar . Clojure , Java Sanal Makinesi ve .NET platformu sanal makinesi üzerinde çalıştırılabilir ve JavaScript'e derlenebilir .

İlkeler

Rich Hickey , Clojure'un gelişimini, bulamadığı bir dili aramak olarak tanımlar: varsayılan olarak çalışan bir lisp , kendi platformu yerine sağlam bir ortamın üzerine inşa edilmiş ve akılda eşzamanlı programlama ile. [ 1 ]

Benzer şekilde, nesne yönelimi ilke olarak reddedilir ve programların veri temsilini ve davranışı karıştıran değişken varlıklar arasındaki etkileşimden ziyade işlevlerin veriye uygulanması olarak ifade edildiği bir yaklaşım sunar. Öte yandan, somutlaştırılabilirlik, polimorfizm ve arayüzler gibi özellikler, etkin bir şekilde dilin bir parçasıdır.

Sözdizimi

Lisp ailesinin geri kalanı gibi, Clojure'un sözdizimi de derlenmeden önce bir okuyucu tarafından veri yapılarına dönüştürülen sembolik ifadeler üzerine kuruludur . İfadeler, parantezlerle sınırlandırılarak ve her bir listenin ilk üyesinin bir işlev olarak çağrıldığı ve diğer üyeleri argüman olarak ilettiği önek gösterimleriyle karakterize edilir.

C programlama dilinin sözdizimine dayanan en popüler dillere alışkın olanlar için garip olan bu özellik, esnekliğinin temelidir. Haritalar , kümeler ve vektörler gibi veri yapılarının değişmez bir ifadesi vardır; derleyici tarafından oluşturulan sözdizimi ağacına dahil edildiklerinde herhangi bir dönüşüm gerektirmezler. Clojure bir Lisp-1'dir ve özellikle diğer lisplerle uyumlu olacak şekilde tasarlanmamıştır .

Makro

Makro , diğer ifadeleri değerlendirmeden argüman olarak kabul eden, değerlendirmeden önce dönüştüren bir kod parçasıdır . Bu, "programlar oluşturan programların" ortaya çıkmasına izin verir: dile - akış kontrol yapılarına eklemeler - veya alana özgü bir dilin oluşturulması . İlke olarak, bir derleyici geliştirmeye başvurmadan diğer dil ailelerinde elde edilemeyen olanaklar .

Clojure'un makro sistemi, Clojure'un backquote versiyonunun ("sözdizimsel alıntı" olarak adlandırılır) sembolleri ait oldukları ad alanı ile nitelendirmesi dışında Common Lisp'inkine çok benzer . Bu, ad nitelikli bağlamalar yasaklandığından, kasıtsız yakalamayı önlemeye yardımcı olur . Onları yakalayan bir makronun genişlemesini zorlamak mümkündür, ancak bunun açıkça yapılması gerekir. Clojure, geçerli adlara aktarılan diğer ad alanlarındaki genel adların yeniden bağlanmasını da yasaklar.

Sözdizimsel alıntının bir başka özelliği de, bir listenin hangi üyelerinin alıntıyı kaldırma (~) ve alıntıyı kaldırma-ekleme (~@) operatörlerini kullanarak değerlendirilmesi gerektiğini belirleyebileceğiniz bir şablonlama sistemine izin vermesidir . yönetilebilir.

Dil özellikleri

  • Bir değerlendirme konsolu ile dinamik geliştirme ( REPL: değerlendirme yazdırma döngüsünü okuyun ).
  • Fonksiyonların değerler olarak temsil edilmesi ve yan etkilere dayalı olarak yineleme yerine daha yüksek dereceli fonksiyonların kullanımı ve özyineleme tercihi .
  • Tamsayı olmayan bölümlerde oluşturulan keyfi kesinlik sayıları ve kesirlerin gerçek temsili.
  • Tembel değerlendirmeli diziler (dizinin öğeleri, ihtiyaç duyulana kadar hesaplanmaz, bu da potansiyel olarak sonsuz kümelerin temsil edilmesine izin verir).
  • Kalıcı ve değişmez veri yapılarının entegre sistemi .
  • İşlem sistemleri, aracılar ve yerel bağlamalar aracılığıyla eşzamanlılık durumlarında durum kontrolü (bir varlığın zaman içinde elde edebileceği değerler kümesi ) .
  • Java ile etkileşim : Clojure ile yazılan uygulamalar JVM bytecode'a derlenerek , uygulama sunucularına veya diğer Java ortamlarına çok az ek karmaşıklıkla kolayca entegre edilebilir. Bu taşınabilirliği sağlamak için gereken çabaları en aza indirmek için sınıf, veri yapısı ve eşzamanlılık düzeyindeki tüm olası arabirimler varsayılan olarak uygulanır.

Örnekler

Merhaba dünya . REPL'nin doğası gereği, bir yazdırma komutunun gerekli olmadığını unutmayın .

"Selam Dünya!"

Eşzamanlı aramaları destekleyen benzersiz ve ardışık bir numara üreteci:

( let  [i  ( atom  0 ) ] 
  ( defn create  -unique-id 
    "Her çağrı için farklı bir sayısal tanımlayıcı döndürür." 
    [] 
    ( takas!  i  inc )))

Bunun anonim bir alt sınıfı java.io.Writerhiçbir yere yazmaz ve onunla değerlendirilen tüm ifadeleri susturmak için onu kullanan bir makro.

( def  bit-bucket-writer 
  ( proxy  [java.io.Writer]  [] 
    ( [buf] nil yaz  ) ( [] nil kapat ) ( flush [] nil ))) 
         
         

( defmacro  noprint 
  "Verilen ifadeyi tüm baskılar *out* sessize alınarak değerlendirir."   
  [&  formlar] 
  ` ( bağlayıcı  [*out*  bit-bucket-writer] 
     ~@forms ))

( noprint 
 ( println  "Merhaba, kimse!" ))

Bu örnekte on iş parçacığı, on ardışık başlangıç ​​benzersiz numarası içeren yüz vektörden oluşan paylaşılan bir veri yapısını manipüle eder. Her iş parçacığı, iki rastgele vektörde iki rastgele konum seçer ve bunları değiştirir. Vektörlerdeki tüm değişiklikler, Clojure'un yazılım işlemsel bellek sistemi kullanılarak işlemler içinde yapılır. Bu yüzden bin yinelemeden sonra bile hiçbir sayı kaybolmaz.

( defn  run  [nvecs  nitems  nthreads  niters] 
  ( let  [vec-refs  ( vec  ( map  ( comp  ref  vec ) ) 
                           ( partition  nitems  ( range  ( *  nvecs  nitems ))))) 
        takas  #( let  [v1  ( rand-int  nvecs ) 
                    v2  ( rand-int  nvecs ) 
                    i1  ( rand-int  nitems ) 
                    i2  ( rand-int  nitems ) ] 
                ( dosync 
                 ( let  [temp  ( nth  @ ( vec-refs  v1 )  i1 ) ] 
                   ( alter  ( vec-refs  v1 )  asoc  i1  ( nth  @ ( vec-refs  v2 )  i2 )) 
                   ( alter  ( vec-refs  v2 )  assoc  i2  temp )))) 
        rapor  #( do 
                 ( prn  ( map  deref  vec-refs )) 
                 ( println  "Ayırt:" 
                          ( sayım  ( farklı  ( concat uygula  ( map deref vec-refs )))))) ] ( rapor ) ( dorun ( pcalls uygula ( tekrar nthreads # ( dotimes [_ niters] ( takas )))) ( rapor )))   
    
            
    

( 100 10 10 100000 çalıştırın  )   

Önceki örneğin çıktısı:

( [0  1  2  3  4  5  6  7  8  9]  [10  11  12  13  14  15  16  17  18  19]  ... 
 [990  991  992  993  994  995  996  997  998  999] ) 
Farklı:  1000
 
( [382  318  466  963  619  22  21  273  45  596]  [808  639  804  471  394  904  952  75  289  778]  ... 
 [484  216  622  139  651  592  379  228  242  355] ) 
Fark:  100ct

Bibliyografya

Dış bağlantılar

Referanslar

  1. ^ "Temel ilkeler" . Zengin Hickey (İngilizce) . 2008-10-17 alındı, bunun paradigması yok .