2019-01-21 17:40:29 +03:00
---
language: clojure
2019-02-11 02:56:03 +03:00
lang: tr-tr
2019-02-01 10:33:52 +03:00
filename: learnclojure-tr.clj
2019-01-21 17:40:29 +03:00
contributors:
2019-02-03 04:34:27 +03:00
- ["Adam Bard", "http://adambard.com/"]
2019-08-20 09:45:22 +03:00
- ["Seçkin KÜKRER", "https://leavenha.github.io"]
2019-02-01 10:33:52 +03:00
translators:
2019-01-21 17:40:29 +03:00
- ["Seçkin KÜKRER", "https://leavenha.github.io"]
---
2019-02-01 10:33:52 +03:00
[JVM]: https://tr.wikipedia.org/wiki/Java_sanal_makinesi
2019-01-21 17:40:29 +03:00
[STM]: https://en.wikipedia.org/wiki/Software_transactional_memory
Clojure, Lisp dialekti, barı nan bir dildir. [JVM][JVM] üzerinde barı nı yor. Clojure, Lisp'in tüm gücü ve kendi mantalitesi ile mükemmel bir genel-amaçlı programlama dilidir. Clojure, Eş-zamanlı programlama, Makrolar, Fonksiyonel Programlama, Tembel yapı lar ve daha fazlası nı vaadediyor.
(Bu örnekleri çalı ştı rmak için Clojure 1.2 versionu veya daha yenisine sahip olmalı sı nı z.)
```clojure
; Noktalı Virgül, satı rı yorumlamak için kullanı lı r.
; Clojure programları formlardan meydana gelir,
; Parantezlerle çevirili değerler, boşluk ile ayrı lı r. --Virgül ile değil--
;
; Clojure okuyucusu*, listedeki ilk elemanı çağı rı lacak bir fonksiyon
; Veya makro, geri kalan ifadeleri o çağı rı ma argüman olarak kabul eder.
;
; Bir dosyadaki ilk çağı rı m isim-uzayı tanı mlamak için `ns` olmalı .
(ns clojure-öğren)
;
; Bir diğer yorumlama seçeneği de, ifade-içi. Bu diyez (`#`), ve alt çizgi
; İle başlar ve herhangi bir s-ifade'ye uygulanabilir.
;
#_(bu çağı rı m değerlendirilmeyecektir)
; Öncelikle fonksiyon çağı rı mları ve temel işlemler:
; Örnek bir fonksiyon çağı rı mı :
; (örnek-bir-fonksiyon ilk-argüman ikinci-argüman)
; `str` aldı ğı argümanları bir karakter katarı olarak geri verir.
(str "Merhaba" " " "dünya!") ; => "Merhaba dünya!"
; Matematik, oldukça sezgisel ve basit
(+ 1 1) ; => 2
(- 2 1) ; => 1
(* 1 2) ; => 2
(/ 2 1) ; => 2
; Eşitlik için `=`
(= 1 1) ; => true
(= 2 1) ; => false
; `not` beklediğiniz gibi, mantı ksal ifadeleri tersine çevirir.
(not true) ; => false
; Clojure formları , iç-içe çağı rı labilir
; Değerlendirilen çağı rı mlar bir üst form'a argüman
; Olarak verilir.
(+ 1 (- 3 2)) ; = 1 + (3 - 2) => 2
; Tipler
;;;;;;;;;;;;;
; Clojure, Java'nı n temel tipleri olan mantı ksal (boolean),
; Tam sayı lar (int) ve karakter katarları nı (string) kullanı r.
; Değerleri denetlemek için `class` fonksiyonunu kullanı n.
(class 1) ; Tam sayı sabitleri ön-tanı mlı olarak `java.lang.Long` ile tanı mlanı r.
(class 1.); Kayan noktalı sayı sabitleri
; Ön-tanı mlı olarak `java.lang.Double` ile tanı mlanı r.
(class ""); Karakter katarı sabitleri her zaman, --sadece-- çift tı rnak
; ile tanı mlanı r ve ön-tanı mlı olarak `java.lang.String` tipindedir.
(class false) ; Mantı ksal değer sabitleri, `java.lang.Boolean` .
(class nil); "Null", (tanı msı z) değerler `nil` ile tanı mlanı r.
; Clojure okuyucusu her paranter ifadesini bir çağı rı m olarak
; değerlendirdiğinden bir liste tanı mlamak için çağı rı mı durdurmalı yı z.
'(+ 1 2) ; => (+ 1 2)
; ((quote (+ 1 2)) için bir kı sa yoldur)
; Alı ntı lanmı ş listeleri çağı rabilirsiniz.
(eval '(+ 1 2)) ; => 3
; Koleksiyonlar ve Ardı şı klar
;;;;;;;;;;;;;;;;;;;
; Listeler bağlı -liste veri yapı sı ,
; Vektörler dizi altyapı sı kullanı r.
(class '(1 2 3)); => clojure.lang.PersistentList
(class [1 2 3]); => clojure.lang.PersistentVector
; Bir liste `(1 2 3)` şeklinde gösterilebilir, yazı labilir.
; Fakat bu listeyi, Alı ntı lamalı yı z --Quote--.
; Bu, onu bir fonksiyon çağı rı mı olarak değil,
; bir liste olarak değerlendirilmesini sağlayacaktı r.
; Ayrı ca, `(list 1 2 3)` tamamen `'(1 2 3)` ifadesi ile
; eşdeğerdir.
; 'Koleksiyonlar' sadece bir veri grubudur.
; Vektörler ve Listeler, koleksiyondur:
(coll? '(1 2 3)) ; => true
(coll? [1 2 3]) ; => true
; 'Ardı şı klar' (seqs), bir veri listesinin soyut tanı mlaması dı r.
; Sadece listeler ardı şı ktı r.
(seq? '(1 2 3)) ; => true
(seq? [1 2 3]) ; => false
; Bir ardı şı k, ulaşı ldı ğı nda sadece giriş verisi vermelidir.
; Yani, ardı şı klar tembel olabilir. | Sonsuz ardı şı klar tanı mlanabilir.
(range 4) ; => (0 1 2 3)
(range) ; => (0 1 2 3 4 ...) (sonsuz bir ardı şı k)
(take 4 (range)) ; (0 1 2 3)
; Bu yapı larda ekleme işlemi için `cons` kullanı lı r.
(cons 4 [1 2 3]) ; => (4 1 2 3)
(cons 4 '(1 2 3)) ; => (4 1 2 3)
; `conj` bir koleksiyona en verimli şekilde veri ekler.
; Bu, listeler için liste başı na, vektörler için ise vektör sonuna demektir.
(conj [1 2 3] 4) ; => [1 2 3 4]
(conj '(1 2 3) 4) ; => (4 1 2 3)
; `concat` koleksiyonları birleştirmek için kullanı lı r.
(concat [1 2] '(3 4)) ; => (1 2 3 4)
; `filter` ve `map` koleksiyonlarla işlem yapmak için
; ön-tanı mlı yüksek-seviyeli fonksiyonlardı r.
;
; ps: `inc` argümanı nı bir arttı ran bir fonksiyon.
(map inc [1 2 3]) ; => (2 3 4)
(filter even? [1 2 3]) ; => (2)
; Koleksiyonları indirgemek için `reduce` kullanı lı r.
(reduce + [1 2 3 4])
; = (+ (+ (+ 1 2) 3) 4)
; => 10
; Reduce, bir ilk-tanı m değeri alabilir.
(reduce conj [] '(3 2 1))
; = (conj (conj (conj [] 3) 2) 1)
; => [3 2 1]
; Fonksiyonlar
;;;;;;;;;;;;;;;;;;;;;
; Yeni bir fonksiyon oluşturmak için `fn` kullanı n.
; Bir fonksiyon her zaman son ifadesini döndürür.
(fn [] "Merhaba Dünya!") ; => fn
; Fonksiyonu çağı rmak için bir çift paranteze daha ihtiyaç var.
((fn [] "Merhaba Dünya!")) ; => "Merhaba Dünya!"
; İsim uzayı nda bir değişken tanı mlamak için `def`
; kullanı lı r.
(def x 1)
x ; => 1
; Bir değişkene fonksiyon değeri atamak için,
(def merhaba-dünya (fn [] "Merhaba Dünya!"))
(merhaba-dünya) ; => "Merhaba Dünya!"
; Bu süreci, `defn` ile kı saltabiliriz.
(defn hello-world [] "Merhaba Dünya!")
; `defn` fonksiyon çağı rı mı ndaki üçüncü eleman
; --vektör-- bir argüman listesidir. Fonksiyonun alacağı
; argümanları tanı mlar.
(defn merhaba [isim]
(str "Merhaba " isim))
(merhaba "Dünya!") ; => "Merhaba Dünya!"
; Ayrı ca, `#()` kı sa yolunu, fonksiyon deklare etmek için
; kullanabiliriz.
(def merhaba2 #(str "Merhaba " %1))
(merhaba2 "Dünya!") ; => "Merhaba Dünya!"
; Çok düzeyli fonksiyonlar da tanı mlanabilir,
(defn merhaba3
([] "Merhaba Dünya!")
([isim] (str "Merhaba " isim)))
(merhaba3) ; => "Merhaba Dünya!"
(merhaba3 "A. NESİN!") ; => "Hello A. NESİN!"
; Fonksiyonlar, belirsiz-sayı da argüman alabilir,
; ve bunları sizin için bir ardı şı kta depolayabilir.
(defn argüman-sayı sı [& argümanları m]
(str "Verilen argüman sayı sı :" (count argümanları m) ", argümanlar: " argümanları m))
(argüman-sayı sı "Öğün" "Çalı ş" "Güven")
; => "Verilen argüman sayı sı :3, argümanlar: ("Öğün" "Çalı ş" "Güven")"
; Elbette, sı radan ve belirsiz-sayı lı fonksiyon argümanları nı
; harmanlayabilirsiniz.
(defn merhabalar [ev-sahibi & misafirler]
(str "Merhabalar, " misafirler ". Benim adı m " ev-sahibi "."))
(merhabalar "İklim" "Ayşe" "Fatma" "Nurdan")
; => "Merhabalar, (\"Ayşe\" \"Fatma\" \"Nurdan\"). Benim adı m İklim."
; Eşlemeler
;;;;;;;;;;
; Hash-Maps, Array-Maps
; Hash-Eşlemeleri ve Dizi-Eşlemeleri bir arayüzü paylaşı rlar.
; Hash-Eşlemeleri daha hı zlı dı r, fakat anahtar sı ralaması tutmazlar.
(class {:a 1 :b 2 :c 3}) ; => clojure.lang.PersistentArrayMap
(class (hash-map :a 1 :b 2 :c 3)) ; => clojure.lang.PersistentHashMap
; Dizi-Eşlemeleri bir çok işlem sı rası nda otomatik olarak Hash-Eşlemelerine
; dönüşürler. Eğer yeterince büyürlerse, endişelenmenize gerek yoktur.
; Eşlemeler anahtar değeri olarak herhangi hash-ifadesi (hashable)
; alabilirler. Ama çoğunlukla, bu iş için anahtar-kelimeler `keyword`
; kullanı lı r.
; Anahtar-kelimeler, karakter katarları gibidirler, fakat
; bir kaç artı ları vardı r.
(class :a) ; => clojure.lang.Keyword
(def karakterkatarı -eşlemesi {"a" 1, "b" 2, "c" 3})
karakterkatarı -eşlemesi ; => {"a" 1, "b" 2, "c" 3}
(def anahtar-eşlemesi {:a 1, :b 2, :c 3})
anahtar-eşlemesi ; => {:a 1, :c 3, :b 2}
; Bu arada, virgüller her zaman boşluk olarak değerlendirilir
; ve etkisizdirler.
; Bir eşlemeleden fonksiyon notasyonu ile değer çağı rmak,
(karakterkatarı -eşlemesi "a") ; => 1
(anahtar-eşlemesi :a) ; => 1
; Keyword tipleri kendi değerlerini argüman olarak aldı kları bir
; eşlemeden değer notasyonu ile çağı rabilirler.
(:b anahtar-eşlemesi) ; => 2
; Bu notasyonu, bir karakter katarı ile denemeyiniz.
;("a" karakterkatarı -eşlemesi)
; => Exception: java.lang.String cannot be cast to clojure.lang.IFn
; Verilmemiş bir değeri çağı rmak, `nil` döndürecektir.
(karakterkatarı -eşlemesi "d") ; => nil
; Eşlemelere yeni değerler eklemek için `assoc` kullanı rı z.
(def yeni-anahtar-eşlemesi (assoc anahtar-eşlemesi :d 4))
yeni-anahtar-eşlemesi ; => {:a 1, :b 2, :c 3, :d 4}
; Ama unutmayı n, Clojure veri yapı ları değişmezdir!
anahtar-eşlemesi ; => {:a 1, :b 2, :c 3}
; Değer silmek için ise `dissoc` kullanı lı r.
(dissoc anahtar-eşlemesi :a :b) ; => {:c 3}
; Kümeler
;;;;;;
(class #{1 2 3}) ; => clojure.lang.PersistentHashSet
(set [1 2 3 1 2 3 3 2 1 3 2 1]) ; => #{1 2 3}
; `conj` ile bir değer eklenir.
(conj #{1 2 3} 4) ; => #{1 2 3 4}
; `disj` ile değer çı karı lı r.
(disj #{1 2 3} 1) ; => #{2 3}
; Fonksiyon notasyonu kümelerde de tanı mlı dı r.
; Kendi içlerinde değer arayan bir fonksiyon olarak
; kullanı labilirler.
(#{1 2 3} 1) ; => 1
(#{1 2 3} 4) ; => nil
; `clojure.sets` isim-uzayı nda daha fazla fonksiyon vardı r.
; Kullanı şlı Formlar
;;;;;;;;;;;;;;;;;
; Clojure için mantı ksal yapı lar bir özel-form'dur.
; Ve diğer fonksiyonlar gibi kullanı labilir.
; `if` fonksiyonunun ilk argümanı bir test ifadesidir.
(if true "ya şundadı r" "ya bunda") ; => "ya şundadı r"
; İkinci ifade doğru, üçüncü ifade ise yanlı şsa ifadeleridir.
; Eğer test terimi doğru olarak değerlendirilirse,
; doğru ifadesi, yanlı şsa yanlı ş ifadesi değerlendirilir ve döndürülür.
;
; Bir yanlı şsa ifadesi yoksa `nil` döndürülür.
(if false "a") ; => nil
; Yerel geçici-değişken tanı mlamak için `let` kullanı lı r.
; İfadelerin varlı ğı `let` çağı rı mı ile sı nı rlı dı r.
(let [a 1 b 2]
(> a b)) ; => false
; İfade ve çağı rı mları `do` ile gruplayabilirsiniz.
; Çağı rı mları n sonuncusu `do` ifadesinin değeri olarak
; döndürülecektir.
(do
(print "Selamlar!")
"Dünya!") ; => "Dünya!" (prints "Selamlar!")
; Fonksiyonlar kapalı bir `do` ifadesi ile çevrelenmiştir.
(defn yazdı r-ve-selamla! [isim]
(println "Merhaba, " isim "!")
(str "Merhaba, " isim "!"))
(yazdı r-ve-selamla! "Zübeyde") ;=> "Merhaba, Zübeyde!" ("Merhaba, Zübeyde!" yazdı rı r.)
; `let` ifadesi de kapalı bir `do` ile gelmektedir.
(let [isim "Ayten"]
(print "Merhabalar, " isim)
(str "Merhabalar, " isim)) ; => "Merhabalar, " ("Merhabalar, Ayten" yazdı rı r)
; Sı ralama-makroları (-> ve ->>) ile veri dönüşümünü daha temiz ifade
; edebilirsiniz.
; Bu makrolar ilk argümanı sonraki her çağı rı mı n içine yerleştirir.
;
; `->` makrosu, ifadeyi çağı rı mları n ilk argümanı olacak şekilde yerleştirir.
(->
{:a 1 :b 2}
(assoc :c 3) ;=> (assoc {:a 1 :b 2} :c 3)
(dissoc :b))
; Bu ifade aşağı daki şekilde yazı labilir:
; (dissoc (assoc {:a 1 :b 2} :c 3) :b)
; ve `{:a 1 :c 3}` olarak değer bulur.
; Sondan-Sı ralama-Makrosu (->>) ise aynı şeyi yapar,
; tek fark ise, ifadeyi, çağı rı mları n son argümanı olarak yerleştirir.
;
(->>
(range 10) ;=> '(0 1 2 3 4 5 6 7 8 9)
(map inc) ;=> (map inc (range 10))
(filter odd?) ;=> (filter odd? (map inc (range 10)))
(into [])) ;=> (into [] (filter odd? (map inc (range 10))))
; Sonuç: [1 3 5 7 9]
; Bir ifadedeki önceki veri dönüşümlerinin sonucunu nereye
; koyacağı nı z konusunda daha fazla özgürlük istediğiniz bir durumda,
; Sı ralama-Makroları ndan daha özgür bi' şey kullanmak istersiniz;
; `as->` makrosu ile dönüşümlerin çı ktı sı na bir isim atayabilir
; ve ardı şı k çağı rı mlarda yer tutucu olarak kullanabilirsiniz.
(as-> [1 2 3] girdi
(map inc girdi);=> ifadeyi isterseniz çağı rı mı n son argümanı olarak,
(nth girdi 2) ;=> veya çağı rı mı n ilk argümanı olarak,
(conj [4 5 6] girdi [8 9 10])) ;=> ya da istediğiniz sı rada kullanabilirsiniz.
;=> [4 5 6 4 [8 9 10]]
; Modüller
;;;;;;;;;;;;;;;
; `use` çağı rdı ğı nı z modüldeki tüm tanı mlara erişmenize olanak verir.
(use 'clojure.set)
; Şu anda, küme fonksiyonları nı kullanabiliriz.
(intersection #{1 2 3} #{2 3 4}) ; => #{2 3}
(difference #{1 2 3} #{2 3 4}) ; => #{1}
; Ayrı ca eklenecek fonksiyonları seçebilirsiniz de:
(use '[clojure.set :only [intersection]])
; Bir modülü eklemek için `require` kullanı lı r.
(require 'clojure.string)
; İsim-uzayı kapsamlı çağı rı mlar aşağı daki şekildedir:
; isim-uzayı /fonksiyon-ismi --isim uzayı ismi ve fonksiyon ismi
; arası na eğik çizgi koymanı z yeterli.
; Burada, modül `clojure.string` ve fonksiyon ismi `blank?`
(clojure.string/blank? "") ; => true
; Ekleme sı rası nda, bir modüle takma-ad verilebilir.
(require '[clojure.string :as str])
(str/replace "Bu bir özet metindir, test için kullanı labilir!"
#"[aeı ioöuü]" str/upper-case)
; => "BU bIr ÖzEt mEtIndIr, tEst IçIn kUllAnIlAbIlIr!"
; (#"", burada düzenli ifadeler için bir sözdizimsel-şekerlemeyi ifade eder)
; Bir isim-uzayı tanı mlaması nda `require` kullanı labilir.
; `ns` bir makrodur ve `require` (ve `use` , ama lütfen kullanmayı n)
; dahil olmak üzere bir çok çağı rı m için işlevsellik sağlamaktadı r.
; Bu notasyonu kullanı rsanı z, modüllerinizi alı ntı lamak zorunda kalmazsı nı z.
(ns test
(:require
[clojure.string :as str]
[clojure.set :as set]))
; Java
;;;;;;;;;;;;;;;;;
; Java, kocaman ve kullanı şlı bir standart kütüphaneye sahip,
; Clojure, Java etkileşimi ile, bundan yararlanabilirsiniz.
; `import` diğer modüller gibi, bir java modülü de ele alabilir.
; Date, bir Java modülü.
(import java.util.Date)
; `ns` çağı rı mı nda da kullanabilirsiniz.
(ns test
(:import java.util.Date
java.util.Calendar))
; Bir Java nesnesinden oluşturmak için `new` çağı rı mı nı kullanabilirsiniz.
(new Date)
; Ayrı ca Clojure Okuyucusu, size bunun daha farklı bir yolunu sunar:
; Sı nı f isminin sonuna koyulacak bir nokta `.` ile
; bu yapı labilir.
(Date.) ; < bir tarih nesnesi >
; `.` --nokta-- çağı rı mı , size nesnelerdeki metotlara erişme imkanı verir.
(. (new Date) getTime) ; < bir zaman-damgası >
(.getTime (Date.)) ; Üstteki ifade ile tamamen aynı sonucu verir.
; Sı nı f içindeki statik metotlara erişmek için `/` ayracı nı
; sı nı f ile metot ismi birleştirmek için kullanabilirsiniz.
; (örnekSı nı f/statikMetot)
(System/currentTimeMillis) ; < bir zaman-damgası > (`system` her zaman sunulur)
; Sı nı flarla işlem yaparken, `doto` bu süreci kolaylaştı rabilir.
; İlk argüman sı nı f nesnesi, sonraki her çağı rı m, nesne üzerinde yapı lı r.
(import java.util.Calendar)
(doto (Calendar/getInstance)
(.set 2000 1 1 0 0 0) ; => `set` metodu, `doto` ifadesine verilen
; sı nı f nesnesi üzerinde çağı rı lı r.
.getTime) ; => Bir tarih nesnesi. set to 2000-01-01 00:00:00
; STM
;;;;;;;;;;;;;;;;;
; 'Software Transactional Memory' Clojure'un değişmez veri yapı ları nı
; ele alı rken kullandı ğı bir mekanizmadı r. Clojure içinde bunu kullanan
; birkaç yapı vardı r.
; Bir `atom` en basitidir. Bir ilkleme-değeri verin.
(def benim-atomum (atom {}))
; Bir atomu güncellemek için `swap!` kullanı lı r.
; `swap!` fonksiyonu, ilk argüman olarak aldı ğı atomu, ikinci argüman
; olarak aldı ğı fonksiyona uygular. Bu fonksiyona ek argümanlar ise
; fonksiyondan sonra gelirler.
(swap! benim-atomum assoc :a 1)
; benim-atomum'un değerini (assoc {} :a 1) ifadesinin sonucu ile değiştirir.
(swap! benim-atomum assoc :b 2)
; benim-atomum'un değerini (assoc {:a 1} :b 2) ifadesinin sonucu ile değiştirir.
; `deref` ile, atomun değerini çözümleyebilirsiniz.
benim-atomum ;=> Atom< #...> (Atom ifadesi döndürür)
@benim -atomum ; => {:a 1 :b 2}
2019-02-01 10:33:52 +03:00
; İşte, `atom` kullanan basit bir sayaç.
2019-01-21 17:40:29 +03:00
(def sayaç (atom 0)) ;=> Şu anki isim uzayı na, `sayaç` ile, 0 başlangı ç
; değeri ile bir atom tanı mladı k.
(defn sayaç-arttı r [benim-atomum]
(swap! sayaç inc)) ;=> Atom'un değerini bir arttı r.
(sayaç-arttı r sayaç)
(sayaç-arttı r sayaç)
(sayaç-arttı r sayaç)
(sayaç-arttı r sayaç)
(sayaç-arttı r sayaç)
(sayaç-arttı r sayaç)
@sayaç ; => 6
; Diğer STM yapı ları `ref` 'ler ve `agent` 'lar.
; Ref'ler: http://clojure.org/refs
; Agent'lar: http://clojure.org/agents
```
### Çevirim-içi içerikler
Bu içerik, Rich Hickey'nin derin yazı lı m geliştirme anlayı şı na ve John McCarthy'nin vizyonu olan Lisp'in, Clojure'a miras verdiklerini anlamak için elbette yeterli değildir. Fakat fonksiyonel paradigma ve bu paradigmanı n modern bir Lisp lehçesinde kullanı mı na göz kı rpmı ş oldunuz.
Clojure.org, bir çok içerik ve makale var. (İngilizce içerik):
[http://clojure.org/ ](http://clojure.org/ )
Clojuredocs.org, örneklerle bezenmiş Clojure dökümantasyonu:
[http://clojuredocs.org/quickref/Clojure%20Core ](http://clojuredocs.org/quickref/Clojure%20Core )
4Clojure, interaktif bir şekilde FP ve Clojure yeteneklerinizi geliştirmenize olanak veriyor:
2023-01-14 08:42:05 +03:00
[https://4clojure.oxal.org/ ](https://4clojure.oxal.org/ )
2019-01-21 17:40:29 +03:00
Clojure-doc.org, Başlangı ç için bir içeriklere sahip:
[http://clojure-doc.org/ ](http://clojure-doc.org/ )
BraveClojure, bir başka clojure öğreten web sitesi:
[https://www.braveclojure.com/ ](https://www.braveclojure.com/ )