Clojure - Panduan Cepat

Clojure adalah bahasa pemrograman fungsional dinamis tingkat tinggi. Clojure dirancang berdasarkan bahasa pemrograman LISP dan memiliki kompiler yang membuatnya berjalan di lingkungan runtime Java dan .Net.

Sebelum kita berbicara tentang Clojure, mari kita lihat dulu gambaran singkat tentang bahasa pemrograman LISP. LISP memiliki inti bahasa yang kecil, hampir tanpa sintaks, dan fasilitas makro yang kuat. Dengan fitur ini, Anda dapat membengkokkan LISP agar sesuai dengan desain Anda, bukan sebaliknya. LISP telah ada sejak lama sejak tahun 1958.

LISP umum membaca ekspresi, mengevaluasinya, dan kemudian mencetak hasilnya. Misalnya, jika Anda ingin menghitung nilai ekspresi matematika sederhana 4 + 6 maka Anda mengetik.

USER(1) (+ 4 6)

Clojure memiliki tujuan utama tingkat tinggi berikut sebagai bahasa pemrograman.

  • Ini didasarkan pada bahasa pemrograman LISP yang membuat pernyataan kodenya lebih kecil daripada bahasa pemrograman tradisional.

  • Ini adalah bahasa pemrograman fungsional.

  • Ini berfokus pada keabadian yang pada dasarnya merupakan konsep bahwa Anda tidak boleh membuat perubahan apa pun pada objek yang dibuat di tempat.

  • Itu dapat mengelola status aplikasi untuk programmer.

  • Ini mendukung konkurensi.

  • Ini mencakup bahasa pemrograman yang ada. Misalnya, Clojure dapat menggunakan seluruh ekosistem Java untuk pengelolaan jalannya kode melalui JVM.

Situs web resmi untuk Clojure adalah https://clojure.org/

Ada berbagai cara untuk menggunakan Clojure sebagai bahasa pemrograman. Kami akan melihat dua cara untuk bekerja dengan pemrograman Clojure.

  • Leiningen - Leiningen adalah alat penting untuk membuat, membangun, dan mengotomatiskan proyek Clojure.

  • Eclipse Plugin - Ada sebuah plugin bernama CounterClockwise, yang tersedia untuk Eclipse untuk menjalankan pengembangan Clojure di Eclipse IDE.

Instalasi Leiningen

Pastikan persyaratan Sistem berikut ini dipenuhi sebelum melanjutkan penginstalan.

Persyaratan sistem

JDK JDK 1.7 atau lebih tinggi
Penyimpanan RAM 2 GB (disarankan)

Step 1- Unduh instalasi biner. Buka tautannyahttp://leiningen-wininstalleruntuk mendapatkan Penginstal Windows. Klik opsi untuk mulai mengunduh penginstal Groovy.

Step 2 - Jalankan Installer dan klik tombol Next.

Step 3 - Tentukan lokasi penginstalan dan klik tombol Berikutnya.

Step 4- Setup akan mendeteksi lokasi instalasi Java yang sudah ada. Klik tombol Berikutnya untuk melanjutkan.

Step 5 - Klik tombol Instal untuk memulai penginstalan.

Setelah penginstalan selesai, Anda akan diberi opsi untuk membuka Clojure REPL, yang merupakan lingkungan yang dapat digunakan untuk membuat dan menguji program Clojure Anda.

Instalasi Eclipse

Pastikan persyaratan Sistem berikut ini dipenuhi sebelum melanjutkan penginstalan.

Persyaratan sistem

JDK JDK 1.7 atau lebih tinggi
Gerhana Gerhana 4.5 (Mars)

Step 1- Buka Eclipse dan klik item Menu. Klik Help → Eclipse Marketplace.

Step 2- Ketik kata kunci Clojure di kotak dialog yang muncul dan tekan tombol 'Go'. Pilihan berlawanan jarum jam akan muncul, klik tombol Install untuk memulai instalasi plugin ini.

Step 3 - Di kotak dialog berikutnya, klik tombol Konfirmasi untuk memulai penginstalan.

Step 4- Di kotak dialog berikutnya, Anda akan diminta untuk menerima perjanjian lisensi. Terima perjanjian lisensi dan klik tombol Selesai untuk melanjutkan penginstalan.

Penginstalan akan dimulai, dan setelah selesai, Anda akan diminta untuk memulai ulang Eclipse.

Setelah Eclipse dimulai ulang, Anda akan melihat opsi di Eclipse untuk membuat proyek Clojure baru.

Untuk memahami sintaks dasar Clojure, pertama-tama mari kita lihat program Hello World sederhana.

Halo Dunia sebagai Program Lengkap

Tulis 'Halo Dunia' dalam program Clojure lengkap. Berikut ini contohnya.

Contoh

(ns clojure.examples.hello
   (:gen-class))
(defn hello-world []
   (println "Hello World"))
(hello-world)

Hal-hal berikut perlu diperhatikan tentang program di atas.

  • Program tersebut akan ditulis dalam sebuah file bernama main.clj. Ekstensi 'clj' adalah nama ekstensi untuk file kode clojure. Pada contoh di atas, nama file disebut main.clj.

  • Kata kunci 'defn' digunakan untuk mendefinisikan suatu fungsi. Kita akan melihat fungsi secara detail di bab lain. Tapi untuk saat ini, ketahuilah bahwa kita sedang membuat sebuah fungsi bernama helloworld, yang akan memiliki kode Clojure utama kita.

  • Dalam kode Clojure kami, kami menggunakan pernyataan 'println' untuk mencetak "Hello World" ke output konsol.

  • Kami kemudian memanggil fungsi hello-world yang pada gilirannya menjalankan pernyataan 'println'.

Program di atas menghasilkan keluaran sebagai berikut.

Keluaran

Hello World

Bentuk Umum Pernyataan

Bentuk umum pernyataan apa pun perlu dievaluasi dalam kurung kurawal seperti yang ditunjukkan pada contoh berikut.

(+ 1 2)

Dalam contoh di atas, seluruh ekspresi diapit oleh tanda kurung. Output dari statement di atas adalah 3. Operator + bertindak seperti fungsi di Clojure, yang digunakan untuk penambahan angka. Nilai 1 dan 2 dikenal sebagai parameters to the function.

Mari kita perhatikan contoh lain. Dalam contoh ini, 'str' adalah operator yang digunakan untuk menggabungkan dua string. String "Halo" dan "Dunia" digunakan sebagai parameter.

(str "Hello" "World")

Contoh

Jika kita menggabungkan dua pernyataan di atas dan menulis sebuah program, akan terlihat seperti berikut ini.

(ns clojure.examples.hello
   (:gen-class))
(defn Example []
   (println (str "Hello World"))
   (println (+ 1 2)))
(Example)

Keluaran

Program di atas menghasilkan keluaran sebagai berikut.

Hello World
3

Namespaces

Namespace digunakan untuk menentukan batas logis antara modul yang ditentukan di Clojure.

Namespace saat ini

Ini mendefinisikan namespace saat ini di mana kode Clojure berada.

Sintaksis

*ns*

Contoh

Di jendela perintah REPL jalankan perintah berikut.

*ns*

Keluaran

Ketika kita menjalankan perintah di atas, output akan berubah tergantung pada namespace saat ini. Berikut adalah contoh output. Namespace dari kode Clojure adalah -

clojure.examples.hello

(ns clojure.examples.hello
   (:gen-class))
(defn Example []
   (println (str "Hello World"))
   (println (+ 1 2)))
(Example)

Memerlukan Pernyataan dalam Clojure

Kode Clojure dikemas dalam perpustakaan. Setiap pustaka Clojure termasuk dalam namespace, yang serupa dengan paket Java. Anda dapat memuat perpustakaan Clojure dengan pernyataan 'Membutuhkan'.

Sintaksis

(require quoted-namespace-symbol)

Contoh

Berikut adalah contoh penggunaan pernyataan ini.

(ns clojure.examples.hello
   (:gen-class))
(require ‘clojure.java.io’)
(defn Example []
   (.exists (file "Example.txt")))
(Example)

Pada kode di atas, kita menggunakan kata kunci 'require' untuk mengimpor namespace clojure.java.io yang memiliki semua fungsi yang diperlukan untuk fungsionalitas input / output. Karena kami tidak memiliki perpustakaan yang diperlukan, kami dapat menggunakan fungsi 'file' dalam kode di atas.

Komentar di Clojure

Komentar digunakan untuk mendokumentasikan kode Anda. Komentar baris tunggal diidentifikasi dengan menggunakan ;; di posisi mana pun dalam antrean. Berikut ini contohnya.

Contoh

(ns clojure.examples.hello
   (:gen-class))

;; This program displays Hello World
(defn Example []
   (println "Hello World"))
(Example)

Pembatas

Dalam Clojure, pernyataan dapat dipisahkan atau dibatasi dengan menggunakan kurung kurawal atau kurung siku.

Contoh

Berikut adalah dua contoh.

(ns clojure.examples.hello
   (:gen-class))

;; This program displays Hello World
(defn Example []
   (println (+ 1 2 3)))
(Example)

Keluaran

Program di atas menghasilkan keluaran sebagai berikut.

6

Contoh

Berikut adalah contoh lainnya.

(ns clojure.examples.hello
   (:gen-class))

;; This program displays Hello World
(defn Example []
   (println [+ 1 2 3]))
(Example)

Keluaran

Program di atas menghasilkan keluaran sebagai berikut.

[#object[clojure.core$_PLUS_ 0x10f163b "clojure.core$_PLUS_@10f163b"] 1 2 3]

Spasi putih

Spasi putih dapat digunakan di Clojure untuk membagi berbagai komponen pernyataan untuk kejelasan yang lebih baik. Ini dapat dilakukan dengan bantuan operator koma (,).

Misalnya, dua pernyataan berikut ini setara dan output dari kedua pernyataan tersebut adalah 15.

(+ 1 2 3 4 5)
(+ 1, 2, 3, 4, 5)

Meskipun Clojure mengabaikan koma, terkadang ia menggunakannya untuk mempermudah pemrogram membaca.

Misalnya, jika Anda memiliki peta hash seperti berikut (def a-map {: a 1: b 2: c 3}) dan menanyakan nilainya di jendela REPL, Clojure akan mencetak keluaran sebagai {: a 1, : b 2,: c 3}.

Hasilnya lebih mudah dibaca, terutama jika Anda melihat data dalam jumlah besar.

Simbol

Di Clojure, simbol setara dengan pengidentifikasi dalam bahasa pemrograman lain. Tetapi tidak seperti bahasa pemrograman lainnya, compiler melihat simbol sebagai nilai string yang sebenarnya. Karena simbol adalah nilai, simbol dapat disimpan dalam koleksi, diteruskan sebagai argumen ke suatu fungsi, dll., Sama seperti objek lainnya.

Simbol hanya boleh berisi karakter alfanumerik dan '* +! /. : - _? ' tetapi tidak boleh dimulai dengan angka atau titik dua.

Berikut adalah contoh simbol yang valid.

tutorial-point!
TUTORIAL
+tutorial+

Struktur Proyek Clojure

Akhirnya mari kita bicara tentang struktur proyek tipikal untuk proyek Clojure. Karena kode Clojure berjalan pada mesin virtual Java, sebagian besar struktur proyek dalam Clojure serupa dengan yang Anda temukan dalam proyek java. Berikut adalah snapshot dari contoh struktur proyek di Eclipse untuk proyek Clojure.

Berikut hal-hal penting yang perlu diperhatikan tentang struktur program di atas.

  • demo_1 - Ini adalah paket tempat file kode Clojure ditempatkan.

  • core.clj - Ini adalah file kode Clojure utama, yang akan berisi kode untuk aplikasi Clojure.

  • Folder Leiningen berisi file seperti clojure-1.6.0.jar yang diperlukan untuk menjalankan aplikasi berbasis Clojure.

  • File pom.properties akan berisi informasi seperti groupId, artifactId dan versi proyek Clojure.

  • File project.clj berisi informasi tentang aplikasi Clojure itu sendiri. Berikut adalah contoh konten file proyek.

(defproject demo-1 "0.1.0-SNAPSHOT"
   :description "FIXME: write description"
   :url "http://example.com/FIXME"
   :license {
      :name "Eclipse Public License"
      :url "http://www.eclipse.org/legal/epl-v10.html"
   }
   :dependencies [[org.clojure/clojure "1.6.0"]])

REPL (read-eval-print loop) adalah alat untuk bereksperimen dengan kode Clojure. Ini memungkinkan Anda untuk berinteraksi dengan program yang sedang berjalan dan dengan cepat mencoba jika semuanya berjalan sebagaimana mestinya. Ini dilakukan dengan memberi Anda prompt di mana Anda dapat memasukkan kode. Kemudian membaca input Anda, mengevaluasinya, mencetak hasilnya, dan loop, memberi Anda prompt lagi.

Proses ini memungkinkan siklus umpan balik cepat yang tidak mungkin dilakukan di sebagian besar bahasa lain.

Memulai Sesi REPL

Sesi REPL dapat dimulai di Leiningen dengan mengetikkan perintah berikut di baris perintah.

lein repl

Ini akan memulai jendela REPL berikut.

Anda kemudian mulai mengevaluasi perintah Clojure di jendela REPL sesuai kebutuhan.

Untuk memulai sesi REPL di Eclipse, klik opsi Menu, pergi ke Run As → Clojure Application.

Ini akan memulai sesi REPL baru di jendela terpisah bersama dengan keluaran konsol.

Secara konseptual, REPL mirip dengan Secure Shell (SSH). Dengan cara yang sama Anda dapat menggunakan SSH untuk berinteraksi dengan server jarak jauh, Clojure REPL memungkinkan Anda untuk berinteraksi dengan proses Clojure yang sedang berjalan. Fitur ini bisa sangat berguna karena Anda bahkan dapat memasang REPL ke aplikasi produksi langsung dan memodifikasi program Anda saat dijalankan.

Variabel Khusus di REPL

REPL menyertakan beberapa variabel berguna, yang banyak digunakan adalah variabel khusus * 1, * 2, dan * 3. Ini digunakan untuk mengevaluasi hasil dari tiga ekspresi terbaru.

Contoh berikut menunjukkan bagaimana variabel-variabel ini dapat digunakan.

user => "Hello"
Hello
user => "World"
World
user => (str *2 *1)
HelloWorld

Dalam contoh di atas, dua string pertama dikirim ke jendela keluaran REPL sebagai “Hello” dan “World”. Kemudian variabel * 2 dan * 1 digunakan untuk memanggil kembali 2 ekspresi terakhir yang dievaluasi.

Clojure menawarkan berbagai macam built-in data types.

Jenis Data Bawaan

Berikut adalah daftar tipe data yang didefinisikan di Clojure.

  • Integers - Berikut representasi Integer yang tersedia di Clojure.

    • Decimal Integers (Short, Long and Int)- Ini digunakan untuk mewakili bilangan bulat. Misalnya, 1234.

    • Octal Numbers- Ini digunakan untuk mewakili angka dalam representasi oktal. Misalnya, 012.

    • Hexadecimal Numbers- Ini digunakan untuk mewakili angka dalam representasi. Misalnya, 0xff.

    • Radix Numbers- Ini digunakan untuk mewakili angka dalam representasi radix. Misalnya, 2r1111 dengan radix adalah bilangan bulat antara 2 dan 36, inklusif.

  • Floating point

    • Defaultnya digunakan untuk merepresentasikan angka floating point 32-bit. Misalnya, 12.34.

    • Representasi lainnya adalah notasi ilmiah. Misalnya, 1.35e-12.

  • char- Ini mendefinisikan literal karakter tunggal. Karakter ditentukan dengan simbol backlash. Misalnya, / e.

  • Boolean - Ini mewakili nilai Boolean, yang bisa benar atau salah.

  • String- Ini adalah literal teks yang direpresentasikan dalam bentuk rangkaian karakter. Misalnya, “Hello World”.

  • Nil - Ini digunakan untuk mewakili nilai NULL di Clojure.

  • Atom- Atom menyediakan cara untuk mengelola keadaan bersama, sinkron, dan independen. Mereka adalah tipe referensi seperti referensi dan vars.

Nilai Terikat

Karena semua tipe data di Clojure diwarisi dari Java, nilai yang dibatasi sama seperti dalam bahasa pemrograman Java. Tabel berikut menunjukkan nilai maksimum yang diperbolehkan untuk literal numerik dan desimal.

literal Rentang
Pendek -32.768 hingga 32.767
int -2.147.483.648 hingga 2.147.483.647
panjang -9.223.372.036.854.775.808 hingga +9.223.372.036.854.775.807
mengapung 1.40129846432481707e-45 hingga 3.40282346638528860e + 38
dua kali lipat 4.94065645841246544e-324d hingga 1.79769313486231570e + 308d

Jenis Numerik Kelas

Selain tipe primitif, tipe objek berikut (terkadang disebut sebagai tipe pembungkus) diperbolehkan.

Nama
java.lang.Byte
java.lang.Short
java.lang.Integer
java.lang.Long
java.lang.Float
java.lang.Double

Contoh

Program berikut menunjukkan kode clojure gabungan untuk mendemonstrasikan tipe data di Clojure.

(ns clojure.examples.hello
   (:gen-class))

;; This program displays Hello World
(defn Example []
   ;; The below code declares a integer variable
   (def x 1)
   
   ;; The below code declares a float variable
   (def y 1.25)
   
   ;; The below code declares a string variable
   (def str1 "Hello")
   (println x)
   (println y)
   (println str1))
(Example)

Keluaran

Program di atas menghasilkan keluaran sebagai berikut.

1
1.25
Hello

Di Clojure, variables ditentukan oleh ‘def’kata kunci. Ini sedikit berbeda dimana konsep variabel lebih berkaitan dengan pengikatan. Di Clojure, nilai terikat ke variabel. Satu hal penting yang perlu diperhatikan di Clojure adalah bahwa variabel tidak dapat diubah, yang berarti bahwa agar nilai variabel berubah, ia perlu dihancurkan dan dibuat kembali.

Berikut adalah tipe dasar variabel di Clojure.

  • short- Ini digunakan untuk mewakili bilangan pendek. Misalnya, 10.

  • int- Ini digunakan untuk mewakili bilangan bulat. Misalnya, 1234.

  • long- Ini digunakan untuk mewakili angka yang panjang. Misalnya, 10000090.

  • float- Ini digunakan untuk mewakili angka floating point 32-bit. Misalnya, 12.34.

  • char- Ini mendefinisikan literal karakter tunggal. Misalnya, '/ a'.

  • Boolean - Ini mewakili nilai Boolean, yang bisa benar atau salah.

  • String- Ini adalah literal teks yang direpresentasikan dalam bentuk rangkaian karakter. Misalnya, “Hello World”.

Deklarasi Variabel

Berikut ini adalah sintaks umum untuk mendefinisikan variabel.

Sintaksis

(def var-name var-value)

Di mana 'var-name' adalah nama variabel dan 'var-value' adalah nilai yang terikat ke variabel.

Contoh

Berikut adalah contoh deklarasi variabel.

(ns clojure.examples.hello
   (:gen-class))

;; This program displays Hello World
(defn Example []
   ;; The below code declares a integer variable
   (def x 1)
   
   ;; The below code declares a float variable
   (def y 1.25)

   ;; The below code declares a string variable
   (def str1 "Hello")
   
   ;; The below code declares a boolean variable
   (def status true))
(Example)

Variabel Penamaan

Nama variabel dapat terdiri dari huruf, angka, dan karakter garis bawah. Ini harus dimulai dengan huruf atau garis bawah. Huruf besar dan kecil berbeda karena Clojure, seperti Java adalah bahasa pemrograman yang peka huruf besar kecil.

Contoh

Berikut adalah beberapa contoh penamaan variabel di Clojure.

(ns clojure.examples.hello
   (:gen-class))

;; This program displays Hello World
(defn Example []
   ;; The below code declares a Boolean variable with the name of status
   (def status true)
   
   ;; The below code declares a Boolean variable with the name of STATUS
   (def STATUS false)
   
   ;; The below code declares a variable with an underscore character.
   (def _num1 2))
(Example)

Note - Dalam pernyataan di atas, karena sensitivitas huruf, status dan STATUS adalah dua definisi variabel yang berbeda di Clojure.

Contoh di atas menunjukkan bagaimana mendefinisikan variabel dengan karakter garis bawah.

Variabel pencetakan

Karena Clojure menggunakan lingkungan JVM, Anda juga dapat menggunakan fungsi 'println'. Contoh berikut menunjukkan bagaimana hal ini dapat dicapai.

Contoh

(ns clojure.examples.hello
   (:gen-class))

;; This program displays Hello World
(defn Example []
   ;; The below code declares a integer variable
   (def x 1)
   
   ;; The below code declares a float variable
   (def y 1.25)
   
   ;; The below code declares a string variable
   (def str1 "Hello")
   (println x)
   (println y)
   (println str1))
(Example)

Keluaran

Program di atas menghasilkan keluaran sebagai berikut.

1
1.25
Hello

Sebuah operator adalah simbol yang memberi tahu kompiler untuk melakukan manipulasi matematika atau logika tertentu.

Clojure memiliki jenis operator berikut -

  • Operator aritmatika
  • Operator relasional
  • Operator logika
  • Operator bitwise

Note - Di Clojure, operator dan operand bekerja dengan sintaks berikut.

Sintaksis

(operator operand1 operand2 operandn)

Sebagai contoh,

Contoh

(+ 1 2)

Contoh di atas melakukan operasi aritmatika pada angka 1 dan 2.

Operator Aritmatika

Bahasa Clojure mendukung operator Aritmatika normal seperti bahasa apapun. Berikut adalah operator Aritmatika yang tersedia di Clojure.

Tunjukkan Contoh

Operator Deskripsi Contoh
+ Penambahan dua operan (+ 1 2) akan menghasilkan 3
- Mengurangi operan kedua dari yang pertama (- 2 1) akan memberikan 1
* Perkalian kedua operan (* 2 2) akan menghasilkan 4
/ Pembagian pembilang dengan penyebut (float (/ 3 2)) akan menghasilkan 1,5
inc Operator inkremental digunakan untuk menaikkan nilai operan sebesar 1 inc 5 akan memberikan 6
des Operator inkremental digunakan untuk menurunkan nilai operand sebesar 1 5 Desember akan memberikan 4
maks Mengembalikan argumen terbesarnya maks 1 2 3 akan menghasilkan 3
min Mengembalikan argumen terkecilnya min 1 2 3 akan menghasilkan 1
rem Sisa pembagian bilangan pertama dengan bilangan kedua rem 3 2 akan memberikan 1

Operator Relasional

Operator relasional memungkinkan perbandingan objek. Berikut ini adalah operator relasional yang tersedia di Clojure.

Tunjukkan Contoh

Operator Deskripsi Contoh
= Menguji persamaan antara dua objek (= 2 2) akan menjadi benar
tidak = Menguji perbedaan antara dua objek (tidak = 3 2) akan memberikan true
< Memeriksa untuk melihat apakah objek kiri kurang dari operan kanan (<2 3) akan memberikan true
<= Memeriksa untuk melihat apakah objek kiri kurang dari atau sama dengan operan kanan (<= 2 3) akan menjadi true
> Memeriksa untuk melihat apakah objek kiri lebih besar dari operan kanan (> 3 2) akan memberikan true
> = Memeriksa untuk melihat apakah objek kiri lebih besar dari atau sama dengan operan kanan (> = 3 2) akan memberikan true

Operator Logis

Operator logika digunakan untuk mengevaluasi ekspresi Boolean. Berikut adalah operator logika yang tersedia di Groovy.

Tunjukkan Contoh

Operator Deskripsi Contoh
and Ini adalah operator logika “dan” (atau true true) akan memberikan true
or Ini adalah operator logika “atau” (dan benar salah) akan menjadi salah
not Ini adalah operator logika “bukan” (tidak salah) akan memberikan benar

Potongan kode berikut menunjukkan bagaimana berbagai operator dapat digunakan.

Operator Bitwise

Clojure menyediakan empat operator bitwise. Berikut adalah operator bitwise yang tersedia di Clojure.

Tunjukkan Contoh

Sr.No. Operator & Deskripsi
1

bit-and

Ini adalah operator bitwise “dan”

2

bit-or

Ini adalah operator bitwise "atau"

3

bit-xor

Ini adalah operator bitwise "xor" atau Exclusive 'atau'

4

bit-not

Ini adalah operator negasi bitwise

Berikut adalah tabel kebenaran yang menampilkan operator ini.

p q p & q p | q p ^ q
0 0 0 0 0
0 1 0 1 1
1 1 1 1 0
1 0 0 1 1

Prioritas Operator

Seperti halnya dengan LISP pada umumnya, tidak perlu khawatir tentang prioritas operator. Ini adalah salah satu keunggulan S-Expressions dan notasi awalan. Semua fungsi mengevaluasi dari kiri ke kanan dan luar dalam. Operator di Clojure hanyalah fungsi, dan semuanya dikurung sepenuhnya.

Sejauh ini kita telah melihat pernyataan yang dieksekusi satu demi satu secara berurutan. Selain itu, pernyataan disediakan di Clojure untuk mengubah aliran kontrol dalam logika program. Mereka kemudian diklasifikasikan menjadi aliran pernyataan kontrol yang akan kita lihat secara rinci.

Sr.No. Loop & Deskripsi
1 While Statement

Itu 'while' pernyataan dieksekusi dengan mengevaluasi ekspresi kondisi (nilai Boolean), dan jika hasilnya benar, maka pernyataan di loop sementara dieksekusi.

2 Pernyataan Doseq

Itu ‘doseq’Pernyataan ini mirip dengan pernyataan 'untuk setiap' yang ditemukan di banyak bahasa pemrograman lainnya. Pernyataan dosisq pada dasarnya digunakan untuk mengulangi urutan.

3 Pernyataan Dotimes

Itu ‘dotimes’ pernyataan digunakan untuk mengeksekusi pernyataan 'x' beberapa kali.

4 Pernyataan Loop

Bentuk khusus lingkaran tidak seperti ‘for’lingkaran. Penggunaan loop sama dengan let binding. Namun, loop menetapkan titik rekursi

Decision-making structures mensyaratkan pemrogram menentukan satu atau lebih kondisi yang akan dievaluasi atau diuji oleh program, bersama dengan pernyataan atau pernyataan yang akan dijalankan jika kondisi ditentukan benar, dan secara opsional, pernyataan lain yang akan dijalankan jika kondisi ditentukan untuk salah.

Sr.No. Metode & Deskripsi
1 Pernyataan If

Di Clojure, kondisi adalah ekspresi yang mengevaluasinya menjadi benar atau salah. 'If' Jika kondisinya benar, maka pernyataan # 1 akan dijalankan, jika tidak pernyataan # 2 akan dieksekusi.

2 Jika / lakukan Ekspresi

Itu ‘if-do’ ekspresi di Clojure digunakan untuk memungkinkan beberapa ekspresi dieksekusi untuk setiap cabang pernyataan 'if'.

3 Pernyataan Jika Bersarang

Banyak 'if' pernyataan yang tertanam di dalam satu sama lain.

4 Pernyataan Kasus

Clojure menawarkan ‘case’ pernyataan yang mirip dengan ‘switch’ pernyataan tersedia dalam bahasa pemrograman Java.

5 Pernyataan Cond

Clojure menawarkan pernyataan evaluasi lain yang disebut ‘cond’pernyataan. Pernyataan ini membutuhkan satu set pasangan tes / ekspresi.

Clojure dikenal sebagai bahasa pemrograman fungsional, oleh karena itu Anda akan melihat banyak penekanan pada cara kerja fungsi di Clojure. Bab ini membahas semua yang bisa dilakukan dengan fungsi di Clojure.

Sr.No. Fungsi & Deskripsi
1 Mendefinisikan Fungsi

Sebuah fungsi ditentukan dengan menggunakan ‘defn’ makro.

2 Fungsi Anonim

Fungsi anonim adalah fungsi yang tidak memiliki nama yang terkait dengannya.

3 Fungsi dengan Banyak Argumen

Fungsi Clojure dapat ditentukan dengan nol atau lebih parameter. Nilai yang Anda berikan ke fungsi dipanggilarguments, dan argumennya bisa jenis apa pun.

4 Fungsi Variadic

Clojure menawarkan pernyataan 'case' yang mirip dengan pernyataan 'switch' yang tersedia dalam bahasa pemrograman Java.

5 Fungsi Urutan Tinggi

Fungsi tingkat tinggi (HOF) adalah fungsi yang menggunakan fungsi lain sebagai argumen. HOF adalah teknik pemrograman fungsional yang penting dan cukup umum digunakan di Clojure.

Numbers datatype di Clojure diturunkan dari kelas Java.

Clojure mendukung bilangan bulat dan titik mengambang.

  • Integer adalah nilai yang tidak menyertakan pecahan.

  • Bilangan floating-point adalah nilai desimal yang mencakup pecahan desimal.

Berikut adalah contoh angka di Clojure.

(def x 5)
(def y 5.25)

Di mana 'x' adalah tipe Integer dan 'y' adalah float.

Di Java, kelas-kelas berikut dilampirkan ke nomor yang ditentukan di Clojure.

Untuk benar-benar melihat bahwa nomor di Clojure berasal dari kelas Java, gunakan program berikut untuk melihat jenis nomor yang ditetapkan saat menggunakan perintah 'def'.

Contoh

(ns clojure.examples.hello
   (:gen-class))

;; This program displays Hello World
(defn Example []
   (def x 5)
   (def y 5.25)
   (println (type x))
   (println (type y)))
(Example)

Itu ‘type’ perintah digunakan untuk mengeluarkan kelas yang terkait dengan nilai yang diberikan ke variabel.

Keluaran

Kode di atas akan menghasilkan keluaran sebagai berikut.

Java.lang.long
Java.lang.double

Tes Angka

Fungsi tes berikut tersedia untuk angka.

Sr.No. Nomor & Deskripsi
1 nol?

Mengembalikan nilai benar jika jumlahnya nol, jika tidak salah.

2 pos?

Mengembalikan nilai benar jika angka lebih besar dari nol, jika tidak salah.

3 neg?

Mengembalikan nilai benar jika angka kurang dari nol, jika tidak salah.

4 bahkan?

Mengembalikan nilai benar jika angkanya genap, dan melontarkan pengecualian jika angkanya bukan bilangan bulat.

5 aneh?

Mengembalikan nilai benar jika jumlahnya ganjil, dan melontarkan pengecualian jika nomor tersebut bukan bilangan bulat.

6 jumlah?

Mengembalikan nilai benar jika angka tersebut benar-benar Angka.

7 bilangan bulat?

Mengembalikan nilai benar jika angkanya adalah bilangan bulat.

8 mengapung?

Mengembalikan nilai benar jika angkanya adalah float.

Kami telah melihat pernyataan berulang dalam topik sebelumnya dan sedangkan loop 'for' agak seperti loop, recur adalah lingkaran nyata di Clojure.

Jika Anda memiliki latar belakang pemrograman, Anda mungkin pernah mendengar tentang rekursi ekor, yang merupakan fitur utama dari bahasa fungsional. Bentuk khusus rekursi ini adalah bentuk yang mengimplementasikan rekursi ekor. Seperti yang ditunjukkan oleh kata “rekursi ekor”, rekursi harus dipanggil pada posisi ekor. Dengan kata lain, kekambuhan harus menjadi hal terakhir yang harus dievaluasi.

Contoh paling sederhana dari pernyataan berulang digunakan dalam loop 'for'. Dalam contoh berikut, pernyataan berulang digunakan untuk mengubah nilai variabel 'i' dan memasukkan nilai variabel kembali ke ekspresi loop.

Contoh

(ns clojure.examples.hello
   (:gen-class))

;; This program displays Hello World
(defn Example []
   (loop [i 0]
      (when (< i 5)
      (println i)
      (recur (inc i)))))
(Example)

Keluaran

Program di atas menghasilkan keluaran sebagai berikut.

0
1
2
3
4

Clojure menyediakan sejumlah metode pembantu saat bekerja dengan I / O. Ini menawarkan kelas yang lebih mudah untuk menyediakan fungsi berikut untuk file.

  • Membaca file
  • Menulis ke file
  • Melihat apakah suatu file adalah file atau direktori

Mari jelajahi beberapa operasi file yang ditawarkan Clojure.

Membaca Isi File sebagai Seluruh String

Jika Anda ingin mendapatkan seluruh konten file sebagai string, Anda dapat menggunakan clojure.core.slurpmetode. Perintah slurp membuka pembaca pada file dan membaca semua isinya, mengembalikan sebuah string.

Berikut adalah contoh bagaimana hal ini dapat dilakukan.

(ns clojure.examples.hello
   (:gen-class))

;; This program displays Hello World
(defn Example []
   (def string1 (slurp "Example.txt"))
   (println string1))
(Example)

Jika file berisi baris berikut, baris tersebut akan dicetak sebagai -

line : Example1
line : Example2

Membaca Isi File Satu Baris Sekaligus

Jika Anda ingin mendapatkan seluruh konten file sebagai string satu baris dalam satu waktu, Anda dapat menggunakan clojure.java.io/readermetode. Kelas clojure.java.io/reader membuat buffer pembaca, yang digunakan untuk membaca setiap baris file.

Berikut adalah contoh yang menunjukkan bagaimana ini bisa dilakukan.

(ns clojure.examples.hello
   (:gen-class))

;; This program displays Hello World
(defn Example []
   (with-open [rdr (clojure.java.io/reader "Example.txt")]
   (reduce conj [] (line-seq rdr))))
(Example)

Jika file berisi baris berikut, baris tersebut akan dicetak sebagai -

line : Example1
line : Example2

Outputnya akan ditampilkan sebagai -

["line : Example1" "line : Example2"]

Menulis 'ke' File

Jika Anda ingin menulis file 'ke', Anda dapat menggunakan clojure.core.spitperintah untuk memuntahkan seluruh string ke dalam file. Perintah spit adalah kebalikan dari metode slurp. Metode ini membuka file sebagai penulis, menulis konten, lalu menutup file.

Berikut ini contohnya.

(ns clojure.examples.hello
   (:gen-class))

;; This program displays Hello World
(defn Example []
   (spit "Example.txt"
      "This is a string"))

Dalam contoh di atas, jika Anda melihat konten file Example.txt, Anda akan melihat konten "Ini adalah string".

Menulis 'ke' File Satu Baris Sekaligus

Jika Anda ingin menulis 'ke' file satu baris dalam satu waktu, Anda dapat menggunakan clojure.java.io.writerkelas. Kelas clojure.java.io.writer digunakan untuk membuat aliran penulis di mana byte data dimasukkan ke dalam aliran dan selanjutnya ke dalam file.

Berikut adalah contoh yang menunjukkan bagaimana perintah spit dapat digunakan.

(ns clojure.examples.hello
   (:gen-class))

;; This program displays Hello World
(defn Example []
   (with-open [w (clojure.java.io/writer "Example.txt" :append true)]
      (.write w (str "hello" "world"))))
(Example)

Ketika kode di atas dijalankan, baris "hello world" akan ada di file Example.txt. Opsi append: true adalah menambahkan data ke file. Jika opsi ini tidak ditentukan, maka file akan ditimpa setiap kali data ditulis ke file.

Memeriksa untuk Melihat Jika File Ada

Untuk memeriksa apakah sebuah file ada, file clojure.java.io.fileclass dapat digunakan untuk memeriksa keberadaan file. Berikut adalah contoh yang menunjukkan bagaimana hal ini dapat dicapai.

(ns clojure.examples.hello
   (:gen-class))

;; This program displays Hello World
(defn Example []
   (println (.exists (clojure.java.io/file "Example.txt"))))
(Example)

Jika file Example.txt ada, hasilnya akan benar.

Membaca dari Konsol

Untuk membaca data dari konsol, file read-linepernyataan dapat digunakan. Berikut adalah contoh yang menunjukkan bagaimana ini dapat digunakan.

Jika Anda memasukkan perintah (read-line) di jendela REPL, Anda akan memiliki kesempatan untuk memasukkan beberapa masukan di jendela konsol.

user->(read-line)
Hello World

Kode di atas akan menghasilkan keluaran sebagai berikut.

“Hello World”

SEBUAH Stringliteral dibangun di Clojure dengan mengapit teks string dalam kutipan. String di Clojure perlu dibuat menggunakan tanda kutip ganda seperti "Hello World".

Contoh

Berikut adalah contoh penggunaan string di Clojure.

(ns clojure.examples.hello
   (:gen-class))
(defn hello-world []
   (println "Hello World")
   (println "This is a demo application"))
(hello-world)

Keluaran

Program di atas menghasilkan keluaran sebagai berikut.

Hello World
This is a demo application

Operasi String Dasar

Clojure memiliki sejumlah operasi yang dapat dilakukan pada string. Berikut adalah operasinya.

Sr.No. Operasi & Deskripsi String
1 str

Rangkaian string dapat dilakukan dengan fungsi str sederhana.

2 format

Pemformatan string dapat dilakukan dengan fungsi format sederhana. Fungsi format memformat string menggunakanjava.lang.String.format.

3 menghitung

Mengembalikan jumlah karakter dalam string.

4 kapal selam

Mengembalikan substring dari 's' yang dimulai pada awal inklusif, dan berakhir pada akhir (default untuk panjang string), eksklusif.

5 membandingkan

Menampilkan angka negatif, nol, atau angka positif ketika 'x' secara logis 'kurang dari', 'sama dengan', atau 'lebih besar dari' 'y'.

6 huruf kecil

Mengonversi string menjadi semua huruf kecil.

7 huruf besar

Mengonversi string menjadi huruf besar semua.

8 Ikuti

Mengembalikan string dari semua elemen dalam koleksi, seperti yang dikembalikan oleh (seq collection), dipisahkan oleh pemisah opsional.

9 membagi

Memisahkan string pada ekspresi reguler.

10 garis terpisah

String terpisah didasarkan pada karakter escape \ n atau \ r \ n.

11 balik

Membalik karakter dalam sebuah string.

12 menggantikan

Mengganti semua contoh pertandingan dalam string dengan string pengganti.

13 memangkas

Menghapus spasi dari kedua ujung string.

14 triml

Menghapus spasi dari sisi kiri string.

15 trimr

Menghapus spasi dari sisi kanan string.

Listadalah struktur yang digunakan untuk menyimpan kumpulan data barang. Di Clojure, List mengimplementasikanISeqantarmuka. Daftar dibuat di Clojure dengan menggunakan fungsi daftar.

Contoh

Berikut adalah contoh pembuatan daftar nomor di Clojure.

(ns clojure.examples.example
   (:gen-class))
(defn example []
   (println (list 1 2 3 4)))
(example)

Keluaran

Kode di atas menghasilkan keluaran sebagai berikut.

(1 2 3 4)

Berikut adalah contoh pembuatan daftar karakter di Clojure.

(ns clojure.examples.example
   (:gen-class))
(defn example []
   (println (list 'a 'b 'c 'd)))
(example)

Kode di atas menghasilkan keluaran sebagai berikut.

(a b c d)

Berikut adalah metode daftar yang tersedia di Clojure.

Sr.No. Daftar & Deskripsi
1 daftar*

Membuat daftar baru yang berisi item yang ditambahkan ke item lainnya, yang terakhir akan diperlakukan sebagai urutan.

2 pertama

Fungsi ini mengembalikan item pertama dalam daftar.

3 nth

Fungsi ini mengembalikan item di posisi 'n' dalam daftar.

4 kontra

Mengembalikan daftar baru di mana elemen ditambahkan ke awal daftar.

5 konj

Mengembalikan daftar baru di mana daftar berada di awal dan elemen yang akan ditambahkan ditempatkan di akhir.

6 beristirahat

Mengembalikan item yang tersisa dalam daftar setelah item pertama.

Setsdi Clojure adalah sekumpulan nilai unik. Set dibuat di Clojure dengan bantuan perintah set.

Contoh

Berikut adalah contoh pembuatan set di Clojure.

(ns clojure.examples.example
   (:gen-class))
(defn example []
   (println (set '(1 1 2 2))))
(example)

Keluaran

Kode di atas menghasilkan keluaran sebagai berikut.

#{1,2}

Berikut adalah metode yang tersedia di Clojure untuk set.

Sr.No. Set & Deskripsi
1 diurutkan-set

Mengembalikan sekumpulan elemen yang diurutkan.

2 Dapatkan

Mengembalikan elemen pada posisi indeks.

3 mengandung?

Mencari tahu apakah himpunan mengandung elemen tertentu atau tidak.

4 konj

Menambahkan elemen ke set dan mengembalikan set elemen baru.

5 disj

Memisahkan elemen dari set.

6 Persatuan

Kembalikan satu set yang merupakan gabungan dari set input

7 perbedaan

Kembalikan satu set yang merupakan set pertama tanpa elemen dari set yang tersisa.

8 persimpangan

Kembalikan satu set yang merupakan perpotongan dari set input.

9 bagian?

Apakah set1 merupakan bagian dari set2?

10 superset?

Apakah set1 merupakan superset dari set2?

SEBUAH Vectoradalah kumpulan nilai yang diindeks oleh bilangan bulat yang berdekatan. Vektor dibuat dengan menggunakan metode vektor di Clojure.

Contoh

Berikut adalah contoh pembuatan vektor di Clojure.

(ns clojure.examples.example
   (:require [clojure.set :as set])
   (:gen-class))
(defn example []
   (println (vector 1 2 3)))
(example)

Keluaran

Kode di atas menghasilkan keluaran sebagai berikut.

[1 2 3]

Berikut adalah metode yang tersedia di Clojure.

Sr.No. Vektor & Deskripsi
1 vektor-dari

Membuat vektor baru dari tipe primitif tunggal 't', di mana 't' adalah salah satu dari: int: long: float: double: byte: short: char atau: boolean.

2 nth

Fungsi ini mengembalikan item di posisi ke-n dalam vektor.

3 Dapatkan

Mengembalikan elemen pada posisi indeks dalam vektor.

4 konj

Menambahkan elemen ke vektor dan mengembalikan set elemen vektor baru.

5 pop

Untuk daftar atau antrian, mengembalikan daftar / antrian baru tanpa item pertama, untuk vektor, mengembalikan vektor baru tanpa item terakhir.

6 subvec

Mengembalikan sub vektor dari indeks awal dan akhir.

SEBUAH Mapadalah koleksi yang memetakan kunci ke nilai. Tersedia dua tipe peta yang berbeda - di-hash dan diurutkan.HashMaps membutuhkan kunci yang mendukung hashCode dan yang setara dengan benar. SortedMaps membutuhkan kunci yang mengimplementasikan Comparable, atau instance dari Comparator.

Sebuah peta dapat dibuat dengan dua cara, yang pertama adalah melalui metode hash-map.

Penciptaan - HashMaps

HashMaps memiliki hubungan nilai kunci yang khas dan dibuat dengan menggunakan fungsi peta hash.

(ns clojure.examples.example
   (:gen-class))
(defn example []
   (def demokeys (hash-map "z" "1" "b" "2" "a" "3"))
   (println demokeys))
(example)

Keluaran

Kode di atas menghasilkan keluaran sebagai berikut.

{z 1, b 2, a 3}

Creation - SortedMaps

SortedMaps memiliki karakteristik unik dalam mengurutkan elemennya berdasarkan elemen kunci. Berikut adalah contoh yang menunjukkan bagaimana peta yang diurutkan dapat dibuat menggunakan fungsi peta-terurut.

(ns clojure.examples.example
   (:gen-class))
(defn example []
   (def demokeys (sorted-map "z" "1" "b" "2" "a" "3"))
   (println demokeys))
(example)

Kode di atas menghasilkan keluaran sebagai berikut.

{a 3, b 2, z 1}

Dari program di atas, Anda dapat dengan jelas melihat bahwa elemen di peta diurutkan sesuai nilai kunci. Berikut adalah metode yang tersedia untuk peta.

Sr.No. Peta & Deskripsi
1 Dapatkan

Mengembalikan nilai yang dipetakan ke key, not-found atau nil jika key tidak ada.

2 mengandung?

Lihat apakah peta berisi kunci yang diperlukan.

3 Temukan

Mengembalikan entri peta untuk kunci.

4 kunci

Menampilkan daftar kunci di peta.

5 vals

Menampilkan daftar nilai di peta.

6 dissoc

Memisahkan entri nilai kunci dari peta.

7 menggabungkan

Menggabungkan dua entri peta menjadi satu entri peta tunggal.

8 bergabung dengan

Menampilkan peta yang terdiri dari sisa peta yang digabungkan ke yang pertama.

9 tombol pilih

Mengembalikan peta yang hanya berisi entri di peta yang kuncinya ada di kunci.

10 ganti nama-kunci

Ubah nama kunci di HashMap saat ini ke yang baru ditentukan.

11 map-invert

Membalik peta sehingga nilainya menjadi kunci dan sebaliknya.

Namespacesdi Clojure digunakan untuk membedakan kelas menjadi ruang logis terpisah seperti di Java. Perhatikan pernyataan berikut.

(:require [clojure.set :as set])

Dalam pernyataan di atas, 'clojure.set' adalah namespace yang berisi berbagai kelas dan metode untuk digunakan dalam program. Misalnya, namespace di atas berisi fungsi yang disebut map-invert, yang digunakan untuk membalikkan peta nilai-kunci. Kami tidak dapat menggunakan fungsi ini kecuali kami secara eksplisit memberi tahu program kami untuk menyertakan namespace ini.

Mari kita lihat berbagai metode yang tersedia untuk namespace.

Sr.No. Metode & Deskripsi
1 * ns *

Ini digunakan untuk melihat namespace Anda saat ini.

2 ns

Ini digunakan untuk membuat namespace baru dan mengaitkannya dengan program yang sedang berjalan.

3 alias

Tambahkan alias di namespace saat ini ke namespace lain. Argumen adalah dua simbol: alias yang akan digunakan dan nama simbolik dari namespace target.

4 all-ns

Menampilkan daftar semua ruang nama.

5 find-ns

Menemukan dan mengembalikan namespace tertentu.

6 ns-nama

Menampilkan nama namespace tertentu.

7 ns-alias

Menampilkan alias, yang terkait dengan ruang nama apa pun.

8 ns-peta

Mengembalikan peta dari semua pemetaan untuk namespace.

9 hapus alias

Mengembalikan peta yang hanya berisi entri di peta yang kuncinya ada di kunci.

Exception handlingdiperlukan dalam bahasa pemrograman apa pun untuk menangani error runtime sehingga aliran normal aplikasi dapat dipertahankan. Pengecualian biasanya mengganggu aliran normal aplikasi, itulah alasan mengapa kita perlu menggunakan penanganan pengecualian dalam aplikasi kita.

Pengecualian secara luas diklasifikasikan ke dalam kategori berikut -

  • Checked Exception- Kelas yang memperluas kelas Throwable kecuali RuntimeException dan Error disebut sebagai pengecualian yang dicentang. Misalnya IOException, SQLException, dll. Pengecualian yang dicentang diperiksa pada waktu kompilasi.

Mari kita pertimbangkan program berikut yang melakukan operasi pada file bernama Example.txt. Namun, selalu ada kasus di mana file Example.txt tidak ada.

(ns clojure.examples.example
   (:gen-class))

;; This program displays Hello World
(defn Example []
   (def string1 (slurp "Example.txt"))
   (println string1))
(Example)

Jika file Example.txt tidak ada, pengecualian berikut akan dibuat oleh program.

Caused by: java.io.FileNotFoundException: Example.txt (No such file or
directory)
at java.io.FileInputStream.open0(Native Method)
at java.io.FileInputStream.open(FileInputStream.java:195)
at java.io.FileInputStream.<init>(FileInputStream.java:138)
at clojure.java.io$fn__9185.invoke(io.clj:229) at clojure.java.io$fn__9098$G__9091__9105.invoke(io.clj:69) at clojure.java.io$fn__9197.invoke(io.clj:258)
at clojure.java.io$fn__9098$G__9091__9105.invoke(io.clj:69)

Dari pengecualian di atas, kita dapat dengan jelas melihat bahwa program memunculkan FileNotFoundException.

  • Unchecked Exception- Kelas yang memperluas RuntimeException dikenal sebagai pengecualian yang tidak dicentang. Misalnya, ArithmeticException, NullPointerException, ArrayIndexOutOfBoundsException, dll. Pengecualian yang tidak dicentang tidak diperiksa pada waktu kompilasi melainkan diperiksa pada waktu proses.

Salah satu kasus klasik adalah ArrayIndexOutOfBoundsException yang terjadi saat Anda mencoba mengakses indeks larik yang lebih besar dari panjang larik. Berikut adalah contoh tipikal dari jenis kesalahan ini.

(ns clojure.examples.example
   (:gen-class))
(defn Example []
   (try
      (aget (int-array [1 2 3]) 5)
      (catch Exception e (println (str "caught exception: " (.toString e))))
      (finally (println "This is our final block")))
   (println "Let's move on"))
(Example)

Ketika kode di atas dijalankan, pengecualian berikut akan dimunculkan.

caught exception: java.lang.ArrayIndexOutOfBoundsException: 5
This is our final block
Let's move on

Kesalahan

Kesalahan tidak dapat dipulihkan misalnya OutOfMemoryError, VirtualMachineError, AssertionError, dll. Ini adalah kesalahan yang tidak dapat dipulihkan oleh program dan akan menyebabkan program macet. Kami sekarang membutuhkan beberapa mekanisme untuk menangkap pengecualian ini sehingga program dapat terus berjalan jika pengecualian ini ada.

Diagram berikut menunjukkan bagaimana hierarki pengecualian di Clojure diatur. Semuanya didasarkan pada hierarki yang ditentukan di Java.

Pengecualian Penangkapan

Sama seperti bahasa pemrograman lainnya, Clojure menyediakan blok 'coba-tangkap' normal untuk menangkap pengecualian saat dan ketika pengecualian itu terjadi.

Berikut ini adalah sintaks umum dari blok coba-tangkap.

(try
   (//Protected code)
   catch Exception e1)
(//Catch block)

Semua kode Anda yang dapat menimbulkan pengecualian ditempatkan di Protected code block.

Dalam catch block, Anda dapat menulis kode khusus untuk menangani pengecualian Anda sehingga aplikasi dapat memulihkan dari pengecualian tersebut.

Mari kita lihat contoh sebelumnya yang menghasilkan pengecualian file-tidak ditemukan dan lihat bagaimana kita dapat menggunakan blok try catch untuk menangkap pengecualian yang dimunculkan oleh program.

(ns clojure.examples.example
   (:gen-class))
(defn Example []
   (try
      (def string1 (slurp "Example.txt"))
      (println string1)
      (catch Exception e (println (str "caught exception: " (.getMessage e))))))
(Example)

Program di atas menghasilkan keluaran sebagai berikut.

caught exception: Example.txt (No such file or directory)

Dari kode di atas, kami membungkus kode yang salah di file try block. Di blok catch, kami hanya menangkap pengecualian kami dan mengeluarkan pesan bahwa pengecualian telah terjadi. Jadi, kami sekarang memiliki cara yang berarti untuk menangkap pengecualian, yang dihasilkan oleh program.

Beberapa Catch Block

Seseorang dapat memiliki beberapa blok tangkapan untuk menangani berbagai jenis pengecualian. Untuk setiap blok catch, tergantung pada tipe exception yang muncul, Anda akan menulis kode untuk menanganinya.

Mari kita ubah kode sebelumnya untuk menyertakan dua blok tangkapan, satu yang khusus untuk file kita tidak ditemukan pengecualian dan yang lainnya untuk blok pengecualian umum.

(ns clojure.examples.example
   (:gen-class))
(defn Example []
   (try
      (def string1 (slurp "Example.txt"))
      (println string1)
      
      (catch java.io.FileNotFoundException e (println (str "caught file
         exception: " (.getMessage e))))
      
      (catch Exception e (println (str "caught exception: " (.getMessage e)))))
   (println "Let's move on"))
(Example)

Program di atas menghasilkan keluaran sebagai berikut.

caught file exception: Example.txt (No such file or directory)
Let's move on

Dari keluaran di atas, kita dapat dengan jelas melihat bahwa pengecualian kita ditangkap oleh blok penangkap 'FileNotFoundException' dan bukan yang umum.

Akhirnya Blokir

Blok terakhir mengikuti blok percobaan atau blok tangkap. Blok kode terakhir selalu dijalankan, terlepas dari terjadinya Exception.

Menggunakan last block memungkinkan Anda menjalankan pernyataan tipe pembersihan apa pun yang ingin Anda jalankan, apa pun yang terjadi dalam kode yang dilindungi. Berikut adalah sintaks untuk blok ini.

(try
   (//Protected code)
   catch Exception e1)
(//Catch block)
(finally
   //Cleanup code)

Mari ubah kode di atas dan tambahkan blok kode terakhir. Berikut adalah potongan kodenya.

(ns clojure.examples.example
   (:gen-class))
(defn Example []
   (try
      (def string1 (slurp "Example.txt"))
      (println string1)
      
      (catch java.io.FileNotFoundException e (println (str "caught file
         exception: " (.getMessage e))))
      
      (catch Exception e (println (str "caught exception: " (.getMessage e))))
      (finally (println "This is our final block")))
   (println "Let's move on"))
(Example)

Program di atas menghasilkan keluaran sebagai berikut.

caught file exception: Example.txt (No such file or directory)
This is our final block
Let's move on

Dari program di atas, Anda dapat melihat bahwa blok terakhir juga diterapkan setelah blok penangkap menangkap pengecualian yang diperlukan.

Karena Clojure memperoleh penanganan pengecualiannya dari Java, mirip dengan Java, metode berikut tersedia di Clojure untuk mengelola pengecualian.

  • public String getMessage()- Menampilkan pesan rinci tentang pengecualian yang telah terjadi. Pesan ini diinisialisasi di konstruktor Throwable.

  • public Throwable getCause() - Mengembalikan penyebab pengecualian seperti yang diwakili oleh objek Throwable.

  • public String toString() - Mengembalikan nama kelas yang digabungkan dengan hasil getMessage ().

  • public void printStackTrace() - Mencetak hasil toString () bersama dengan pelacakan tumpukan ke System.err, aliran keluaran kesalahan.

  • public StackTraceElement [] getStackTrace()- Mengembalikan larik yang berisi setiap elemen pada jejak tumpukan. Elemen di indeks 0 mewakili bagian atas tumpukan panggilan, dan elemen terakhir dalam larik mewakili metode di bagian bawah tumpukan panggilan.

  • public Throwable fillInStackTrace() - Mengisi jejak tumpukan dari objek yang dapat dilempar ini dengan jejak tumpukan saat ini, menambahkan ke informasi sebelumnya di jejak tumpukan.

Berikut adalah contoh kode yang menggunakan beberapa metode yang tercantum di atas.

(ns clojure.examples.example
   (:gen-class))
(defn Example []
   (try
      (def string1 (slurp "Example.txt"))
      (println string1)
      
      (catch java.io.FileNotFoundException e (println (str "caught file
         exception: " (.toString e))))
      
      (catch Exception e (println (str "caught exception: " (.toString e))))
   (finally (println "This is our final block")))
   (println "Let's move on"))
(Example)

Program di atas menghasilkan keluaran sebagai berikut.

caught file exception: java.io.FileNotFoundException: Example.txt (No such file
or directory)
This is our final block
Let's move on

Sequences dibuat dengan bantuan ‘seq’perintah. Berikut adalah contoh sederhana pembuatan urutan.

(ns clojure.examples.example
   (:gen-class))

;; This program displays Hello World
(defn Example []
   (println (seq [1 2 3])))
(Example)

Program di atas menghasilkan keluaran sebagai berikut.

(1 2 3)

Berikut adalah berbagai metode yang tersedia untuk urutan.

Sr.No. Metode & Deskripsi
1 kontra

Mengembalikan urutan baru di mana 'x' adalah elemen pertama dan 'seq' adalah sisanya.

2 konj

Mengembalikan urutan baru di mana 'x' adalah elemen yang ditambahkan ke akhir urutan.

3 concat

Ini digunakan untuk menggabungkan dua urutan.

4 berbeda

Digunakan untuk hanya memastikan bahwa elemen berbeda ditambahkan ke urutan.

5 balik

Membalikkan elemen dalam urutan.

6 pertama

Mengembalikan elemen pertama dari urutan.

7 terakhir

Mengembalikan elemen terakhir dari urutan.

8 beristirahat

Mengembalikan seluruh urutan kecuali elemen pertama.

9 menyortir

Mengembalikan urutan elemen yang diurutkan.

10 penurunan

Menurunkan elemen dari urutan berdasarkan jumlah elemen yang perlu dihapus.

11 ambil-terakhir

Mengambil daftar elemen terakhir dari urutan.

12 mengambil

Mengambil daftar elemen pertama dari urutan.

13 split-at

Membagi urutan item menjadi dua bagian. Lokasi ditentukan di mana pemisahan harus dilakukan.

SEBUAH regular expressionadalah pola yang digunakan untuk mencari substring dalam teks. Ekspresi reguler digunakan dalam berbagai bahasa pemrograman dan banyak digunakan dalam bahasa pemrograman jenis LISP.

Berikut adalah contoh ekspresi reguler.

//d+

Ekspresi reguler di atas digunakan untuk menemukan satu digit kemunculan lagi dalam sebuah string. Karakter // digunakan untuk memastikan bahwa karakter 'd' dan '+' digunakan untuk mewakili ekspresi reguler.

Secara umum, ekspresi reguler berfungsi dengan kumpulan aturan berikut.

  • Ada dua karakter posisi khusus yang digunakan untuk menunjukkan awal dan akhir baris: caret (∧) dan tanda dolar ($):

  • Ekspresi reguler juga bisa menyertakan bilangan. Tanda plus (+) mewakili satu kali atau lebih, diterapkan ke elemen ekspresi sebelumnya. Tanda bintang (*) digunakan untuk mewakili nol atau lebih kejadian. Tanda tanya (?) Menunjukkan nol atau sekali.

  • Karakter meta {dan} digunakan untuk mencocokkan sejumlah contoh dari karakter sebelumnya.

  • Dalam ekspresi reguler, simbol titik (.) Dapat mewakili karakter apa pun. Ini dijelaskan sebagai karakter wildcard.

  • Ekspresi reguler dapat mencakup kelas karakter. Sekumpulan karakter dapat diberikan sebagai urutan karakter sederhana yang dilingkupi dalam meta karakter [dan] seperti pada [aeiou]. Untuk rentang huruf atau angka, Anda dapat menggunakan pemisah tanda hubung seperti pada [a – z] atau [a – mA – M]. Komplemen kelas karakter dilambangkan dengan tanda sisipan di depan tanda kurung siku seperti pada [∧a – z] dan mewakili semua karakter selain yang ditentukan.

Metode berikut tersedia untuk ekspresi reguler.

Sr.No. Metode & Deskripsi
1 pola ulang

Mengembalikan sebuah instance dari java.util.regex.Pattern. Ini kemudian digunakan dalam metode lebih lanjut untuk pencocokan pola.

2 menemukan kembali

Mengembalikan kecocokan regex berikutnya, jika ada, dari string ke pola, menggunakan java.util.regex.Matcher.find ()

3 menggantikan

Fungsi replace digunakan untuk mengganti substring dalam string dengan nilai string baru. Pencarian substring dilakukan dengan menggunakan pola.

4 ganti-dulu

Fungsi replace digunakan untuk mengganti substring dalam string dengan nilai string baru, tetapi hanya untuk substring yang pertama kali muncul. Pencarian substring dilakukan dengan menggunakan pola.

Predicatesadalah fungsi yang mengevaluasi suatu kondisi dan memberikan nilai benar atau salah. Kita telah melihat fungsi predikat dalam contoh bab tentang angka. Kami telah melihat fungsi seperti 'genap?' yang digunakan untuk menguji apakah suatu bilangan genap atau tidak, atau 'neg?' yang digunakan untuk menguji apakah suatu angka lebih besar dari nol atau tidak. Semua fungsi ini mengembalikan nilai benar atau salah.

Berikut contoh predikat di Clojure.

(ns clojure.examples.example
   (:gen-class))

;; This program displays Hello World
(defn Example []
   (def x (even? 0))
   (println x)
   
   (def x (neg? 2))
   (println x)
   
   (def x (odd? 3))
   (println x)
   
   (def x (pos? 3))
   (println x))
(Example)

Program di atas menghasilkan keluaran sebagai berikut.

true
false
true
true

Selain fungsi predikat normal, Clojure menyediakan lebih banyak fungsi untuk predikat. Metode berikut tersedia untuk predikat.

Sr.No. Metode & Deskripsi
1 every-pred

Mengambil sekumpulan predikat dan mengembalikan fungsi 'f' yang mengembalikan nilai true jika semua predikat penyusunnya mengembalikan nilai benar logis terhadap semua argumennya, jika tidak maka akan mengembalikan salah.

2 setiap?

Mengembalikan nilai benar jika predikatnya benar untuk setiap nilai, jika tidak salah.

3 beberapa

Mengembalikan nilai benar logis pertama untuk setiap nilai predikat x dalam kumpulan nilai.

4 tidak ada?

Menampilkan salah jika salah satu predikat nilai dalam koleksi secara logis benar, jika tidak benar.

Destructuring adalah fungsionalitas dalam Clojure, yang memungkinkan seseorang untuk mengekstrak nilai dari struktur data, seperti vektor dan mengikatnya ke simbol tanpa harus secara eksplisit melintasi struktur data.

Mari kita lihat contoh apa sebenarnya arti Destructuring dan bagaimana hal itu terjadi.

Contoh

(ns clojure.examples.example
   (:gen-class))
(defn Example []
   (def my-vector [1 2 3 4])
   (let [[a b c d] my-vector]
   (println a b c d)))
(Example)

Program di atas menghasilkan keluaran sebagai berikut.

Keluaran

1 2 3 4

Dalam contoh di atas, hal-hal berikut harus diperhatikan -

  • Kami mendefinisikan vektor bilangan bulat sebagai 1, 2, 3 dan 4.

  • Kami kemudian menggunakan ‘let’ pernyataan untuk menetapkan 4 variabel (a, b, c, dan d) ke variabel vektor-saya secara langsung.

  • Jika kita menjalankan ‘println’ pernyataan pada empat variabel, kita dapat melihat bahwa mereka telah ditugaskan ke nilai dalam vektor masing-masing.

Jadi clojure telah merusak variabel my-vector yang memiliki empat nilai ketika ditugaskan menggunakan pernyataan 'let'. Empat nilai yang didekonstruksi kemudian ditetapkan ke empat parameter yang sesuai.

Jika ada variabel berlebih yang tidak memiliki nilai terkait yang dapat ditetapkan, maka variabel tersebut akan diberi nilai nil. Contoh berikut menjelaskan hal ini.

Contoh

(ns clojure.examples.hello
   (:gen-class))
(defn Example []
   (def my-vector [1 2 3 4])
   (let [[a b c d e] my-vector]
   (println a b c d e)))
(Example)

Program di atas menghasilkan keluaran sebagai berikut. Anda dapat melihat dari output bahwa karena variabel terakhir 'e' tidak memiliki nilai yang sesuai dalam vektor, maka nilainya menjadi nihil.

Keluaran

1 2 3 4 nil

sisanya

Variabel 'the-rest' digunakan untuk menyimpan nilai yang tersisa, yang tidak bisa diberikan ke variabel apapun.

Contoh bagaimana ini digunakan ditunjukkan pada program berikut.

Contoh

(ns clojure.examples.example
   (:gen-class))
(defn Example []
   (def my-vector [1 2 3 4])
   (let [[a b & the-rest] my-vector]
   (println a b the-rest)))
(Example)

Program di atas menghasilkan keluaran sebagai berikut. Dari output, Anda dapat dengan jelas melihat bahwa nilai 3 dan 4 tidak dapat ditetapkan ke variabel apa pun sehingga nilai tersebut ditetapkan ke variabel 'sisanya'.

Keluaran

1 2 (3 4)

Merusak Peta

Sama seperti vektor, peta juga dapat dirusak. Berikut adalah contoh bagaimana hal ini dapat dicapai.

Contoh

(ns clojure.examples.example
   (:gen-class))
(defn Example []
   (def my-map {"a" 1 "b" 2})
   (let [{a "a" b "b"} my-map]
   (println a b)))
(Example)

Program di atas menghasilkan keluaran sebagai berikut. Dari program ini, Anda dapat dengan jelas melihat bahwa nilai peta "a" dan "b" diberikan ke variabel a dan b.

Keluaran

1 2

Demikian pula dalam kasus vektor, jika tidak ada nilai yang sesuai di peta saat penghancuran terjadi, maka variabel akan diberi nilai nil.

Berikut ini contohnya.

Contoh

(ns clojure.examples.example
   (:gen-class))
(defn Example []
   (def my-map {"a" 1 "b" 2})
   (let [{a "a" b "b" c "c"} my-map]
   (println a b c)))
(Example)

Program di atas menghasilkan keluaran sebagai berikut.

Keluaran

1 2 nil

Karena kerangka kerja Clojure diturunkan dari kelas-kelas Java, seseorang dapat menggunakan kelas-kelas tanggal-waktu yang tersedia di Java di Clojure. Ituclass date mewakili waktu instan tertentu, dengan presisi milidetik.

Berikut adalah metode yang tersedia untuk kelas tanggal-waktu.

java.util.Date

Ini digunakan untuk membuat objek tanggal di Clojure.

Sintaksis

Berikut adalah sintaksnya.

java.util.Date.

Parameters - Tidak ada.

Return Value - Mengalokasikan objek Tanggal dan menginisialisasinya sehingga mewakili waktu di mana ia dialokasikan, diukur ke milidetik terdekat.

Contoh

Contoh bagaimana ini digunakan ditunjukkan pada program berikut.

(ns example)
(defn Example []
   (def date (.toString (java.util.Date.)))
   (println date))
(Example)

Keluaran

Program di atas menghasilkan keluaran sebagai berikut. Ini akan tergantung pada tanggal dan waktu saat ini pada sistem, tempat program sedang dijalankan.

Tue Mar 01 06:11:17 UTC 2016

java.text.SimpleDateFormat

Ini digunakan untuk memformat keluaran tanggal.

Sintaksis

Berikut adalah sintaksnya.

(java.text.SimpleDateFormat. format dt)

Parameters- 'format' adalah format yang akan digunakan saat memformat tanggal. 'dt' adalah tanggal yang perlu diformat.

Return Value - Keluaran tanggal yang diformat.

Contoh

Contoh bagaimana ini digunakan ditunjukkan pada program berikut.

(ns example)
(defn Example []
   (def date (.format (java.text.SimpleDateFormat. "MM/dd/yyyy") (new java.util.Date)))
   (println date))
(Example)

Keluaran

Program di atas menghasilkan keluaran sebagai berikut. Ini akan tergantung pada tanggal dan waktu saat ini pada sistem, tempat program sedang dijalankan.

03/01/2016

getTime

Mengembalikan jumlah milidetik sejak 1 Januari 1970, 00:00:00 GMT diwakili oleh objek Tanggal ini.

Sintaksis

Berikut adalah sintaksnya.

(.getTime)

Parameters - Tidak ada.

Return Value - Jumlah milidetik sejak 1 Januari 1970, 00:00:00 GMT diwakili oleh tanggal ini.

Contoh

Contoh bagaimana ini digunakan ditunjukkan pada program berikut.

(ns example)
(import java.util.Date)
(defn Example []
   (def date (.getTime (java.util.Date.)))
   (println date))
(Example)

Keluaran

Program di atas menghasilkan keluaran sebagai berikut. Ini akan tergantung pada tanggal dan waktu saat ini pada sistem, tempat program sedang dijalankan.

1456812778160

Atomsadalah tipe data di Clojure yang menyediakan cara untuk mengelola status bersama, sinkron, dan independen. Sebuah atom sama seperti tipe referensi apa pun dalam bahasa pemrograman lainnya. Penggunaan utama atom adalah untuk menyimpan struktur data Clojure yang tidak dapat diubah. Nilai yang dipegang oleh sebuah atom diubah denganswap! method.

Secara internal, tukar! membaca nilai saat ini, menerapkan fungsinya, dan mencoba membandingkan-dan-mengaturnya. Karena thread lain mungkin telah mengubah nilai dalam waktu sela, ia mungkin harus mencoba lagi, dan melakukannya dalam putaran putaran. Efek bersihnya adalah bahwa nilai tersebut akan selalu menjadi hasil penerapan fungsi yang disediakan ke nilai saat ini, secara atomis.

Contoh

Atom dibuat dengan bantuan metode atom. Contoh yang sama ditunjukkan pada program berikut.

(ns clojure.examples.example
   (:gen-class))
(defn example []
   (def myatom (atom 1))
   (println @myatom))
(example)

Keluaran

Program di atas memberikan hasil sebagai berikut.

1

Nilai atom diakses dengan menggunakan simbol @. Clojure memiliki beberapa operasi yang dapat dilakukan pada atom. Berikut adalah operasinya.

Sr.No. Operasi & Deskripsi
1 reset!

Menetapkan nilai atom ke nilai baru tanpa memperhatikan nilai saat ini.

2 bandingkan-dan-set!

Secara atomis menetapkan nilai atom ke nilai baru jika dan hanya jika nilai atom saat ini identik dengan nilai lama yang dipegang oleh atom. Mengembalikan nilai benar jika set terjadi, jika tidak maka mengembalikan salah.

3 menukar!

Menukar nilai atom dengan yang baru secara atom berdasarkan fungsi tertentu.

Di Clojure, metadatadigunakan untuk membuat anotasi data dalam koleksi atau untuk data yang disimpan dalam simbol. Ini biasanya digunakan untuk menganotasi data tentang tipe ke kompiler yang mendasari, tetapi juga bisa digunakan untuk pengembang. Metadata tidak dianggap sebagai bagian dari nilai objek. Pada saat yang sama, metadata tidak dapat diubah.

Operasi berikut dapat dilakukan di Clojure yang berkaitan dengan metadata.

Sr.No. Operasi & Deskripsi
1 meta-dengan

Fungsi ini digunakan untuk mendefinisikan peta metadata untuk objek apapun.

2 meta

Fungsi ini digunakan untuk melihat apakah ada metadata yang dikaitkan dengan suatu objek.

3 variatif-meta

Mengembalikan objek dengan tipe dan nilai yang sama dengan objek asli, tetapi dengan metadata gabungan.

StructMapsdigunakan untuk membuat struktur di Clojure. Misalnya, jika Anda ingin membuat struktur yang terdiri dari Nama Karyawan dan ID Karyawan, Anda dapat melakukannya dengan StructMaps.

Operasi berikut dapat dilakukan di Clojure yang berkaitan dengan StructMaps.

Sr.No. Operasi & Deskripsi
1 defstruct

Fungsi ini digunakan untuk mendefinisikan struktur yang dibutuhkan.

2 struct

Fungsi ini digunakan untuk mendefinisikan objek struktur dari tipe, yang dibuat oleh operasi defstruct.

3 struct-map

Fungsi ini digunakan untuk secara khusus menetapkan nilai ke nilai kunci dengan secara eksplisit menentukan nilai mana yang akan ditetapkan ke kunci mana dalam struktur.

4 Mengakses Bidang Individual

Bidang individu struktur dapat diakses dengan mengakses kunci bersama dengan objek struktur.

5 Alam yang Abadi

Secara default, struktur juga tidak dapat diubah, jadi jika kita mencoba mengubah nilai kunci tertentu, itu tidak akan berubah.

6 Menambahkan Kunci Baru ke Struktur

Karena struktur tidak dapat diubah, satu-satunya cara agar kunci lain dapat ditambahkan ke struktur adalah melalui pembuatan struktur baru. Contoh bagaimana hal ini dapat dicapai ditunjukkan dalam program berikut.

Seperti yang ditunjukkan berkali-kali, Clojure adalah bahasa pemrograman di mana banyak tipe datanya tidak dapat diubah, yang berarti bahwa satu-satunya cara seseorang dapat mengubah nilai variabel adalah dengan membuat variabel baru dan menetapkan nilai baru padanya. Namun, Clojure memang menyediakan beberapa elemen, yang bisa membuat keadaan bisa berubah. Kita telah melihat bahwa ini dapat dicapai dengan tipe data atom. Cara lain untuk melakukannya adalah melalui Agen.

Agentsmenyediakan perubahan lokasi individu yang independen dan tidak sinkron. Agen terikat ke satu lokasi penyimpanan seumur hidup mereka, dan hanya mengizinkan mutasi lokasi tersebut (ke keadaan baru) terjadi sebagai hasil dari suatu tindakan. Tindakan adalah fungsi (dengan, opsional, argumen tambahan) yang diterapkan secara asinkron ke status Agen dan yang nilai kembaliannya menjadi status baru Agen.

Operasi berikut dapat dilakukan di Clojure sehubungan dengan Agen.

Sr.No. Operasi & Deskripsi
1 agen

Agen dibuat dengan menggunakan perintah agen.

2 Kirim

Fungsi ini digunakan untuk mengirimkan nilai ke agen.

3 agen penghenti

Fungsi ini digunakan untuk mematikan semua agen yang sedang berjalan.

4 mengirim

Ada contoh di mana agen diberi fungsi yang bersifat memblokir.

5 menunggu-untuk

Karena ada penundaan saat nilai agen diperbarui, Clojure menyediakan fungsi 'await-for' yang digunakan untuk menentukan waktu dalam milidetik untuk menunggu agen diperbarui.

6 menunggu

Memblokir thread saat ini (tanpa batas!) Hingga semua tindakan yang dikirim sejauh ini, dari thread atau agen ini, ke agen telah terjadi. Akan memblokir agen yang gagal.

7 agen-kesalahan

Mengembalikan pengecualian yang muncul selama tindakan asynchronous agen, jika agen gagal. Mengembalikan nol jika agen tidak gagal.

Watchersadalah fungsi yang ditambahkan ke jenis variabel seperti atom dan variabel referensi yang dipanggil saat nilai jenis variabel berubah. Misalnya, jika program pemanggil mengubah nilai variabel atom, dan jika fungsi pengamat dilampirkan ke variabel atom, fungsi tersebut akan dipanggil segera setelah nilai atom diubah.

Fungsi berikut tersedia di Clojure untuk Pengamat.

add-watch

Menambahkan fungsi jam tangan ke referensi agen / atom / var / ref. Jam tangan‘fn’harus berupa 'fn' dari 4 args: key, reference, old-state, new-state-nya. Kapan pun status referensi mungkin telah diubah, semua jam tangan terdaftar akan dipanggil fungsinya.

Sintaksis

Berikut adalah sintaksnya.

(add-watch variable :watcher
   (fn [key variable-type old-state new-state]))

Parameters- 'variabel' adalah nama atom atau variabel referensi. 'variable-type' adalah jenis variabel, baik atom atau variabel referensi. 'old-state & new-state' adalah parameter yang secara otomatis akan menyimpan nilai lama dan baru dari variabel. 'kunci' harus unik per referensi, dan dapat digunakan untuk melepas jam tangan dengan jam tangan lepas.

Return Value - Tidak ada.

Contoh

Contoh bagaimana ini digunakan ditunjukkan pada program berikut.

(ns clojure.examples.example
   (:gen-class))
(defn Example []
   (def x (atom 0))
   (add-watch x :watcher
      (fn [key atom old-state new-state]
      (println "The value of the atom has been changed")
      (println "old-state" old-state)
      (println "new-state" new-state)))
(reset! x 2))
(Example)

Keluaran

Program di atas menghasilkan keluaran sebagai berikut.

The value of the atom has been changed
old-state 0
new-state 2

lepas jam tangan

Menghapus jam tangan yang telah dilampirkan ke variabel referensi.

Sintaksis

Berikut adalah sintaksnya.

(remove-watch variable watchname)

Parameters- 'variabel' adalah nama atom atau variabel referensi. 'watchname' adalah nama yang diberikan ke arloji ketika fungsi arloji didefinisikan.

Return Value - Tidak ada.

Contoh

Contoh bagaimana ini digunakan ditunjukkan pada program berikut.

(ns clojure.examples.example
   (:gen-class))
(defn Example []
   (def x (atom 0))
   (add-watch x :watcher
      (fn [key atom old-state new-state]
         (println "The value of the atom has been changed")
         (println "old-state" old-state)
         (println "new-state" new-state)))
   (reset! x 2)
   (remove-watch x :watcher)
(reset! x 4))
(Example)

Keluaran

Program di atas menghasilkan keluaran sebagai berikut.

The value of the atom has been changed
old-state 0
new-state 2

Anda dapat dengan jelas melihat dari program di atas bahwa perintah reset kedua tidak memicu pengawas karena telah dihapus dari daftar pengawas.

Dalam bahasa apapun, Macrosdigunakan untuk menghasilkan kode sebaris. Clojure tidak terkecuali dan menyediakan fasilitas makro sederhana untuk pengembang. Makro digunakan untuk menulis rutinitas pembuatan kode, yang menyediakan cara yang efektif bagi pengembang untuk menyesuaikan bahasa dengan kebutuhan pengembang.

Berikut adalah metode yang tersedia untuk Macro.

defmacro

Fungsi ini digunakan untuk menentukan makro Anda. Makro akan memiliki nama makro, daftar parameter, dan badan makro.

Sintaksis

Berikut adalah sintaksnya.

(defmacro name [params*] body)

Parameters- 'name' adalah nama makro. 'params' adalah parameter yang ditetapkan ke makro. 'body' adalah tubuh makro.

Return Value - Tidak ada.

Contoh

Contoh bagaimana ini digunakan ditunjukkan pada program berikut.

(ns clojure.examples.example
   (:gen-class))
(defn Example []
   (defmacro Simple []
      (println "Hello"))
   (macroexpand '(Simple)))
(Example)

Keluaran

Program di atas menghasilkan keluaran sebagai berikut.

Hello

Dari program di atas Anda dapat melihat bahwa makro 'Sederhana' diperluas sebaris menjadi 'println' “Hello”. Makro mirip dengan fungsi, dengan satu-satunya perbedaan bahwa argumen ke formulir dievaluasi dalam kasus makro.

perluasan makro

Ini digunakan untuk memperluas makro dan menempatkan kode sebaris dalam program.

Sintaksis

Berikut adalah sintaksnya.

(macroexpand macroname)

Parameters - 'macroname' adalah nama makro yang perlu diperluas.

Return Value - Makro yang diperluas.

Contoh

Contoh bagaimana ini digunakan ditunjukkan pada program berikut.

(ns clojure.examples.example
   (:gen-class))
(defn Example []
   (defmacro Simple []
      (println "Hello"))
   (macroexpand '(Simple)))
(Example)

Keluaran

Program di atas menghasilkan keluaran sebagai berikut.

Hello

Makro dengan Argumen

Makro juga dapat digunakan untuk mengambil argumen. Makro dapat menerima sejumlah argumen. Contoh berikut menunjukkan bagaimana argumen dapat digunakan.

Example

(ns clojure.examples.example
   (:gen-class))
(defn Example []
   (defmacro Simple [arg]
      (list 2 arg))
   (println (macroexpand '(Simple 2))))
(Example)

The above example places an argument in the Simple macro and then uses the argument to add argument value to a list.

Output

The above program produces the following output.

(2 2)

Reference values are another way Clojure can work with the demand to have mutable variables. Clojure provides mutable data types such as atoms, agents, and reference types.

Following are the operations available for reference values.

Sr.No. Operations & Description
1 ref

This is used to create a reference value. When creating a reference value, there is an option to provide a validator function, which will validate the value created.

2 ref-set

This function is used to set the value of a reference to a new value irrespective of whatever is the older value.

3 alter

This function is used to alter the value of a reference type but in a safe manner. This is run in a thread, which cannot be accessed by another process.

4 dosync

Runs the expression (in an implicit do) in a transaction that encompasses expression and any nested calls.

5 commute

Commute is also used to change the value of a reference type just like alter and ref-set.

In order to use the database functionality, please ensure to first download the jdbc files from the following url − https://codeload.github.com/clojure/java.jdbc/zip/master

You will find a zip file which has the necessary drivers for Clojure to have the ability to connect to databases. Once the zip file is extracted, ensure to add the unzipped location to your classpath.

The main file for database connectivity is a file called jdbc.clj in the location clojure/java.

The clojure jdbc connector supports a wide variety of databases, some of which are the following.

  • H2Database
  • Oracle
  • Microsoft SQL Server
  • MySQL
  • PostgreSQL

In our example, we are going to use MySQL DB as an example.

The following operations are possible in Clojure with regards to Databases.

Database Connection

Before connecting to a MySQL database, make sure of the following −

  • You have created a database TESTDB.

  • You have created a table EMPLOYEE in TESTDB.

  • This table has fields FIRST_NAME, LAST_NAME, AGE, SEX and INCOME.

  • User ID "testuser" and password "test123" are set to access TESTDB.

  • Ensure you have downloaded the ‘mysql jar file’ and added the file to your classpath.

  • You have gone through MySQL tutorial to understand MySQL Basics.

Syntax

Following is the syntax to create a connection in Clojure.

(def connection_name {
   :subprotocol “protocol_name”
   :subname “Location of mysql DB”
   :user “username” :password “password” })

Parameters − ‘connection_name’ is the name to be given to the connection. ‘subprotocol’ is the protocol to be used for the connection. By default we will be using the mysql protocol. ‘subname’ is the url to connect to the mysql db along with the database name. ‘user’ is the username used to connect to the database. ‘password’ is the password to be used to connect to the database.

Return Value − This will provide a connection string, which can be used in subsequent mysql operations.

The following example shows how to connect to the tables in the information schema and retrieve all the data in the table.

Example

(ns test.core
   (:require [clojure.java.jdbc :as sql]))
(defn -main []
   (def mysql-db {
      :subprotocol "mysql"
      :subname "//127.0.0.1:3306/information_schema"
      :user "root"
      :password "shakinstev"})
   (println (sql/query mysql-db
      ["select table_name from tables"]
      :row-fn :table_name)))

Querying Data

Querying data on any database means to fetch some useful information from the database. Once a database connection is established, you are ready to make a query into this database. Following is the syntax by which data can be queried using Clojure.

Syntax

clojure.java.jdbc/query dbconn
["query"]
   :row-fn :sequence

Parameters − ‘dbconn’ is the name of the connection used to connect to the database. ‘query’ is the query string used to fetch data from the database. ‘:sequence’ is by default all the rows of data fetched from the database and is returned as a sequence. The necessary operations on the sequence can then be done to see what data has been fetched.

Return Value − This will return a sequence, which will have the rows of data from the query operation.

The following example shows how to connect to the employee table and fetch the first_name column of the rows in the table.

Example

(ns test.core
   (:require [clojure.java.jdbc :as sql]))
(defn -main []
   (def mysql-db {
      :subprotocol "mysql"
      :subname "//127.0.0.1:3306/testdb"
      :user "root"
      :password "shakinstev"})
   (println (sql/query mysql-db
      ["select first_name from employee"]
      :row-fn :first_name)))

From the above code, we can see that

  • The query of “select first_name from employee” is passed as the query string.

  • The :first_name is the sequence, which is returned as a result of the fetch operation.

If we assume that there is just one row in our database which contains a first_name value of John, following will be the output of the above program.

(John)

Inserting Data

It is required when you want to create your records into a database table. Following is the syntax by which data can be inserted using Clojure. This is done by using the ‘insert!’ function.

Syntax

clojure.java.jdbc/insert!
   :table_name {:column_namen columnvalue}

Parameters − ‘:table_name’ is the name of the table in which the insertion needs to be made. ‘{:column_namen columnvalue }’ is a map of all the column names and values, which need to be added as a row in the table.

Return Value − This will return nil if the insertion is made successfully.

The following example shows how to insert a record into the employee table in the testdb database.

Example

(ns test.core
   (:require [clojure.java.jdbc :as sql]))
(defn -main []
   (def mysql-db {
      :subprotocol "mysql"
      :subname "//127.0.0.1:3306/testdb"
      :user "root"
      :password "shakinstev"})
   (sql/insert! mysql-db
      :employee {:first_name "John" :last_name "Mark" :sex "M" :age 30 :income 30}))

If you now check your MySQL database and the employee table, you will see that the above row will be successfully inserted in the table.

Deleting Data

Rows can be deleted from a table by using the ‘delete!’ function. Following is the syntax on how this operation can be performed.

Syntax

clojure.java.jdbc/delete!
   :table_name [condition]

Parameters − ‘:table_name’ is the name of the table in which the insertion needs to be made. ‘condition’ is the condition used to determine which row needs to be deleted from the table.

Return Value − This will return the number of rows deleted.

The following example shows how to delete a record from the employee table in the testdb database. The example deletes a row from the table based on the condition that the age is equal to 30.

Example

(ns test.core
   (:require [clojure.java.jdbc :as sql]))
(defn -main []
   (def mysql-db {
      :subprotocol "mysql"
      :subname "//127.0.0.1:3306/testdb"
      :user "root"
      :password "shakinstev"})
   (println (sql/delete! mysql-db
      :employee ["age = ? " 30])))

If you had a record which had a row with age equal to the value of 30, that row will be deleted.

Updating Data

Rows can be updated from a table by using the ‘update!’ function. Following is the syntax on how this operation can be performed.

Syntax

clojure.java.jdbc/update!
   :table_name
{setcondition}
[condition]

Parameters − ‘:table_name’ is the name of the table in which the insertion needs to be made. ‘setcondition’ is the column which needs to be updated as mentioned in terms of a map. ‘condition’ is the condition which is used to determine which row needs to be deleted from the table.

Return Value − This will return the number of rows updated.

The following example shows how to delete a record from the employee table in the testdb database. The example updates a row from the table based on the condition that the age is equal to 30 and updates the value of income to 40.

(ns test.core
   (:require [clojure.java.jdbc :as sql]))
(defn -main []
   (def mysql-db {
      :subprotocol "mysql"
      :subname "//127.0.0.1:3306/testdb"
      :user "root"
      :password "shakinstev"})
   (println (sql/update! mysql-db
      :employee
      {:income 40}
      ["age = ? " 30])))

If you had a record which had a row with age equal to the value of 30, that row will be updated wherein the value of income will be set to 40.

Transactions

Transactions are mechanisms that ensure data consistency. Transactions have the following four properties −

  • Atomicity − Either a transaction completes or nothing happens at all.

  • Consistency − A transaction must start in a consistent state and leave the system in a consistent state.

  • Isolation − Intermediate results of a transaction are not visible outside the current transaction.

  • Durability − Once a transaction was committed, the effects are persistent, even after a system failure.

Example

The following example shows how to implement transactions in Clojure. Any operations which needs to be performed in a transaction needs to be embedded in the ‘with-dbtransaction’ clause.

(ns test.core
   (:require [clojure.java.jdbc :as sql]))
(defn -main []
   (def mysql-db {
      :subprotocol "mysql"
      :subname "//127.0.0.1:3306/testdb"
      :user "root"
      :password "shakinstev"})
   (sql/with-db-transaction [t-con mysql-db]
      (sql/update! t-con
         :employee
         {:income 40}
         ["age = ? " 30])))

As we already know, Clojure code runs on the Java virtual environment at the end. Thus it only makes sense that Clojure is able to utilize all of the functionalities from Java. In this chapter, let’s discuss the correlation between Clojure and Java.

Calling Java Methods

Java methods can be called by using the dot notation. An example is strings. Since all strings in Clojure are anyway Java strings, you can call normal Java methods on strings.

An example on how this is done is shown in the following program.

Example

(ns Project
   (:gen-class))
(defn Example []
   (println (.toUpperCase "Hello World")))
(Example)

The above program produces the following output. You can see from the code that if you just call the dot notation for any string method, it will also work in Clojure.

Output

HELLO WORLD

Calling Java Methods with Parameters

You can also call Java methods with parameters. An example on how this is done is shown in the following program.

Example

(ns Project
   (:gen-class))
(defn Example []
   (println (.indexOf "Hello World","e")))
(Example)

The above program produces the following output. You can see from the above code, that we are passing the parameter “e” to the indexOf method. The above program produces the following output.

Output

1

Creating Java Objects

Objects can be created in Clojure by using the ‘new’ keyword similar to what is done in Java.

An example on how this is done is shown in the following program.

Example

(ns Project
   (:gen-class))
(defn Example []
   (def str1 (new String "Hello"))
   (println str1))
(Example)

The above program produces the following output. You can see from the above code, that we can use the ‘new’ keyword to create a new object from the existing String class from Java. We can pass the value while creating the object, just like we do in Java. The above program produces the following output.

Output

Hello

Following is another example which shows how we can create an object of the Integer class and use them in the normal Clojure commands.

Example

(ns Project
   (:gen-class))
(defn Example []
   (def my-int(new Integer 1))
   (println (+ 2 my-int)))
(Example)

The above program produces the following output.

Output

3

Import Command

We can also use the import command to include Java libraries in the namespace so that the classes and methods can be accessed easily.

The following example shows how we can use the import command. In the example we are using the import command to import the classes from the java.util.stack library. We can then use the push and pop method of the stack class as they are.

Example

(ns Project
   (:gen-class))
(import java.util.Stack)
(defn Example []
   (let [stack (Stack.)]
   (.push stack "First Element")
   (.push stack "Second Element")
   (println (first stack))))
(Example)

Program di atas menghasilkan keluaran sebagai berikut.

Keluaran

First Element

Menjalankan Kode Menggunakan Perintah Java

Kode Clojure dapat dijalankan dengan menggunakan perintah Java. Berikut adalah sintaks bagaimana ini bisa dilakukan.

java -jar clojure-1.2.0.jar -i main.clj

Anda harus menyebutkan file jar Clojure, sehingga semua kelas berbasis Clojure akan dimuat di JVM. File 'main.clj' adalah file kode Clojure yang perlu dijalankan.

Fungsi Bawaan Java

Clojure dapat menggunakan banyak fungsi bawaan Java. Beberapa dari mereka adalah -

Math PI function- Clojure dapat menggunakan metode Matematika untuk nilai PI. Berikut adalah contoh kode.

Contoh

(ns Project
   (:gen-class))
(defn Example []
   (println (. Math PI)))
(Example)

Kode di atas menghasilkan keluaran sebagai berikut.

Keluaran

3.141592653589793

System Properties- Clojure juga dapat menanyakan properti sistem. Berikut adalah contoh kode.

Contoh

(ns Project
   (:gen-class))
(defn Example []
   (println (.. System getProperties (get "java.version"))))
(Example)

Bergantung pada versi Java di sistem, nilai yang sesuai akan ditampilkan. Berikut adalah contoh keluarannya.

Keluaran

1.8.0_45

Dalam pemrograman Clojure sebagian besar tipe data tidak dapat diubah, jadi ketika datang ke pemrograman bersamaan, kode yang menggunakan tipe data ini cukup aman ketika kode berjalan pada banyak prosesor. Namun seringkali, ada persyaratan untuk berbagi data, dan ketika datang ke data bersama di beberapa prosesor, menjadi penting untuk memastikan bahwa status data dipertahankan dalam hal integritas saat bekerja dengan banyak prosesor. Ini dikenal sebagaiconcurrent programming dan Clojure memberikan dukungan untuk pemrograman semacam itu.

Sistem memori transaksional perangkat lunak (STM), yang diekspos melalui dosync, ref, set, alter, dll. Mendukung berbagi perubahan status antar utas secara sinkron dan terkoordinasi. Sistem agen mendukung berbagi perubahan status antar utas secara asinkron dan independen. Sistem atom mendukung berbagi perubahan keadaan antar utas secara sinkron dan independen. Sedangkan sistem var dinamis, yang diekspos melalui def, binding, dll. Mendukung pengisolasian perubahan status dalam utas.

Bahasa pemrograman lain juga mengikuti model untuk pemrograman konkuren.

  • Mereka memiliki referensi langsung ke data yang dapat diubah.

  • Jika akses bersama diperlukan, objek dikunci, nilainya diubah, dan proses berlanjut untuk akses berikutnya ke nilai itu.

Di Clojure tidak ada kunci, tetapi referensi tidak langsung ke struktur data persisten yang tidak dapat diubah.

Ada tiga jenis referensi di Clojure.

  • Vars - Perubahan diisolasi dalam utas.

  • Refs - Perubahan disinkronkan dan dikoordinasikan antar utas.

  • Agents - Melibatkan perubahan independen asinkron antar utas.

Operasi berikut dimungkinkan di Clojure yang berkaitan dengan pemrograman bersamaan.

Transaksi

Concurrency di Clojure didasarkan pada transaksi. Referensi hanya dapat diubah dalam satu transaksi. Aturan berikut diterapkan dalam transaksi.

  • Semua perubahan bersifat atom dan terisolasi.
  • Setiap perubahan referensi terjadi dalam transaksi.
  • Tidak ada transaksi yang melihat efek yang dibuat oleh transaksi lain.
  • Semua transaksi ditempatkan di dalam blok dosync.

Kita sudah melihat apa yang dilakukan blok dosync, mari kita lihat lagi.

dosync

Menjalankan ekspresi (dalam do implisit) dalam transaksi yang mencakup ekspresi dan panggilan bertingkat apa pun. Memulai transaksi jika belum ada yang berjalan di utas ini. Pengecualian yang tidak tertangkap akan membatalkan transaksi dan keluar dari dosync.

Berikut adalah sintaksnya.

Sintaksis

(dosync expression)

Parameters - 'Ekspresi' adalah himpunan ekspresi yang akan ada di blok dosync.

Return Value - Tidak ada.

Mari kita lihat contoh di mana kami mencoba mengubah nilai variabel referensi.

Contoh

(ns clojure.examples.example
   (:gen-class))
(defn Example []
   (def names (ref []))
   (alter names conj "Mark"))
(Example)

Keluaran

Program di atas saat dijalankan memberikan kesalahan berikut.

Caused by: java.lang.IllegalStateException: No transaction running
   at clojure.lang.LockingTransaction.getEx(LockingTransaction.java:208)
   at clojure.lang.Ref.alter(Ref.java:173)
   at clojure.core$alter.doInvoke(core.clj:1866)
   at clojure.lang.RestFn.invoke(RestFn.java:443)
   at clojure.examples.example$Example.invoke(main.clj:5) at clojure.examples.example$eval8.invoke(main.clj:7)
   at clojure.lang.Compiler.eval(Compiler.java:5424)
   ... 12 more

Dari kesalahan tersebut Anda dapat dengan jelas melihat bahwa Anda tidak dapat mengubah nilai tipe referensi tanpa terlebih dahulu memulai transaksi.

Agar kode di atas berfungsi, kita harus menempatkan perintah alter dalam blok dosync seperti yang dilakukan pada program berikut.

Contoh

(ns clojure.examples.example
   (:gen-class))
(defn Example []
   (def names (ref []))
   
   (defn change [newname]
      (dosync
         (alter names conj newname)))
   (change "John")
   (change "Mark")
   (println @names))
(Example)

Program di atas menghasilkan keluaran sebagai berikut.

Keluaran

[John Mark]

Mari kita lihat contoh lain dari dosync.

Contoh

(ns clojure.examples.example
   (:gen-class))
(defn Example []
   (def var1 (ref 10))
   (def var2 (ref 20))
   (println @var1 @var2)
   
   (defn change-value [var1 var2 newvalue]
      (dosync
         (alter var1 - newvalue)
         (alter var2 + newvalue)))
   (change-value var1 var2 20)
   (println @var1 @var2))
(Example)

Dalam contoh di atas, kami memiliki dua nilai yang diubah dalam blok dosync. Jika transaksi berhasil, kedua nilai akan berubah jika tidak maka seluruh transaksi akan gagal.

Program di atas menghasilkan keluaran sebagai berikut.

Keluaran

10 20
-10 40

Clojure memiliki beberapa pustaka kontribusi yang memiliki kemampuan untuk membuat Desktop dan Web-based applications. Mari kita bahas satu per satu.

Sr.No. Aplikasi & Deskripsi
1 Desktop - Jungkat-jungkit

See-saw adalah pustaka yang dapat digunakan untuk membuat aplikasi desktop.

2 Desktop - Mengubah Nilai Teks

Nilai konten di jendela dapat diubah dengan menggunakan ‘config!’pilihan. Dalam contoh berikut, config! opsi digunakan untuk mengubah konten jendela ke nilai baru "Selamat tinggal".

3 Desktop - Menampilkan Kotak Dialog Modal

Kotak dialog modal dapat ditampilkan dengan menggunakan metode peringatan kelas jungkat-jungkit. Metode ini mengambil nilai teks, yang perlu ditampilkan di kotak dialog modal.

4 Desktop - Menampilkan Tombol

Tombol dapat ditampilkan dengan bantuan kelas tombol.

5 Desktop - Menampilkan Label

Label dapat ditampilkan dengan bantuan kelas label.

6 Desktop - Menampilkan Bidang Teks

Bidang Teks dapat ditampilkan dengan bantuan kelas teks.

Aplikasi Web - Pendahuluan

Untuk membuat aplikasi web di Clojure Anda perlu menggunakan perpustakaan aplikasi Ring, yang tersedia di tautan berikut https://github.com/ring-clojure/ring

Anda perlu memastikan Anda mengunduh toples yang diperlukan dari situs dan memastikan untuk menambahkannya sebagai dependensi untuk aplikasi Clojure.

Itu Ring framework menyediakan kemampuan berikut -

  • Mengatur hal-hal sedemikian rupa sehingga permintaan http masuk ke aplikasi web Anda sebagai Clojure HashMap biasa, dan juga membuatnya sehingga Anda dapat mengembalikan tanggapan sebagai HashMap.

  • Memberikan spesifikasi yang mendeskripsikan dengan tepat seperti apa tampilan peta permintaan dan respons tersebut.

  • Membawa server web (Jetty) dan menghubungkan aplikasi web Anda ke sana.

Kerangka kerja Ring secara otomatis dapat memulai server web dan memastikan aplikasi Clojure berfungsi di server ini. Kemudian seseorang juga dapat menggunakan kerangka kerja Compojure. Hal ini memungkinkan seseorang untuk membuat rute yang sekarang menjadi cara sebagian besar aplikasi web modern dikembangkan.

Creating your first Clojure application - Contoh berikut menunjukkan bagaimana Anda dapat membuat aplikasi web pertama Anda di Clojure.

(ns my-webapp.handler
   (:require [compojure.core :refer :all]
      [compojure.route :as route]
      [ring.middleware.defaults :refer [wrap-defaults site-defaults]]))
(defroutes app-routes
   (GET "/" [] "Hello World")
   (route/not-found "Not Found"))
(def app
   (wrap-defaults app-routes site-defaults))

Mari kita lihat aspek program berikut -

  • Itu ‘defroutes’ digunakan untuk membuat rute sehingga permintaan yang dibuat ke aplikasi web ke rute yang berbeda dapat diarahkan ke fungsi yang berbeda di aplikasi Clojure Anda.

  • Dalam contoh di atas, "/" dikenal sebagai rute default, jadi saat Anda menelusuri ke dasar aplikasi web Anda, string "Hello World" akan dikirim ke browser web.

  • Jika pengguna menemukan url apa pun yang tidak dapat diproses oleh aplikasi Clojure, maka itu akan menampilkan string "Tidak Ditemukan".

Saat Anda menjalankan aplikasi Clojure, secara default aplikasi Anda akan dimuat sebagai localhost: 3000, jadi jika Anda menjelajah ke lokasi ini, Anda akan menerima keluaran berikut.

Aplikasi Web - Menambahkan Lebih Banyak Rute ke Aplikasi Web Anda

Anda juga dapat menambahkan lebih banyak rute ke aplikasi web Anda. Contoh berikut menunjukkan bagaimana mencapai ini.

(ns my-webapp.handler
   (:require [compojure.core :refer :all]
      [compojure.route :as route]
      [ring.middleware.defaults :refer [wrap-defaults site-defaults]]))
(defroutes app-routes
   (GET "/" [] "Hello World")
   (GET "/Tutorial" [] "This is a tutorial on Clojure")
   (route/not-found "Not Found"))
(def app
   (wrap-defaults app-routes site-defaults))

Anda dapat melihat bahwa menambahkan rute dalam aplikasi itu semudah menambahkan fungsi GET lain dengan rute url. (GET "/ Tutorial" [] "Ini adalah tutorial tentang Clojure")

Jika Anda menelusuri ke lokasi http://localhost:3000/Tutorial, Anda akan menerima keluaran berikut.

Dalam bab ini, mari kita bahas opsi pengujian otomatis yang disediakan oleh Clojure.

Menguji Aplikasi Klien

Untuk menggunakan pengujian framework Clojure, Anda harus menggunakan dependensi yang terletak di https://github.com/slagyr/speclj#manual-installation

URL ini menyediakan specljframework, yang digunakan sebagai framework pengujian yang didorong oleh data atau perilaku untuk Clojure. Anda harus memastikan bahwa Anda menggunakan kerangka kerja Clojure 1.7.0 saat menggunakan salah satu pustaka 'speclj'. Secara default, file pengujian akan berbeda dari file kode Clojure dan perlu ditempatkan di direktori 'spec'.

Berikut ini adalah contoh kode untuk file tes.

(ns change.core-spec
   (:require [speclj.core :refer :all]))
(describe "Truth"
   (it "is true"
   (should true))
   (it "is not false"
   (should-not false)))
(run-specs)

Hal-hal berikut perlu diperhatikan tentang kode di atas -

  • Pertama-tama kita harus memastikan untuk menggunakan pernyataan 'require' untuk menyertakan semua pustaka inti dalam kerangka kerja 'speclj'.

  • Berikutnya adalah fungsi 'gambarkan'. Ini digunakan untuk memberikan deskripsi untuk kasus uji yang sedang dibuat.

  • Fungsi selanjutnya adalah fungsi 'it', yang merupakan kasus uji sebenarnya. Dalam kasus uji pertama, string "adalah benar" adalah nama yang diberikan untuk kasus uji.

  • Harus dan tidak boleh dikenal sebagai assertions. Semua pernyataan dimulai dengan seharusnya. Harus dan tidak boleh hanyalah dua dari sekian banyak pernyataan yang tersedia. Mereka berdua mengambil ekspresi bahwa mereka akan memeriksa kebenaran dan kepalsuan masing-masing.

Jika Anda menjalankan kasus uji, Anda akan mendapatkan output berikut. Keluarannya menunjukkan waktu yang dibutuhkan dalam milidetik untuk menjalankan kasus uji.

←[32m.←[0m←[32m.←[0m
Finished in 0.00014 seconds

Pengujian untuk Aplikasi Berbasis Web

Seleniumadalah salah satu kerangka kerja utama yang digunakan untuk menguji aplikasi berbasis web modern. Perpustakaan Clojure juga tersedia yang dapat digunakan untuk menguji aplikasi berbasis web.

Mari kita lihat bagaimana kita dapat menggunakan pustaka Selenium untuk menguji aplikasi berbasis web Clojure.

Step 1- Langkah pertama adalah memastikan kami menggunakan framework Ring and Compojure untuk membuat aplikasi berbasis web, yang perlu diuji. Mari gunakan salah satu contoh dari bab sebelumnya. Kode berikut adalah aplikasi web sederhana, yang menampilkan "Hello World" di browser.

(ns my-webapp.handler
   (:require [compojure.core :refer :all]
      [compojure.route :as route]
      [ring.middleware.defaults :refer [wrap-defaults site-defaults]]))
(defroutes app-routes
   (GET "/" [] "Hello World")
   (route/not-found "Not Found"))
(def app
   (wrap-defaults app-routes site-defaults))

Step 2 - Selanjutnya pastikan untuk mendownload file jar selenium https://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-server/2.47.0 dan memasukkannya ke classpath Anda.

Step 3 - Juga pastikan untuk mengunduh driver web 'clj', yang akan digunakan untuk menjalankan pengujian web dari lokasi berikut.

https://clojars.org/clj-webdriver/versions/0.7.1

Step 4 - Dalam direktori proyek Anda, buat direktori lain bernama fitur dan buat file bernama 'config.clj'.

Step 5 - Selanjutnya tambahkan kode berikut ke file 'config.clj' yang dibuat pada langkah sebelumnya.

ns clj-webdriver-tutorial.features.config)
(def test-port 3000)
(def test-host "localhost")
(def test-base-url (str "http://" test-host ":" test-port "/"))

Kode di atas pada dasarnya memberi tahu kerangka kerja pengujian web untuk menguji aplikasi, yang dimuat di URL http://localhost:3000

Step 6 - Terakhir, mari tulis kode kita untuk melakukan pengujian.

(ns clj-webdriver-tutorial.features.homepage
   (:require [clojure.test :refer :all]
      [ring.adapter.jetty :refer [run-jetty]]
      [clj-webdriver.taxi :refer :all]
      [clj-webdriver-tutorial.features.config :refer :all]
      [clj-webdriver-tutorial.handler :refer [app-routes]]))
(ns clj-webdriver-tutorial.features.homepage
   (:require [clojure.test :refer :all]
      [ring.adapter.jetty :refer [run-jetty]]
      [clj-webdriver.taxi :refer :all]
      [clj-webdriver-tutorial.features.config :refer :all]
      [clj-webdriver-tutorial.handler :refer [app-routes]]))
(defn start-server []
   (loop [server (run-jetty app-routes {:port test-port, :join? false})]
      (if (.isStarted server)
         server
         (recur server))))
(defn stop-server [server]
   (.stop server))
(defn start-browser []
   (set-driver! {:browser :firefox}))
(defn stop-browser []
   (quit))
(deftest homepage-greeting
   (let [server (start-server)]
      (start-browser)
      (to test-base-url)
      (is (= (text "body") "Hello World"))
      (stop-browser)
      (stop-server server)))

Kode di atas akan mengambil tindakan berikut -

  • Mulai server untuk aplikasi.
  • Buka jalur root di browser.
  • Periksa apakah pesan "Hello World" ada di halaman.
  • Tutup browser.
  • Matikan server.

Satu hal yang membuat perpustakaan Clojure begitu kuat adalah jumlah perpustakaan yang tersedia untuk kerangka kerja Clojure. Kami telah melihat begitu banyak pustaka yang digunakan dalam contoh sebelumnya untuk pengujian web, pengembangan web, pengembangan aplikasi berbasis ayunan, pustaka jdbc untuk menghubungkan ke database MySQL. Berikut ini hanyalah beberapa contoh dari beberapa perpustakaan lainnya.

data.xml

Pustaka ini memungkinkan Clojure bekerja dengan data XML. Versi pustaka yang akan digunakan adalah org.clojure / data.xml "0.0.8". Data.xml mendukung parsing dan emitting XML. Fungsi parsing akan membaca XML dari Reader atau InputStream.

Contoh

Berikut contoh pengolahan data dari string menjadi XML.

(ns clojure.examples.example
   (use 'clojure.data.xml)
   (:gen-class))
(defn Example []
   (let [input-xml (java.io.StringReader. "<?xml version = \"1.0\"
      encoding = \"UTF-8\"?><example><clo><Tutorial>The Tutorial
      value</Tutorial></clo></example>")]
      (parse input-xml)))

#clojure.data.xml.Element{
   :tag :example, :attrs {}, :content (#clojure.data.xml.Element {
      :tag :clo, :attrs {}, :content (#clojure.data.xml.Element {
         :tag :Tutorial, :attrs {},:content ("The Tutorial value")})})}
(Example)

data.json

Pustaka ini memungkinkan Clojure untuk bekerja dengan data JSON. Versi pustaka yang akan digunakan adalah org.clojure / data.json "0.2.6".

Contoh

Berikut adalah contoh penggunaan library ini.

(ns clojure.examples.example
   (:require [clojure.data.json :as json])
   (:gen-class))
(defn Example []
   (println (json/write-str {:a 1 :b 2})))
(Example)

Keluaran

Program di atas menghasilkan keluaran sebagai berikut.

{\"a\":1,\"b\":2}

data.csv

Pustaka ini memungkinkan Clojure untuk bekerja dengannya ‘csv’data. Versi pustaka yang akan digunakan adalah org.clojure / data.csv "0.1.3".

Contoh

Berikut adalah contoh penggunaan library ini.

(ns clojure.examples.example
   (require '[clojure.data.csv :as csv]
      '[clojure.java.io :as io])
   (:gen-class))
(defn Example []
   (with-open [in-file (io/reader "in-file.csv")]
      (doall
      (csv/read-csv in-file)))
   (with-open [out-file (io/writer "out-file.csv")]
   (csv/write-csv out-file
      [[":A" "a"]
      [":B" "b"]])))
(Example)

Pada kode di atas, fungsi 'csv' pertama-tama akan membaca file bernama in-file.csvdan letakkan semua data di variabel dalam file. Selanjutnya, kami menggunakan fungsi tulis-csv untuk menulis semua data ke file bernamaout-file.csv.