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.