Clojure-quick-guide
Clojure-概要
Clojureは、高レベルで動的な関数型プログラミング言語です。 Clojureは、LISPプログラミング言語に基づいて設計されており、Javaと.Netランタイム環境の両方で実行できるコンパイラーを備えています。
Clojureについて説明する前に、LISPプログラミング言語について簡単に説明しましょう。 LISPには小さな言語コアがあり、構文はほとんどなく、強力なマクロ機能があります。 これらの機能を使用すると、設計に合わせてLISPを曲げることができます。 LISPは1958年に長い間存在していました。
Common LISPは式を読み込み、評価してから結果を出力します。 たとえば、4 + 6の単純な数式の値を計算する場合は、入力します。
USER(1) (+ 4 6)
Clojureには、プログラミング言語として次の高レベルの主要な目的があります。
- LISPプログラミング言語に基づいており、コードステートメントを従来のプログラミング言語よりも小さくしています。
- 関数型プログラミング言語です。
- これは、不変性に焦点を当てています。不変性は、基本的に、適切に作成されたオブジェクトに変更を加えないという概念です。
- プログラマーのアプリケーションの状態を管理できます。
- 並行性をサポートします。
- 既存のプログラミング言語が含まれます。 たとえば、Clojureは、JVMを介したコードの実行の管理にJavaエコシステム全体を利用できます。
Clojureの公式Webサイトはhttps://clojure.org/です
Clojure-環境
Clojureをプログラミング言語として使用するには、さまざまな方法があります。 Clojureプログラミングで作業する2つの方法を見ていきます。
- Leiningen -Leiningenは、Clojureプロジェクトを作成、構築、および自動化するために不可欠なツールです。
- * Eclipseプラグイン*-CounterClockwiseと呼ばれるプラグインがあり、Eclipse IDEでClojure開発を実行するためにEclipseで使用できます。
ライニンゲンのインストール
インストールを進める前に、次のシステム要件が満たされていることを確認してください。
システム要求
JDK | JDK 1.7 or above |
Memory | 2 GB RAM (recommended) |
- ステップ1 *-バイナリインストールをダウンロードします。 リンクhttp://leiningen-win-installer.djpowell.net/[http://leiningen-wininstaller]にアクセスして、Windowsインストーラーを取得します。 オプションをクリックして、Groovyインストーラーのダウンロードを開始します。
- ステップ2 *-インストーラーを起動し、[次へ]ボタンをクリックします。
- ステップ3 *-インストールの場所を指定し、[次へ]ボタンをクリックします。
- ステップ4 *-セットアップは、既存のJavaインストールの場所を検出します。 [次へ]ボタンをクリックして続行します。
- ステップ5 *-[インストール]ボタンをクリックして、インストールを開始します。
インストールが完了すると、Clojure REPLを開くオプションが表示されます。ClojureREPLは、Clojureプログラムの作成とテストに使用できる環境です。
Eclipseのインストール
インストールを進める前に、次のシステム要件が満たされていることを確認してください。
システム要求
JDK | JDK 1.7 or above |
Eclipse | Eclipse 4.5 (Mars) |
- ステップ1 *-Eclipseを開き、メニュー項目をクリックします。 [ヘルプ]→[Eclipse Marketplace]をクリックします。
- ステップ2 *-表示されるダイアログボックスにキーワードClojureを入力し、[Go]ボタンを押します。 反時計回りのオプションが表示されます。[インストール]ボタンをクリックして、このプラグインのインストールを開始します。
- ステップ3 *-次のダイアログボックスで、[確認]ボタンをクリックしてインストールを開始します。
- ステップ4 *-次のダイアログボックスで、ライセンス契約に同意するように求められます。 ライセンス契約に同意し、[完了]ボタンをクリックしてインストールを続行します。
インストールが開始され、完了するとEclipseを再起動するように求められます。
Eclipseを再起動すると、Eclipseに新しいClojureプロジェクトを作成するオプションが表示されます。
Clojure-基本的な構文
Clojureの基本的な構文を理解するために、まず簡単なHello Worldプログラムを見てみましょう。
完全なプログラムとしてのHello World
完全なClojureプログラムで「Hello world」を作成します。 以下はその一例です。
例
(ns clojure.examples.hello
(:gen-class))
(defn hello-world []
(println "Hello World"))
(hello-world)
上記のプログラムについて、次のことに注意する必要があります。
- プログラムは、main.cljというファイルに書き込まれます。 拡張子「clj」は、clojureコードファイルの拡張子名です。 上記の例では、ファイルの名前はmain.cljです。
- 「defn」キーワードは、関数を定義するために使用されます。 関数の詳細については、別の章で説明します。 しかし今のところ、helloworldという関数を作成していることに注意してください。この関数にはメインのClojureコードが含まれます。
- Clojureコードでは、「println」ステートメントを使用して、コンソール出力に「Hello World」を出力しています。
- 次に、hello-world関数を呼び出して、「println」ステートメントを実行します。
上記のプログラムは、次の出力を生成します。
出力
Hello World
声明の一般的な形式
次の例に示すように、ステートメントの一般的な形式は中括弧で評価する必要があります。
(+ 1 2)
上記の例では、式全体が中括弧で囲まれています。 上記のステートメントの出力は3です。 + operatorは、数字の追加に使用されるClojureの関数のように機能します。 1および2の値は、*関数のパラメーター*として知られています。
別の例を考えてみましょう。 この例では、「str」は2つの文字列を連結するために使用される演算子です。 文字列「Hello」と「World」がパラメーターとして使用されます。
(str "Hello" "World")
例
上記の2つのステートメントを組み合わせてプログラムを作成すると、次のようになります。
(ns clojure.examples.hello
(:gen-class))
(defn Example []
(println (str "Hello World"))
(println (+ 1 2)))
(Example)
出力
上記のプログラムは、次の出力を生成します。
Hello World
3
ネームスペース
ネームスペースは、Clojureで定義されたモジュール間の論理境界を定義するために使用されます。
現在の名前空間
これは、現在のClojureコードが存在する現在のネームスペースを定義します。
構文
*ns*
例
REPLコマンドウィンドウで、次のコマンドを実行します。
*ns*
出力
上記のコマンドを実行すると、現在のネームスペースに応じて出力が遅延します。 以下は出力の例です。 Clojureコードの名前空間は-
clojure.examples.hello
(ns clojure.examples.hello
(:gen-class))
(defn Example []
(println (str "Hello World"))
(println (+ 1 2)))
(Example)
Clojureのステートメントが必要
Clojureコードはライブラリにパッケージ化されています。 各Clojureライブラリは、Javaパッケージに類似した名前空間に属します。 「Require」ステートメントを使用してClojureライブラリをロードできます。
構文
(require quoted-namespace-symbol)
例
以下は、このステートメントの使用例です。
(ns clojure.examples.hello
(:gen-class))
(require ‘clojure.java.io’)
(defn Example []
(.exists (file "Example.txt")))
(Example)
上記のコードでは、「require」キーワードを使用して、入出力機能に必要なすべての機能を備えた名前空間clojure.java.ioをインポートしています。 必要なライブラリがないため、上記のコードで「ファイル」関数を使用できます。
Clojureのコメント
コメントは、コードを文書化するために使用されます。 単一行のコメントは、;;を使用して識別されます。行の任意の位置。 以下はその一例です。
例
(ns clojure.examples.hello
(:gen-class))
;; This program displays Hello World
(defn Example []
(println "Hello World"))
(Example)
区切り記号
Clojureでは、曲線または角かっこを使用してステートメントを分割または区切ることができます。
例
以下に2つの例を示します。
(ns clojure.examples.hello
(:gen-class))
;; This program displays Hello World
(defn Example []
(println (+ 1 2 3)))
(Example)
出力
上記のプログラムは、次の出力を生成します。
6
例
以下は別の例です。
(ns clojure.examples.hello
(:gen-class))
;; This program displays Hello World
(defn Example []
(println [+ 1 2 3]))
(Example)
出力
上記のプログラムは、次の出力を生成します。
[#object[clojure.core$_PLUS_ 0x10f163b "clojure.core$_PLUS_@10f163b"] 1 2 3]
空白
Clojureでは、空白を使用してステートメントのさまざまなコンポーネントを分割し、明確にすることができます。 これは、コンマ(、)演算子を使用して実行できます。
たとえば、次の2つのステートメントは同等であり、両方のステートメントの出力は15になります。
(+ 1 2 3 4 5)
(+ 1, 2, 3, 4, 5)
Clojureはコンマを無視しますが、プログラマが読みやすいようにコンマを使用する場合があります。
たとえば、次のようなハッシュマップ(def a-map \ {:a 1:b 2:c 3})があり、REPLウィンドウでその値を要求すると、Clojureは出力を\ {:aとして出力します1、:b 2、:c 3}。
特に大量のデータを表示している場合は、結果が読みやすくなります。
シンボル
Clojureでは、シンボルは他のプログラミング言語の識別子と同等です。 しかし、他のプログラミング言語とは異なり、コンパイラはシンボルを実際の文字列値と見なします。 シンボルは値であるため、他のオブジェクトと同様に、シンボルをコレクションに格納し、関数などに引数として渡すことができます。
シンボルに含めることができるのは、英数字と「* +!/. :-_?」が数字またはコロンで始まってはいけません。
シンボルの有効な例を次に示します。
tutorial-point!
TUTORIAL
+tutorial+
Clojureプロジェクトの構造
最後に、Clojureプロジェクトの典型的なプロジェクト構造について話しましょう。 ClojureコードはJava仮想マシンで実行されるため、Clojure内のプロジェクト構造のほとんどは、Javaプロジェクトで見られるものと似ています。 以下は、ClojureプロジェクトのEclipseのサンプルプロジェクト構造のスナップショットです。
上記のプログラム構造について、次の重要事項に注意する必要があります。
- demo_1-これは、Clojureコードファイルが配置されているパッケージです。
- core.clj-これは、Clojureアプリケーションのコードを含むメインのClojureコードファイルです。
- Leiningenフォルダーには、Clojureベースのアプリケーションを実行するために必要なclojure-1.6.0.jarなどのファイルが含まれています。
- pom.propertiesファイルには、groupId、artifactId、Clojureプロジェクトのバージョンなどの情報が含まれます。
- project.cljファイルには、Clojureアプリケーション自体に関する情報が含まれています。 以下は、プロジェクトファイルの内容のサンプルです。
(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-v10l"
}
:dependencies [[org.clojure/clojure "1.6.0"]])
Clojure-REPL
REPL(read-eval-print loop)は、Clojureコードを実験するためのツールです。 実行中のプログラムと対話して、物事がうまくいくかどうかをすぐに試すことができます。 これを行うには、コードを入力できるプロンプトが表示されます。 次に、入力を読み取り、評価し、結果を出力してループし、再度プロンプトを表示します。
このプロセスにより、他のほとんどの言語では不可能な迅速なフィードバックサイクルが可能になります。
REPLセッションの開始
コマンドラインで次のコマンドを入力することにより、ライニンゲンでREPLセッションを開始できます。
lein repl
これにより、次のREPLウィンドウが起動します。
次に、必要に応じてREPLウィンドウでClojureコマンドの評価を開始します。
EclipseでREPLセッションを開始するには、[メニュー]オプションをクリックし、[実行]→[Clojureアプリケーション]に移動します。
これにより、コンソール出力とともに別のウィンドウで新しいREPLセッションが開始されます。
概念的には、REPLはSecure Shell(SSH)に似ています。 SSHを使用してリモートサーバーと対話できるのと同じ方法で、Clojure REPLを使用すると、実行中のClojureプロセスと対話できます。 この機能は非常に強力な場合があります。これは、REPLをライブプロダクションアプリにアタッチし、実行中にプログラムを変更することさえできるためです。
REPLの特殊変数
REPLにはいくつかの便利な変数が含まれています。広く使用されているのは、特殊変数* 1、* 2、および *3です。 これらは、最新の3つの式の結果を評価するために使用されます。
次の例は、これらの変数の使用方法を示しています。
user => "Hello"
Hello
user => "World"
World
user => (str* 2 *1)
HelloWorld
上記の例では、最初の2つの文字列がそれぞれ「Hello」および「World」としてREPL出力ウィンドウに送信されています。 次に、* 2および* 1変数を使用して、最後に評価された2つの式を呼び出します。
Clojure-データ型
Clojureは、さまざまな*組み込みデータ型*を提供します。
組み込みデータ型
以下は、Clojureで定義されているデータ型のリストです。
- 整数-以下はClojureで利用可能な整数の表現です。
- * 10進整数(Short、Long、およびInt)*-これらは整数を表すために使用されます。 たとえば、1234。
- * 8進数*-これらは、8進数で数値を表すために使用されます。 たとえば、012。
- * 16進数*-これらは、表現で数字を表すために使用されます。 たとえば、0xff。
- 基数-これらは基数表現で数を表すために使用されます。 たとえば、基数が2〜36の整数である2r1111です。
- 浮動小数点数
- デフォルトは、32ビット浮動小数点数を表すために使用されます。 たとえば、12.34。
- 他の表現は科学表記法です。 たとえば、1.35e-12。
- char -これは単一の文字リテラルを定義します。 文字はバックラッシ記号で定義されます。 たとえば、/e。
- ブール-これはブール値を表し、trueまたはfalseのいずれかです。
- 文字列-これらは、文字のチェーンの形式で表されるテキストリテラルです。 たとえば、「Hello World」。
- Nil -これは、ClojureでNULL値を表すために使用されます。
- Atom -Atomは、共有、同期、独立状態を管理する方法を提供します。 refsやvarsのような参照型です。
バインドされた値
Clojureのデータ型はすべてJavaから継承されているため、境界値はJavaプログラミング言語と同じです。 次の表は、数値リテラルと10進数リテラルの最大許容値を示しています。
literals | Ranges |
---|---|
Short | -32,768 to 32,767 |
int | -2,147,483,648 to 2,147,483,647 |
long | -9,223,372,036,854,775,808 to +9,223,372,036,854,775,807 |
float | 1.40129846432481707e-45 to 3.40282346638528860e+38 |
double | 4.94065645841246544e-324d to 1.79769313486231570e+308d |
クラスの数値型
プリミティブ型に加えて、次のオブジェクト型(ラッパー型と呼ばれることもあります)が許可されます。
Name | java.lang.Byte | java.lang.Short | java.lang.Integer | java.lang.Long | java.lang.Float | java.lang.Double |
---|
例
次のプログラムは、Clojureのデータ型を示すための統合された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)
出力
上記のプログラムは、次の出力を生成します。
1
1.25
Hello
Clojure-変数
Clojureでは、変数*は *‘def’ キーワードによって定義されます。 変数の概念がバインディングに関係している場合は少し異なります。 Clojureでは、値は変数にバインドされます。 Clojureで注意すべき重要な点の1つは、変数が不変であることです。つまり、変数の値を変更するには、その変数を破棄して再作成する必要があります。
Clojureの変数の基本タイプは次のとおりです。
- short -これは短い番号を表すために使用されます。 たとえば、10。
- int -これは整数を表すために使用されます。 たとえば、1234。
- long -これは、長い数値を表すために使用されます。 たとえば、10000090。
- float -32ビット浮動小数点数を表すために使用されます。 たとえば、12.34。
- char -これは単一の文字リテラルを定義します。 たとえば、「/a」。
- ブール-これはブール値を表し、trueまたはfalseのいずれかです。
- 文字列-これらは、文字のチェーンの形式で表されるテキストリテラルです。 たとえば、「Hello World」。
可変宣言
以下は、変数を定義する一般的な構文です。
構文
(def var-name var-value)
ここで、「var-name」は変数の名前、「var-value」は変数にバインドされた値です。
例
以下は、変数宣言の例です。
(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)
変数の命名
変数の名前は、文字、数字、およびアンダースコア文字で構成できます。 文字またはアンダースコアで始まる必要があります。 Clojureは、Javaが大文字と小文字を区別するプログラミング言語であるため、大文字と小文字は区別されます。
例
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)
注-上記のステートメントでは、大文字と小文字が区別されるため、ステータスとステータスはClojureで定義される2つの異なる変数です。
上記の例は、アンダースコア文字を使用して変数を定義する方法を示しています。
変数の印刷
ClojureはJVM環境を使用するため、「println」関数も使用できます。 次の例は、これを実現する方法を示しています。
例
(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)
出力
上記のプログラムは、次の出力を生成します。
1
1.25
Hello
Clojure-オペレーター
- 演算子*は、特定の数学的または論理的な操作を実行するようコンパイラーに指示する記号です。
Clojureには次のタイプの演算子があります-
- 算術演算子
- 関係演算子
- 論理演算子
- ビットごとの演算子
注-Clojureでは、演算子とオペランドは次の構文で機能します。
構文
(operator operand1 operand2 operandn)
例えば、
例
(+ 1 2)
上記の例は、数値1と2に対して算術演算を実行します。
算術演算子
Clojure言語は、通常の算術演算子を任意の言語としてサポートします。 Clojureで使用できる算術演算子は次のとおりです。
リンク:/clojure/clojure_arithmetic_operators [例を表示]
Operator | Description | Example |
---|---|---|
+ | Addition of two operands | (+ 1 2) will give 3 |
− | Subtracts second operand from the first | (- 2 1) will give 1 |
* | Multiplication of both operands | (* 2 2) will give 4 |
/ | Division of numerator by denominator | (float (/3 2)) will give 1.5 |
inc | Incremental operators used to increment the value of an operand by 1 | inc 5 will give 6 |
dec | Incremental operators used to decrement the value of an operand by 1 | dec 5 will give 4 |
max | Returns the largest of its arguments | max 1 2 3 will return 3 |
min | Returns the smallest of its arguments | min 1 2 3 will return 1 |
rem | Remainder of dividing the first number by the second | rem 3 2 will give 1 |
関係演算子
関係演算子を使用すると、オブジェクトを比較できます。 Clojureで使用できる関係演算子は次のとおりです。
リンク:/clojure/clojure_relational_operators [例を表示]
Operator | Description | Example |
---|---|---|
= | Tests the equality between two objects | (= 2 2) will give true |
not= | Tests the difference between two objects | (not = 3 2) will give true |
< | Checks to see if the left object is less than the right operand | (< 2 3) will give true |
⇐ | Checks to see if the left object is less than or equal to the right operand | (⇐ 2 3) will give true |
> | Checks to see if the left object is greater than the right operand | (> 3 2) will give true |
>= | Checks to see if the left object is greater than or equal to the right operand | (>= 3 2) will give true |
論理演算子
論理演算子は、ブール式を評価するために使用されます。 以下は、Groovyで使用可能な論理演算子です。
link:/clojure/clojure_logical_operators [例を表示]
Operator | Description | Example |
---|---|---|
and | This is the logical “and” operator | (or true true) will give true |
or | This is the logical “or” operator | (and true false) will give false |
*not * | This is the logical “not” operator | (not false) will give true |
次のコードスニペットは、さまざまな演算子の使用方法を示しています。
ビット演算子
Clojureは4つのビット演算子を提供します。 Clojureで使用できるビット演算子は次のとおりです。
リンク:/clojure/clojure_bitwise_operators [例を表示]
Sr.No. | Operator & Description |
---|---|
1 |
これはビット単位の「and」演算子です |
2 |
bit-or これはビット単位の「or」演算子です |
3 |
bit-xor これはビット単位の「xor」または排他的な「or」演算子です |
4 |
bit-not これはビットごとの否定演算子です |
以下は、これらの演算子を示す真理値表です。
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 |
演算子の優先順位
一般的なLISPの場合と同様に、演算子の優先順位について心配する必要はありません。 これは、S-Expressionsとプレフィックス表記の利点の1つです。 すべての関数は、左から右、裏返しで評価されます。 Clojureの演算子は単なる関数であり、すべてが括弧で囲まれています。
Clojure-ループ
これまでのところ、次々に順番に実行されるステートメントを見てきました。 さらに、プログラムのロジックの制御の流れを変更するために、Clojureでステートメントが提供されます。 次に、これらは制御ステートメントのフローに分類され、詳細に説明します。
Sr.No. | Loops & Description |
---|---|
1 |
|
2 |
|
3 |
|
4 |
ループの特別な形式は、 'for' ループとは異なります。 ループの使用法はletバインディングと同じです。 ただし、ループは再帰ポイントを設定します |
Clojure-意思決定
- 意思決定構造*では、プログラマーが、プログラムによって評価またはテストされる1つ以上の条件、条件が真であると判断された場合に実行されるステートメント、およびオプションで実行される他のステートメントを指定する必要があります条件が偽と判断された場合。
Sr.No. | Methods & Description |
---|---|
1 |
Clojureでは、条件はtrueまたはfalseであると評価する式です。 'If' 条件が真の場合、ステートメント#1が実行され、そうでない場合はステートメント#2が実行されます。 |
2 |
Clojureの 'if-do' 式は、「if」ステートメントの各ブランチに対して複数の式を実行できるようにするために使用されます。 |
3 |
相互に埋め込まれた複数の 'if' ステートメント。 |
4 |
Clojureは、Javaプログラミング言語で使用可能な 'switch' ステートメントに似た 'case' ステートメントを提供します。 |
5 |
Clojureは、 'cond' ステートメントと呼ばれる別の評価ステートメントを提供しています。 このステートメントは、テスト/式のペアのセットを取ります。 |
Clojure-関数
Clojureは関数型プログラミング言語として知られているため、Clojureで関数がどのように機能するかに重点を置くことが期待されます。 この章では、Clojureの関数を使用してできることをすべて説明します。
Sr.No. | Functions & Description |
---|---|
1 |
関数は 'defn' マクロを使用して定義されます。 |
2 |
無名関数は、名前が関連付けられていない関数です。 |
3 |
Functions with Multiple Arguments Clojure関数は、ゼロ個以上のパラメーターで定義できます。 関数に渡す値は arguments と呼ばれ、引数はどのタイプでもかまいません。 |
4 |
Clojureは、Javaプログラミング言語で使用可能な「switch」ステートメントに似た「case」ステートメントを提供します。 |
5 |
高階関数(HOF)は、他の関数を引数として取る関数です。 HOFは重要な関数型プログラミング手法であり、Clojureで非常に一般的に使用されています。 |
Clojure-数字
Clojureの Numbers データ型はJavaクラスから派生しています。
Clojureは整数と浮動小数点数をサポートしています。
- 整数は、分数を含まない値です。
- 浮動小数点数は、小数を含む小数値です。
以下は、Clojureの数字の例です。
(def x 5)
(def y 5.25)
「x」は Integer タイプで、「y」は float です。
Javaでは、Clojureで定義された番号に次のクラスが添付されます。
Clojureの数値がJavaクラスから派生したことを実際に確認するには、次のプログラムを使用して、「def」コマンドの使用時に割り当てられた数値のタイプを確認します。
例
(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)
*'type'* コマンドは、変数に割り当てられた値に関連付けられたクラスを出力するために使用されます。
出力
上記のコードは次の出力を生成します。
Java.lang.long
Java.lang.double
番号テスト
次のテスト関数は、数字に対して使用できます。
Sr.No. | Numbers & Description |
---|---|
1 |
数値がゼロの場合はtrue、そうでない場合はfalseを返します。 |
2 |
数値がゼロより大きい場合はtrue、そうでない場合はfalseを返します。 |
3 |
数値がゼロより小さい場合はtrueを返し、そうでない場合はfalseを返します。 |
4 |
数値が偶数の場合はtrueを返し、数値が整数でない場合は例外をスローします。 |
5 |
数値が奇数の場合はtrueを返し、数値が整数でない場合は例外をスローします。 |
6 |
数値が実際に数値である場合にtrueを返します。 |
7 |
数値が整数の場合、trueを返します。 |
8 |
数値がfloatの場合、trueを返します。 |
Clojure-再帰
前のトピックで再帰ステートメントを見てきましたが、「for」ループはループに似ていますが、 recur はClojureの実際のループです。
プログラミングの経験がある場合は、関数型言語の主要な機能である末尾再帰について聞いたことがあるかもしれません。 この再帰特殊形式は、末尾再帰を実装する形式です。 「末尾再帰」という言葉が示すように、末尾位置で再帰を呼び出す必要があります。 つまり、再帰は最後に評価される必要があります。
recurステートメントの最も単純な例は、「for」ループ内で使用されます。 次の例では、recurステートメントを使用して変数「i」の値を変更し、変数の値をループ式にフィードバックしています。
例
(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)
出力
上記のプログラムは、次の出力を生成します。
0
1
2
3
4
Clojure-ファイルI/O
Clojureは、I/Oを操作するときに多くのヘルパーメソッドを提供します。 ファイルに次の機能を提供する簡単なクラスを提供します。
- ファイルを読む
- ファイルへの書き込み
- ファイルがファイルかディレクトリかを確認する
Clojureが提供しているファイル操作のいくつかを見てみましょう。
ファイルの内容を文字列全体として読み取る
ファイルの内容全体を文字列として取得する場合は、 clojure.core.slurp メソッドを使用できます。 slurpコマンドは、ファイルのリーダーを開き、その内容をすべて読み取り、文字列を返します。
以下は、これを行う方法の例です。
(ns clojure.examples.hello
(:gen-class))
;; This program displays Hello World
(defn Example []
(def string1 (slurp "Example.txt"))
(println string1))
(Example)
ファイルに次の行が含まれている場合、それらは次のように印刷されます-
line : Example1
line : Example2
ファイルの内容を一度に1行ずつ読み取る
ファイルの内容全体を一度に1行ずつ文字列として取得する場合は、 clojure.java.io/reader メソッドを使用できます。 clojure.java.io/readerクラスは、ファイルの各行を読み取るために使用されるリーダーバッファーを作成します。
以下は、これを行う方法を示す例です。
(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)
ファイルに次の行が含まれている場合、それらは次のように印刷されます-
line : Example1
line : Example2
出力は次のように表示されます-
["line : Example1" "line : Example2"]
「宛先」ファイルの書き込み
「to」ファイルを書きたい場合は、 clojure.core.spit コマンドを使用して、文字列全体をファイルに吐き出すことができます。 spitコマンドは、slurpメソッドの反対です。 このメソッドは、ファイルをライターとして開き、コンテンツを書き込んでからファイルを閉じます。
以下はその一例です。
(ns clojure.examples.hello
(:gen-class))
;; This program displays Hello World
(defn Example []
(spit "Example.txt"
"This is a string"))
上記の例では、Example.txtファイルの内容が表示されている場合、「これは文字列です」の内容が表示されます。
「to」ファイルを1行ずつ書き込む
「to」ファイルを一度に1行ずつ書き込みたい場合は、 clojure.java.io.writer クラスを使用できます。 clojure.java.io.writerクラスは、データのバイトがストリームに送られ、その後ファイルに送られるライターストリームを作成するために使用されます。
以下は、spitコマンドの使用方法を示す例です。
(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)
上記のコードを実行すると、Example.txtファイルに「hello world」という行が表示されます。 append:trueオプションは、データをファイルに追加することです。 このオプションが指定されていない場合、ファイルにデータが書き込まれるたびにファイルが上書きされます。
ファイルが存在するかどうかを確認する
ファイルが存在するかどうかを確認するには、 clojure.java.io.file クラスを使用してファイルの存在を確認できます。 以下は、これを達成する方法を示す例です。
(ns clojure.examples.hello
(:gen-class))
;; This program displays Hello World
(defn Example []
(println (.exists (clojure.java.io/file "Example.txt"))))
(Example)
ファイルExample.txtが存在する場合、出力はtrueになります。
コンソールからの読み取り
コンソールからデータを読み取るには、 read-line ステートメントを使用できます。 以下は、これの使用方法を示す例です。
REPLウィンドウで(読み取り行)コマンドを入力すると、コンソールウィンドウに入力を行う機会があります。
user->(read-line)
Hello World
上記のコードは次の出力を生成します。
“Hello World”
Clojure-文字列
Clojureでは、文字列テキストを引用符で囲むことにより、 String リテラルが構築されます。 Clojureの文字列は、「Hello World」などの二重引用符を使用して作成する必要があります。
例
以下は、Clojureでの文字列の使用例です。
(ns clojure.examples.hello
(:gen-class))
(defn hello-world []
(println "Hello World")
(println "This is a demo application"))
(hello-world)
出力
上記のプログラムは、次の出力を生成します。
Hello World
This is a demo application
基本的な文字列操作
Clojureには、文字列に対して実行できる多くの操作があります。 操作は次のとおりです。
Sr.No. | String Operations & Description |
---|---|
1 |
文字列の連結は、単純なstr関数によって実行できます。 |
2 |
文字列のフォーマットは、単純なフォーマット機能によって実行できます。 format関数は、* java.lang.String.format。*を使用して文字列をフォーマットします |
3 |
文字列の文字数を返します。 |
4 |
「s」の部分文字列を返します。開始文字列で始まり、末尾文字列で終了します(デフォルトは文字列の長さです)。 |
5 |
「x」が論理的に「より小さい」、「等しい」、「より大きい」「y」の場合、負の数、ゼロ、または正の数を返します。 |
6 |
文字列をすべて小文字に変換します。 |
7 |
文字列をすべて大文字に変換します。 |
8 |
(seq collection)によって返されるコレクション内のすべての要素のストリングを、オプションのセパレーターで区切って返します。 |
9 |
正規表現で文字列を分割します。 |
10 |
分割文字列は、エスケープ文字\ nまたは\ r \ nに基づいています。 |
11 |
文字列内の文字を反転します。 |
12 |
文字列内の一致のすべてのインスタンスを置換文字列で置き換えます。 |
13 |
文字列の両端から空白を削除します。 |
14 |
文字列の左側から空白を削除します。 |
15 |
文字列の右側から空白を削除します。 |
Clojure-リスト
*List* は、データ項目のコレクションを格納するために使用される構造です。 Clojureでは、リストは *ISeq* インターフェースを実装します。 リストは、リスト関数を使用してClojureで作成されます。
例
以下は、Clojureで数値のリストを作成する例です。
(ns clojure.examples.example
(:gen-class))
(defn example []
(println (list 1 2 3 4)))
(example)
出力
上記のコードは次の出力を生成します。
(1 2 3 4)
以下は、Clojureでキャラクターのリストを作成する例です。
(ns clojure.examples.example
(:gen-class))
(defn example []
(println (list 'a 'b 'c 'd)))
(example)
上記のコードは次の出力を生成します。
(a b c d)
Clojureで使用できるリストメソッドは次のとおりです。
Sr.No. | Lists & Description |
---|---|
1 |
残りの前に追加されたアイテムを含む新しいリストを作成します。最後のアイテムはシーケンスとして扱われます。 |
2 |
この関数は、リストの最初のアイテムを返します。 |
3 |
この関数は、リストの「n番目」の位置にあるアイテムを返します。 |
4 |
要素がリストの先頭に追加された新しいリストを返します。 |
5 |
リストが先頭にあり、追加される要素が末尾に配置されている新しいリストを返します。 |
6 |
リストの最初のアイテムの後の残りのアイテムを返します。 |
Clojure-セット
Clojureの*セット*は一意の値のセットです。 セットは、setコマンドの助けを借りてClojureで作成されます。
例
以下は、Clojureでのセットの作成の例です。
(ns clojure.examples.example
(:gen-class))
(defn example []
(println (set '(1 1 2 2))))
(example)
出力
上記のコードは次の出力を生成します。
#{1,2}
以下は、Clojureで使用できるセットのメソッドです。
Sr.No. | Sets & Description |
---|---|
1 |
要素のソートされたセットを返します。 |
2 |
インデックス位置の要素を返します。 |
3 |
セットに特定の要素が含まれているかどうかを調べます。 |
4 |
要素をセットに追加し、新しい要素セットを返します。 |
5 |
セットから要素を切り離します。 |
6 |
入力セットの和集合であるセットを返します |
7 |
残りのセットの要素がない最初のセットであるセットを返します。 |
8 |
入力セットの共通部分であるセットを返します。 |
9 |
set1はset2のサブセットですか? |
10 |
set1はset2のスーパーセットですか? |
Clojure-ベクトル
*Vector* は、連続した整数でインデックス付けされた値のコレクションです。 ベクターは、Clojureのベクターメソッドを使用して作成されます。
例
以下は、Clojureでベクターを作成する例です。
(ns clojure.examples.example
(:require [clojure.set :as set])
(:gen-class))
(defn example []
(println (vector 1 2 3)))
(example)
出力
上記のコードは次の出力を生成します。
[1 2 3]
Clojureで使用できるメソッドは次のとおりです。
Sr.No. | Vectors & Description |
---|---|
1 |
単一のプリミティブ型「t」の新しいベクトルを作成します。「t」は:int:long:float:double:byte:short:charまたは:booleanのいずれかです。 |
2 |
この関数は、ベクトルのn番目の位置にあるアイテムを返します。 |
3 |
ベクター内のインデックス位置にある要素を返します。 |
4 |
要素をベクターに追加し、ベクター要素の新しいセットを返します。 |
5 |
リストまたはキューの場合、最初のアイテムなしで新しいリスト/キューを返します。ベクトルの場合、最後のアイテムなしで新しいベクトルを返します。 |
6 |
開始インデックスと終了インデックスからサブベクトルを返します。 |
Clojure-マップ
*Map* は、キーを値にマップするコレクションです。 ハッシュとソートの2つの異なるマップタイプが提供されます。 *HashMaps* は、hashCodeおよびequalsを正しくサポートするキーを必要とします。 *SortedMaps* には、Comparableを実装するキー、またはComparatorのインスタンスが必要です。
マップは2つの方法で作成できます。1つ目は、ハッシュマップメソッドを使用する方法です。
作成-HashMaps
HashMapは典型的なキー値関係を持ち、ハッシュマップ関数を使用して作成されます。
(ns clojure.examples.example
(:gen-class))
(defn example []
(def demokeys (hash-map "z" "1" "b" "2" "a" "3"))
(println demokeys))
(example)
出力
上記のコードは次の出力を生成します。
{z 1, b 2, a 3}
作成-SortedMaps
SortedMapには、キー要素に基づいて要素を並べ替えるという独自の特性があります。 以下は、sorted-map関数を使用してソート済みマップを作成する方法を示す例です。
(ns clojure.examples.example
(:gen-class))
(defn example []
(def demokeys (sorted-map "z" "1" "b" "2" "a" "3"))
(println demokeys))
(example)
上記のコードは次の出力を生成します。
{a 3, b 2, z 1}
上記のプログラムから、マップ内の要素がキー値に従ってソートされていることが明確にわかります。 以下は、マップに使用できるメソッドです。
Sr.No. | Maps & Description |
---|---|
1 |
キーにマップされた値、not-found、またはキーが存在しない場合はnilを返します。 |
2 |
マップに必要なキーが含まれているかどうかを確認します。 |
3 |
キーのマップエントリを返します。 |
4 |
マップ内のキーのリストを返します。 |
5 |
マップ内の値のリストを返します。 |
6 |
キー値エントリをマップから分離します。 |
7 |
2つのマップエントリを1つの単一のマップエントリにマージします。 |
8 |
最初に結合された残りのマップで構成されるマップを返します。 |
9 |
キーがキーにあるマップ内のエントリのみを含むマップを返します。 |
10 |
現在のHashMapのキーの名前を新しく定義されたものに変更します。 |
11 |
値がキーになり、その逆になるようにマップを反転します。 |
Clojure-名前空間
Clojureの Namespaces は、Javaのようにクラスを個別の論理空間に区別するために使用されます。 次の文を検討してください。
(:require [clojure.set :as set])
上記のステートメントで、「clojure.set」は、プログラムで使用されるさまざまなクラスとメソッドを含む名前空間です。 たとえば、上記の名前空間には、キー値のマップを反転するために使用されるmap-invertという関数が含まれています。 この名前空間を含めるようにプログラムに明示的に指示しない限り、この関数を使用することはできません。
名前空間に使用できるさまざまなメソッドを見てみましょう。
Sr.No. | Methods & Description |
---|---|
1 |
これは、現在のネームスペースを見るために使用されます。 |
2 |
これは、新しいネームスペースを作成し、実行中のプログラムに関連付けるために使用されます。 |
3 |
現在のネームスペースのエイリアスを別のネームスペースに追加します。 引数は2つのシンボルです:使用されるエイリアスとターゲット名前空間のシンボル名。 |
4 |
すべての名前空間のリストを返します。 |
5 |
特定の名前空間を検索して返します。 |
6 |
特定の名前空間の名前を返します。 |
7 |
ネームスペースに関連付けられているエイリアスを返します。 |
8 |
名前空間のすべてのマッピングのマップを返します。 |
9 |
キーがキーにあるマップ内のエントリのみを含むマップを返します。 |
Clojure-例外処理
アプリケーションの通常のフローを維持できるように、ランタイムエラーを処理するには、プログラミング言語で*例外処理*が必要です。 例外は通常、アプリケーションの通常のフローを中断します。これが、アプリケーションで例外処理を使用する必要がある理由です。
例外は大きく次のカテゴリに分類されます-
- チェック済み例外-RuntimeExceptionおよびErrorを除くThrowableクラスを拡張するクラスは、チェック済み例外と呼ばれます。 E.g. IOException、SQLExceptionなど チェックされた例外はコンパイル時にチェックされます。
Example.txtというファイルを操作する次のプログラムを考えてみましょう。 ただし、ファイルExample.txtが存在しない場合は常に存在する可能性があります。
(ns clojure.examples.example
(:gen-class))
;; This program displays Hello World
(defn Example []
(def string1 (slurp "Example.txt"))
(println string1))
(Example)
ファイルExample.txtが存在しない場合、プログラムによって次の例外が生成されます。
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)
上記の例外から、プログラムがFileNotFoundExceptionを発生させたことが明確にわかります。
- 未チェックの例外-RuntimeExceptionを拡張するクラスは、未チェックの例外として知られています。 たとえば、ArithmeticException、NullPointerException、ArrayIndexOutOfBoundsExceptionなど。 未チェックの例外はコンパイル時にチェックされず、実行時にチェックされます。
古典的なケースの1つは、ArrayIndexOutOfBoundsExceptionです。これは、配列の長さよりも大きい配列のインデックスにアクセスしようとしたときに発生します。 以下は、この種の間違いの典型的な例です。
(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)
上記のコードが実行されると、次の例外が発生します。
caught exception: java.lang.ArrayIndexOutOfBoundsException: 5
This is our final block
Let's move on
エラー
エラーは回復不能です。 OutOfMemoryError、VirtualMachineError、AssertionErrorなど。 これらは、プログラムが回復できないエラーであり、プログラムをクラッシュさせます。 これらの例外が存在する場合にプログラムを実行し続けることができるように、これらの例外をキャッチするメカニズムが必要になりました。
次の図は、Clojureの例外の階層がどのように編成されているかを示しています。 すべてJavaで定義された階層に基づいています。
例外をキャッチする
他のプログラミング言語と同じように、Clojureは通常の「try-catch」ブロックを提供して、例外が発生したときにそれをキャッチします。
try-catchブロックの一般的な構文は次のとおりです。
(try
(//Protected code)
catch Exception e1)
(//Catch block)
例外を発生させる可能性のあるすべてのコードは、*保護されたコードブロック*に配置されます。
- catchブロック*で、アプリケーションが例外から回復できるように、カスタムコードを記述して例外を処理できます。
file-not-found例外を生成した以前の例を見て、try catchブロックを使用してプログラムによって発生した例外をキャッチする方法を見てみましょう。
(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)
上記のプログラムは、次の出力を生成します。
caught exception: Example.txt (No such file or directory)
上記のコードから、* tryブロック*に障害のあるコードをラップします。 catchブロックでは、例外をキャッチして、例外が発生したというメッセージを出力しているだけです。 これで、プログラムによって生成された例外をキャプチャする意味のある方法ができました。
複数のキャッチブロック
複数のタイプの例外を処理するために、複数のcatchブロックを使用できます。 キャッチブロックごとに、発生した例外のタイプに応じて、それに応じて処理するコードを記述します。
以前のコードを修正して、2つのcatchブロックを含めます。1つはファイルが見つからないという例外に固有のもので、もう1つは一般的な例外ブロック用です。
(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)
上記のプログラムは、次の出力を生成します。
caught file exception: Example.txt (No such file or directory)
Let's move on
上記の出力から、一般的なブロックではなく、「FileNotFoundException」キャッチブロックによって例外がキャッチされたことが明確にわかります。
最後にブロック
finallyブロックは、tryブロックまたはcatchブロックの後に続きます。 例外の発生に関係なく、コードの最終ブロックは常に実行されます。
finallyブロックを使用すると、保護されたコードで何が起こっても、実行するクリーンアップタイプのステートメントを実行できます。 このブロックの構文は次のとおりです。
(try
(//Protected code)
catch Exception e1)
(//Catch block)
(finally
//Cleanup code)
上記のコードを変更して、最終的にコードのブロックを追加しましょう。 以下はコードスニペットです。
(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)
上記のプログラムは、次の出力を生成します。
caught file exception: Example.txt (No such file or directory)
This is our final block
Let's move on
上記のプログラムから、catchブロックが必要な例外をキャッチした後に、最終ブロックも実装されていることがわかります。
ClojureはJavaと同様にJavaから例外処理を派生させるため、Clojureでは例外を管理するために次のメソッドを使用できます。
- * public String getMessage()*-発生した例外に関する詳細なメッセージを返します。 このメッセージは、Throwableコンストラクターで初期化されます。
- * public Throwable getCause()*-Throwableオブジェクトで表される例外の原因を返します。
- * public String toString()*-getMessage()の結果と連結されたクラスの名前を返します。
- * public void printStackTrace()*-toString()の結果とスタックトレースをSystem.err、エラー出力ストリームに出力します。
- * public StackTraceElement [] getStackTrace()*-スタックトレース上の各要素を含む配列を返します。 インデックス0の要素は呼び出しスタックの一番上を表し、配列の最後の要素は呼び出しスタックの一番下のメソッドを表します。
- * public Throwable fillInStackTrace()*-このThrowableオブジェクトのスタックトレースを現在のスタックトレースで埋め、スタックトレースの以前の情報に追加します。
上記のメソッドの一部を使用するサンプルコードを次に示します。
(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)
上記のプログラムは、次の出力を生成します。
caught file exception: java.io.FileNotFoundException: Example.txt (No such file
or directory)
This is our final block
Let's move on
Clojure-シーケンス
シーケンス*は、 *‘seq’ コマンドを使用して作成されます。 以下は、シーケンス作成の簡単な例です。
(ns clojure.examples.example
(:gen-class))
;; This program displays Hello World
(defn Example []
(println (seq [1 2 3])))
(Example)
上記のプログラムは、次の出力を生成します。
(1 2 3)
以下は、シーケンスに使用できるさまざまな方法です。
Sr.No. | Methods & Description |
---|---|
1 |
「x」が最初の要素で、「seq」が残りの新しいシーケンスを返します。 |
2 |
「x」がシーケンスの末尾に追加される要素である新しいシーケンスを返します。 |
3 |
これは、2つのシーケンスを連結するために使用されます。 |
4 |
明確な要素がシーケンスに追加されることを保証するためにのみ使用されます。 |
5 |
シーケンス内の要素を反転します。 |
6 |
シーケンスの最初の要素を返します。 |
7 |
シーケンスの最後の要素を返します。 |
8 |
最初の要素を除くシーケンス全体を返します。 |
9 |
要素のソートされたシーケンスを返します。 |
10 |
削除する必要がある要素の数に基づいて、シーケンスから要素を削除します。 |
11 |
シーケンスから要素の最後のリストを取得します。 |
12 |
シーケンスから要素の最初のリストを取得します。 |
13 |
アイテムのシーケンスを2つの部分に分割します。 分割が発生する場所が指定されます。 |
Clojure-正規表現
- 正規表現*は、テキスト内のサブストリングを見つけるために使用されるパターンです。 正規表現はさまざまなプログラミング言語で使用され、LISPタイプのプログラミング言語で多く使用されます。
以下は、正規表現の例です。
//d+
上記の正規表現は、文字列内の数字のもう1つの出現を見つけるために使用されます。//文字は、文字「d」および「+」が正規表現を表すために使用されるようにするために使用されます。
一般に、正規表現は次のルールセットで機能します。
- 行の開始と終了を示すために使用される2つの特別な位置文字があります:キャレット(∧)とドル記号($):
- 正規表現には数量詞も含めることができます。 プラス記号(+)は、式の前の要素に適用される1回以上を表します。 アスタリスク(*)は、0個以上のオカレンスを表すために使用されます。 疑問符(?)はゼロまたは1回を示します。
- メタ文字\ {および}は、前の文字のインスタンスの特定の数と一致するために使用されます。
- 正規表現では、ピリオド記号(。)は任意の文字を表すことができます。 これは、ワイルドカード文字として説明されます。
- 正規表現には文字クラスが含まれる場合があります。 文字のセットは、[aeiou]のように、メタ文字[and]で囲まれた単純な文字列として指定できます。 文字または数字の範囲には、[a–z]または[a–mA–M]のようにダッシュ区切り文字を使用できます。 文字クラスの補数は、[∧a–z]のように角括弧内の先頭のキャレットで示され、指定された文字以外のすべての文字を表します。
正規表現には次のメソッドを使用できます。
Sr.No. | Methods & Description |
---|---|
1 |
java.util.regex.Patternのインスタンスを返します。 これは、パターンマッチングのその他の方法で使用されます。 |
2 |
java.util.regex.Matcher.find()を使用して、パターンに文字列の次の正規表現が一致する場合、それを返します。 |
3 |
replace関数は、ストリング内のサブストリングを新しいストリング値で置き換えるために使用されます。 部分文字列の検索は、パターンを使用して行われます。 |
4 |
replace関数は、文字列内の部分文字列を新しい文字列値で置き換えるために使用されますが、最初に出現するのは部分文字列のみです。 部分文字列の検索は、パターンを使用して行われます。 |
Clojure-述語
- 述語*は、条件を評価し、trueまたはfalseの値を提供する関数です。 数字の章の例で述語関数を見てきました。 数値が偶数かどうかをテストするために使用される「偶数?」や、数値がゼロより大きいかどうかをテストするために使用される「否定」などの関数を見てきました。 これらの関数はすべて、trueまたはfalseの値を返します。
以下は、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)
上記のプログラムは、次の出力を生成します。
true
false
true
true
通常の述語関数に加えて、Clojureは述語のためのより多くの関数を提供します。 述語には次のメソッドを使用できます。
Sr.No. | Methods & Description |
---|---|
1 |
一連の述語を取り、すべての構成述語がそのすべての引数に対して論理的な真の値を返す場合はtrueを返す関数 'f’を返します。それ以外の場合はfalseを返します。 |
2 |
述語がすべての値に対して真である場合は真を返し、そうでない場合は偽を返します。 |
3 |
値のコレクション内のxの述語値の最初の論理的な真の値を返します。 |
4 |
コレクション内の値の述語のいずれかが論理的にtrueの場合はfalseを返し、そうでない場合はtrueを返します。 |
Clojure-破壊
*Destructuring* はClojure内の機能であり、データ構造を明示的に走査することなく、ベクターなどのデータ構造から値を抽出し、シンボルにバインドできます。
破壊の正確な意味と、それがどのように発生するかを見てみましょう。
例
(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)
上記のプログラムは、次の出力を生成します。
出力
1 2 3 4
上記の例では、次のことに注意してください-
- 整数のベクトルを1、2、3、4として定義しています。
- 次に、 ’let’ ステートメントを使用して、4つの変数(a、b、c、およびd)をmy-vector変数に直接割り当てます。
- 4つの変数に対して 'println' ステートメントを実行すると、それぞれがベクトルの値に既に割り当てられていることがわかります。
そのため、clojureは、「let」ステートメントを使用して割り当てられたときに4つの値を持つmy-vector変数を非構造化しました。 分解された4つの値は、それに応じて4つのパラメーターに割り当てられました。
割り当てることができる対応する値を持たない余分な変数がある場合は、nilの値が割り当てられます。 次の例は、この点を明確にします。
例
(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)
上記のプログラムは、次の出力を生成します。 出力から、最後の変数 'e’にはベクトルに対応する値がないため、nilであることがわかります。
出力
1 2 3 4 nil
残り
「残り」変数は、変数に割り当てられない残りの値を格納するために使用されます。
これがどのように使用されるかの例は、次のプログラムに示されています。
例
(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)
上記のプログラムは、次の出力を生成します。 出力から、3と4の値を変数に割り当てることができないため、「the-rest」変数に割り当てられていることが明確にわかります。
出力
1 2 (3 4)
マップの破壊
ベクトルと同様に、マップも非構造化できます。 以下は、これを実現する方法の例です。
例
(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)
上記のプログラムは、次の出力を生成します。 プログラムから、「a」と「b」のマップ値がaとbの変数に割り当てられていることが明確にわかります。
出力
1 2
同様に、ベクトルの場合、破壊が発生したときにマップに対応する値がない場合、変数にはnilの値が割り当てられます。
以下はその一例です。
例
(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)
上記のプログラムは、次の出力を生成します。
出力
1 2 nil
Clojure-日付と時刻
ClojureフレームワークはJavaクラスから派生しているため、ClojureのJavaで使用可能な日時クラスを使用できます。 *クラスの日付*は、特定の瞬間をミリ秒の精度で表します。
以下は、日時クラスで使用できるメソッドです。
java.util.Date
これは、Clojureで日付オブジェクトを作成するために使用されます。
構文
構文は次のとおりです。
java.util.Date.
パラメータ-なし。
戻り値-Dateオブジェクトを割り当て、初期化して、最も近いミリ秒まで測定された、割り当てられた時間を表すようにします。
例
これがどのように使用されるかの例は、次のプログラムに示されています。
(ns example)
(defn Example []
(def date (.toString (java.util.Date.)))
(println date))
(Example)
出力
上記のプログラムは、次の出力を生成します。 これは、プログラムが実行されているシステムの現在の日付と時刻に依存します。
Tue Mar 01 06:11:17 UTC 2016
java.text.SimpleDateFormat
これは、日付出力のフォーマットに使用されます。
構文
構文は次のとおりです。
(java.text.SimpleDateFormat. format dt)
パラメータ-「フォーマット」は、日付をフォーマットするときに使用されるフォーマットです。 「dt」はフォーマットが必要な日付です。
戻り値-フォーマットされた日付出力。
例
これがどのように使用されるかの例は、次のプログラムに示されています。
(ns example)
(defn Example []
(def date (.format (java.text.SimpleDateFormat. "MM/dd/yyyy") (new java.util.Date)))
(println date))
(Example)
出力
上記のプログラムは、次の出力を生成します。 これは、プログラムが実行されているシステムの現在の日付と時刻に依存します。
03/01/2016
時間をもらう
このDateオブジェクトで表される1970年1月1日00:00:00 GMT以降のミリ秒数を返します。
構文
構文は次のとおりです。
(.getTime)
パラメータ-なし。
戻り値-この日付で表される1970年1月1日00:00:00 GMT以降のミリ秒数。
例
これがどのように使用されるかの例は、次のプログラムに示されています。
(ns example)
(import java.util.Date)
(defn Example []
(def date (.getTime (java.util.Date.)))
(println date))
(Example)
出力
上記のプログラムは、次の出力を生成します。 これは、プログラムが実行されているシステムの現在の日付と時刻に依存します。
1456812778160
Clojure-アトム
*Atoms* は、共有、同期、独立状態を管理する方法を提供するClojureのデータ型です。 アトムは、他のプログラミング言語の参照型とまったく同じです。 アトムの主な用途は、Clojureの不変のデータ構造を保持することです。 アトムが保持する値は、* swap!で変更されます。 方法*。
内部的には、スワップ! 現在の値を読み取り、関数を適用して、比較と設定を試みます。 別のスレッドが介入時間内に値を変更した可能性があるため、再試行する必要があり、スピンループで変更します。 最終的な効果は、値が常に現在の値に提供された関数をアトミックに適用した結果になることです。
例
原子はatomメソッドの助けを借りて作成されます。 同じ例が次のプログラムに示されています。
(ns clojure.examples.example
(:gen-class))
(defn example []
(def myatom (atom 1))
(println @myatom))
(example)
出力
上記のプログラムは次の結果を生成します。
1
アトムの値には、@記号を使用してアクセスします。 Clojureには、原子に対して実行できる操作がいくつかあります。 操作は次のとおりです。
Sr.No. | Operations & Description |
---|---|
1 |
現在の値に関係なく、アトムの値を新しい値に設定します。 |
2 |
アトムの現在の値がアトムによって保持されている古い値と同一である場合にのみ、アトムの値を新しい値に原子的に設定します。 設定された場合はtrueを返し、そうでない場合はfalseを返します。 |
3 |
特定の関数に基づいて、原子の値を新しい原子と原子的に交換します。 |
Clojure-メタデータ
Clojureでは、 metadata を使用して、コレクション内のデータに注釈を付けたり、シンボルに格納されたデータに注釈を付けたりします。 これは通常、基礎となるコンパイラーに型に関するデータに注釈を付けるために使用されますが、開発者にも使用できます。 メタデータは、オブジェクトの値の一部とは見なされません。 同時に、メタデータは不変です。
Clojureでは、メタデータに関して次の操作が可能です。
Sr.No. | Operations & Description |
---|---|
1 |
この関数は、オブジェクトのメタデータマップを定義するために使用されます。 |
2 |
この関数は、オブジェクトにメタデータが関連付けられているかどうかを確認するために使用されます。 |
3 |
元のオブジェクトと同じタイプと値のオブジェクトを返しますが、メタデータが組み合わされています。 |
Clojure-StructMaps
*StructMaps* は、Clojureで構造を作成するために使用されます。 たとえば、従業員名と従業員IDで構成される構造を作成する場合は、StructMapsを使用して作成できます。
StructMapsに関するClojureでは、次の操作が可能です。
Sr.No. | Operations & Description |
---|---|
1 |
この関数は、必要な構造を定義するために使用されます。 |
2 |
この関数は、defstruct操作によって作成されるタイプの構造体オブジェクトを定義するために使用されます。 |
3 |
この関数は、構造内のどのキーにどの値を割り当てるかを明示的に定義することにより、キー値に値を明確に割り当てるために使用されます。 |
4 |
構造オブジェクトと共にキーにアクセスすることにより、構造の個々のフィールドにアクセスできます。 |
5 |
デフォルトでは構造も不変であるため、特定のキーの値を変更しようとしても変更されません。 |
6 |
Adding a New Key to the Structure 構造は不変であるため、別のキーを構造に追加できる唯一の方法は、新しい構造を作成することです。 これを実現する方法の例を次のプログラムに示します。 |
Clojure-エージェント
何度も指摘されているように、Clojureは多くのデータ型が不変であるプログラミング言語です。つまり、変数の値を変更できる唯一の方法は、新しい変数を作成して新しい値を割り当てることです。 ただし、Clojureには、可変状態を作成できる要素がいくつかあります。 これは、原子データ型を使用して実現できることがわかりました。 これを実現するもう1つの方法は、エージェントを使用することです。
- エージェント*は、個々の場所の独立した非同期の変更を提供します。 エージェントは、その存続期間中、単一の保管場所にバインドされ、アクションの結果としてその場所の変更(新しい状態への変更)のみを許可します。 アクションは、エージェントの状態に非同期的に適用され、戻り値がエージェントの新しい状態になる関数(オプションで、追加の引数を含む)です。
Clojureでは、エージェントに関して次の操作が可能です。
Sr.No. | Operations & Description |
---|---|
1 |
エージェントは、agentコマンドを使用して作成されます。 |
2 |
この関数は、値を介してエージェントに送信するために使用されます。 |
3 |
この関数は、実行中のエージェントをシャットダウンするために使用されます。 |
4 |
エージェントが本来ブロックしている機能を割り当てられている場合があります。 |
5 |
エージェントの値が更新されると遅延が発生するため、Clojureはエージェントの更新を待機する時間をミリ秒単位で指定するために使用される「待機」機能を提供しました。 |
6 |
このスレッドまたはエージェントからエージェントにこれまでにディスパッチされたすべてのアクションが発生するまで、現在のスレッドをブロックします(無期限に!)。 失敗したエージェントをブロックします。 |
7 |
エージェントが失敗した場合、エージェントの非同期アクション中にスローされた例外を返します。 エージェントが失敗しない場合、nilを返します。 |
Clojure-ウォッチャー
*Watchers* は、変数タイプの値が変更されたときに呼び出されるアトムや参照変数などの変数タイプに追加される関数です。 たとえば、呼び出し側プログラムがアトム変数の値を変更し、ウォッチャー関数がアトム変数に関連付けられている場合、アトムの値が変更されるとすぐに関数が呼び出されます。
Clojure for Watchersでは、次の機能を使用できます。
ウォッチを追加
監視機能をagent/atom/var/ref参照に追加します。 時計 'fn' は、4つの引数の 'fn’でなければなりません:キー、参照、その古い状態、新しい状態。 参照の状態が変更された可能性があるときはいつでも、登録されているすべてのウォッチに関数が呼び出されます。
構文
構文は次のとおりです。
(add-watch variable :watcher
(fn [key variable-type old-state new-state]))
パラメータ-「変数」はアトムまたは参照変数の名前です。 「変数タイプ」は、原子または参照変数の変数タイプです。 「古い状態と新しい状態」は、変数の古い値と新しい値を自動的に保持するパラメーターです。 「キー」は参照ごとに一意である必要があり、remove-watchで時計を削除するために使用できます。
戻り値-なし。
例
これがどのように使用されるかの例は、次のプログラムに示されています。
(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)
出力
上記のプログラムは、次の出力を生成します。
The value of the atom has been changed
old-state 0
new-state 2
削除する
参照変数にアタッチされているウォッチを削除します。
構文
構文は次のとおりです。
(remove-watch variable watchname)
パラメータ-「変数」はアトムまたは参照変数の名前です。 「ウォッチ名」は、ウォッチ機能が定義されているときにウォッチに付けられる名前です。
戻り値-なし。
例
これがどのように使用されるかの例は、次のプログラムに示されています。
(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)
出力
上記のプログラムは、次の出力を生成します。
The value of the atom has been changed
old-state 0
new-state 2
上記のプログラムから、2番目のリセットコマンドはウォッチャーのリストから削除されたためウォッチャーをトリガーしないことが明確にわかります。
Clojure-マクロ
どの言語でも、 Macro はインラインコードの生成に使用されます。 Clojureも例外ではなく、開発者にシンプルなマクロ機能を提供します。 マクロは、コード生成ルーチンを記述するために使用されます。これにより、開発者は開発者のニーズに合わせて言語を調整する強力な方法を提供できます。
以下は、マクロで使用できるメソッドです。
デフマクロ
この関数は、マクロを定義するために使用されます。 マクロには、マクロ名、パラメーターリスト、およびマクロの本文が含まれます。
構文
構文は次のとおりです。
(defmacro name [params*] body)
パラメータ-「名前」はマクロの名前です。 「params」は、マクロに割り当てられたパラメーターです。 「body」はマクロの本体です。
戻り値-なし。
例
これがどのように使用されるかの例は、次のプログラムに示されています。
(ns clojure.examples.example
(:gen-class))
(defn Example []
(defmacro Simple []
(println "Hello"))
(macroexpand '(Simple)))
(Example)
出力
上記のプログラムは、次の出力を生成します。
Hello
上記のプログラムから、マクロ「Simple」がインラインで「println」「Hello」に展開されていることがわかります。 マクロは関数に似ていますが、マクロの場合にフォームへの引数が評価されるという唯一の違いがあります。
マクロ展開
これは、マクロを展開し、プログラム内にコードをインラインで配置するために使用されます。
構文
構文は次のとおりです。
(macroexpand macroname)
パラメータ-「マクロ名」は、展開する必要があるマクロの名前です。
戻り値-展開されたマクロ。
例
これがどのように使用されるかの例は、次のプログラムに示されています。
(ns clojure.examples.example
(:gen-class))
(defn Example []
(defmacro Simple []
(println "Hello"))
(macroexpand '(Simple)))
(Example)
出力
上記のプログラムは、次の出力を生成します。
Hello
引数付きマクロ
マクロを使用して引数を受け取ることもできます。 マクロは任意の数の引数を取ることができます。 次の例は、引数の使用方法を示しています。
例
(ns clojure.examples.example
(:gen-class))
(defn Example []
(defmacro Simple [arg]
(list 2 arg))
(println (macroexpand '(Simple 2))))
(Example)
上記の例では、Simpleマクロに引数を配置し、その引数を使用して引数値をリストに追加します。
出力
上記のプログラムは、次の出力を生成します。
(2 2)
Clojure-参照値
- 参照値*は、Clojureが可変変数を持つという要求に対応できるもう1つの方法です。 Clojureは、原子、エージェント、参照型などの可変データ型を提供します。
参照値に使用できる操作は次のとおりです。
Sr.No. | Operations & Description |
---|---|
1 |
これは、参照値を作成するために使用されます。 参照値を作成するとき、作成された値を検証する検証機能を提供するオプションがあります。 |
2 |
この関数は、古い値に関係なく、参照の値を新しい値に設定するために使用されます。 |
3 |
この関数は、参照型の値を安全な方法で変更するために使用されます。 これはスレッドで実行され、別のプロセスからはアクセスできません。 |
4 |
式とネストされた呼び出しを含むトランザクションで式を(暗黙のdoで)実行します。 |
5 |
Commuteは、alterやref-setと同様に、参照型の値を変更するためにも使用されます。 |
Clojure-データベース
データベース機能を使用するには、まず次のURLから* jdbcファイル*をダウンロードしてください-https://codeload.github.com/clojure/java.jdbc/zip/master
Clojureがデータベースに接続するために必要なドライバーを含むzipファイルがあります。 zipファイルを抽出したら、解凍した場所をクラスパスに追加してください。
データベース接続のメインファイルは、clojure/javaの場所にある jdbc.clj というファイルです。
clojure jdbcコネクターは、さまざまなデータベースをサポートしていますが、その一部は次のとおりです。
- H2Database
- オラクル
- Microsoft SQL Server
- MySQL
- PostgreSQL
この例では、MySQL DBを例として使用します。
Clojureでは、データベースに関して次の操作が可能です。
データベース接続
MySQLデータベースに接続する前に、次のことを確認してください-
- データベースTESTDBを作成しました。
- TESTDBにテーブルEMPLOYEEを作成しました。
- このテーブルには、FIRST_NAME、LAST_NAME、AGE、SEX、およびINCOMEフィールドがあります。
- ユーザーID「testuser」とパスワード「test123」は、TESTDBにアクセスするように設定されています。
- 「mysql jarファイル」をダウンロードし、ファイルをクラスパスに追加したことを確認してください。
- MySQL Basicsを理解するためにMySQLチュートリアルを完了しました。
構文
Clojureで接続を作成する構文は次のとおりです。
(def connection_name {
:subprotocol “protocol_name”
:subname “Location of mysql DB”
:user “username” :password “password” })
パラメータ-「connection_name」は、接続に付けられる名前です。 「サブプロトコル」は、接続に使用されるプロトコルです。 デフォルトでは、mysqlプロトコルを使用します。 「サブネーム」は、データベース名とともにmysql dbに接続するURLです。 「user」は、データベースへの接続に使用されるユーザー名です。 「パスワード」は、データベースへの接続に使用されるパスワードです。
戻り値-これは、後続のmysql操作で使用できる接続文字列を提供します。
次の例は、情報スキーマ内のテーブルに接続し、テーブル内のすべてのデータを取得する方法を示しています。
例
(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)))
データのクエリ
任意のデータベースのデータを照会すると、データベースからいくつかの有用な情報を取得することを意味します。 データベース接続が確立されると、このデータベースにクエリを実行する準備が整います。 以下は、Clojureを使用してデータを照会できる構文です。
構文
clojure.java.jdbc/query dbconn
["query"]
:row-fn :sequence
パラメータ-「dbconn」は、データベースへの接続に使用される接続の名前です。 「クエリ」は、データベースからデータを取得するために使用されるクエリ文字列です。 「:sequence」はデフォルトで、データベースからフェッチされたデータのすべての行であり、シーケンスとして返されます。 その後、シーケンスで必要な操作を実行して、フェッチされたデータを確認できます。
戻り値-これは、クエリ操作からのデータの行を持つシーケンスを返します。
次の例は、従業員表に接続し、表の行のfirst_name列をフェッチする方法を示しています。
例
(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)))
上記のコードから、次のことがわかります。
- 「従業員からfirst_nameを選択」のクエリがクエリ文字列として渡されます。
- :first_nameは、フェッチ操作の結果として返されるシーケンスです。
データベースにJohnのfirst_name値を含む行が1つしかないと仮定すると、上記のプログラムの出力は次のようになります。
(John)
データの挿入
データベーステーブルにレコードを作成する場合に必要です。 以下は、Clojureを使用してデータを挿入できる構文です。 これは、*「挿入!」*関数を使用して行われます。
構文
clojure.java.jdbc/insert!
:table_name {:column_namen columnvalue}
パラメータ-「:table_name」は、挿入が必要なテーブルの名前です。 「\ {:column_namen columnvalue}」は、すべての列名と値のマップであり、テーブルに行として追加する必要があります。
戻り値-挿入が正常に行われると、nilが返されます。
次の例は、testdbデータベースの従業員テーブルにレコードを挿入する方法を示しています。
例
(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}))
MySQLデータベースと従業員テーブルを確認すると、上記の行がテーブルに正常に挿入されていることがわかります。
データを削除する
- 「delete!」*関数を使用して、テーブルから行を削除できます。 以下は、この操作を実行する方法の構文です。
構文
clojure.java.jdbc/delete!
:table_name [condition]
パラメータ-「:table_name」は、挿入が必要なテーブルの名前です。 「条件」は、テーブルから削除する必要がある行を決定するために使用される条件です。
戻り値-これは削除された行の数を返します。
次の例は、testdbデータベースのemployeeテーブルからレコードを削除する方法を示しています。 この例では、年齢が30に等しいという条件に基づいて、テーブルから行を削除します。
例
(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])))
年齢が値30に等しい行を持つレコードがある場合、その行は削除されます。
データの更新
*'update!'* 関数を使用して、テーブルから行を更新できます。 以下は、この操作を実行する方法の構文です。
構文
clojure.java.jdbc/update!
:table_name
{setcondition}
[condition]
パラメータ-「:table_name」は、挿入が必要なテーブルの名前です。 「setcondition」は、マップの項で述べたように更新する必要がある列です。 「条件」は、テーブルから削除する必要がある行を決定するために使用される条件です。
戻り値-これは更新された行の数を返します。
次の例は、testdbデータベースのemployeeテーブルからレコードを削除する方法を示しています。 この例では、年齢が30に等しいという条件に基づいてテーブルの行を更新し、収入の値を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])))
年齢が値30に等しい行を持つレコードがある場合、その行は更新され、収入の値は40に設定されます。
トランザクション
トランザクションは、データの一貫性を保証するメカニズムです。 トランザクションには、次の4つのプロパティがあります-
- Atomicity -トランザクションが完了するか、まったく何も起こりません。
- 一貫性-トランザクションは一貫した状態で開始し、システムを一貫した状態のままにする必要があります。
- 分離-トランザクションの中間結果は、現在のトランザクションの外部では見えません。
- 耐久性-トランザクションがコミットされると、システム障害が発生した後でも効果は持続します。
例
次の例は、Clojureでトランザクションを実装する方法を示しています。 トランザクションで実行する必要のある操作は、 'with-dbtransaction' 句に埋め込む必要があります。
(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])))
Clojure-Javaインターフェイス
すでに知っているように、Clojureコードは最後にJava仮想環境で実行されます。 したがって、ClojureがJavaのすべての機能を利用できるのは理にかなっています。 この章では、ClojureとJavaの相関関係について説明します。
Javaメソッドの呼び出し
Javaメソッドは、ドット表記を使用して呼び出すことができます。 例は文字列です。 とにかくClojureの文字列はすべてJava文字列なので、文字列に対して通常のJavaメソッドを呼び出すことができます。
これがどのように行われるかの例を、次のプログラムに示します。
例
(ns Project
(:gen-class))
(defn Example []
(println (.toUpperCase "Hello World")))
(Example)
上記のプログラムは、次の出力を生成します。 コードから、文字列メソッドのドット表記を呼び出すだけで、Clojureでも機能することがわかります。
出力
HELLO WORLD
パラメータを使用したJavaメソッドの呼び出し
パラメーターを使用してJavaメソッドを呼び出すこともできます。 これがどのように行われるかの例を、次のプログラムに示します。
例
(ns Project
(:gen-class))
(defn Example []
(println (.indexOf "Hello World","e")))
(Example)
上記のプログラムは、次の出力を生成します。 上記のコードから、パラメーター「e」をindexOfメソッドに渡していることがわかります。 上記のプログラムは、次の出力を生成します。
出力
1
Javaオブジェクトの作成
Javaで行われるのと同様の「新しい」キーワードを使用して、Clojureでオブジェクトを作成できます。
これがどのように行われるかの例を、次のプログラムに示します。
例
(ns Project
(:gen-class))
(defn Example []
(def str1 (new String "Hello"))
(println str1))
(Example)
上記のプログラムは、次の出力を生成します。 上記のコードからわかるように、「new」キーワードを使用して、Javaの既存のStringクラスから新しいオブジェクトを作成できます。 Javaで行うように、オブジェクトの作成中に値を渡すことができます。 上記のプログラムは、次の出力を生成します。
出力
Hello
以下は、Integerクラスのオブジェクトを作成し、通常のClojureコマンドでそれらを使用する方法を示す別の例です。
例
(ns Project
(:gen-class))
(defn Example []
(def my-int(new Integer 1))
(println (+ 2 my-int)))
(Example)
上記のプログラムは、次の出力を生成します。
出力
3
インポートコマンド
importコマンドを使用して、名前空間にJavaライブラリーを含めて、クラスとメソッドに簡単にアクセスできるようにすることもできます。
次の例は、importコマンドの使用方法を示しています。 この例では、importコマンドを使用して java.util.stack ライブラリからクラスをインポートしています。 その後、スタッククラスのpushおよびpopメソッドをそのまま使用できます。
例
(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)
上記のプログラムは、次の出力を生成します。
出力
First Element
Javaコマンドを使用したコードの実行
Clojureコードは、Javaコマンドを使用して実行できます。 以下は、これを行う方法の構文です。
java -jar clojure-1.2.0.jar -i main.clj
すべてのClojureベースのクラスがJVMにロードされるように、Clojure jarファイルに言及する必要があります。 「main.clj」ファイルは、実行する必要があるClojureコードファイルです。
Java組み込み関数
Clojureは、Javaの多くの組み込み関数を使用できます。 それらのいくつかは-
- Math PI関数*-Clojureは、PIの値に対してMathメソッドを使用できます。 以下はコード例です。
例
(ns Project
(:gen-class))
(defn Example []
(println (. Math PI)))
(Example)
上記のコードは次の出力を生成します。
出力
3.141592653589793
システムプロパティ-Clojureはシステムプロパティを照会することもできます。 以下はコード例です。
例
(ns Project
(:gen-class))
(defn Example []
(println (.. System getProperties (get "java.version"))))
(Example)
システム上のJavaのバージョンに応じて、対応する値が表示されます。 次に出力例を示します。
出力
1.8.0_45
Clojure-並行プログラミング
Clojureプログラミングでは、ほとんどのデータ型は不変であるため、並行プログラミングに関しては、コードが複数のプロセッサで実行される場合、これらのデータ型を使用するコードは非常に安全です。 しかし、多くの場合、データを共有する必要があり、複数のプロセッサ間で共有されるデータに関しては、複数のプロセッサを使用する場合、整合性に関してデータの状態を維持する必要があります。 これは*並行プログラミング*として知られており、Clojureはそのようなプログラミングのサポートを提供します。
dosync、ref、set、alterなどを通じて公開されるソフトウェアトランザクショナルメモリシステム(STM) 同期的かつ調整された方法でスレッド間で状態の変化を共有することをサポートします。 エージェントシステムは、非同期で独立した方法でスレッド間で状態の変化を共有することをサポートします。 アトムシステムは、同期的かつ独立した方法でスレッド間で状態の変化を共有することをサポートしています。 一方、def、バインディングなどを通じて公開される動的なvarシステム スレッド内の変化する状態の分離をサポートします。
他のプログラミング言語も、並行プログラミングのモデルに従います。
- 変更可能なデータへの直接参照があります。
- 共有アクセスが必要な場合、オブジェクトはロックされ、値が変更され、その値への次のアクセスのためにプロセスが続行されます。
Clojureにはロックはありませんが、不変の永続データ構造への間接参照です。
Clojureには3種類の参照があります。
- Vars -変更はスレッドで分離されます。
- 参照-変更はスレッド間で同期および調整されます。
- エージェント-スレッド間の非同期の独立した変更を含みます。
同時プログラミングに関して、Clojureでは次の操作が可能です。
トランザクション
Clojureの同時実行性はトランザクションに基づいています。 参照はトランザクション内でのみ変更できます。 トランザクションには次のルールが適用されます。
- すべての変更はアトミックで分離されています。
- 参照へのすべての変更はトランザクションで発生します。
- トランザクションは、別のトランザクションによる効果を認識しません。
- すべてのトランザクションはdosyncブロック内に配置されます。
dosyncブロックの機能についてはすでに説明しました。もう一度見てみましょう。
dosync
式とネストされた呼び出しを含むトランザクションで式を(暗黙のdoで)実行します。 このスレッドで既に何も実行されていない場合、トランザクションを開始します。 キャッチされない例外は、トランザクションを中止し、dosyncから流出します。
構文は次のとおりです。
構文
(dosync expression)
パラメータ-「式」は、dosyncブロックに含まれる式のセットです。
戻り値-なし。
参照変数の値を変更しようとする例を見てみましょう。
例
(ns clojure.examples.example
(:gen-class))
(defn Example []
(def names (ref []))
(alter names conj "Mark"))
(Example)
出力
上記のプログラムを実行すると、次のエラーが発生します。
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
エラーから、最初にトランザクションを開始しないと参照タイプの値を変更できないことが明確にわかります。
上記のコードを機能させるには、次のプログラムで行うように、dosyncブロックにalterコマンドを配置する必要があります。
例
(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)
上記のプログラムは、次の出力を生成します。
出力
[John Mark]
dosyncの別の例を見てみましょう。
例
(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)
上記の例では、dosyncブロックで変更される2つの値があります。 トランザクションが成功すると、両方の値が変更されます。そうでない場合、トランザクション全体が失敗します。
上記のプログラムは、次の出力を生成します。
出力
10 20
-10 40
Clojure-アプリケーション
Clojureには、デスクトップ*および Webベースのアプリケーション*の作成を可能にするいくつかの寄贈ライブラリがあります。 それらのそれぞれについて説明しましょう。
Sr.No. | Applications & Description |
---|---|
1 |
See-sawは、デスクトップアプリケーションの作成に使用できるライブラリです。 |
2 |
Desktop – Changing the Value of Text ウィンドウ内のコンテンツの値は、 ‘config!’ オプションを使用して変更できます。 次の例では、config! オプションを使用して、ウィンドウの内容を「Good Bye」の新しい値に変更します。 |
3 |
Desktop – Displaying a Modal Dialog Box シーソークラスのアラートメソッドを使用して、モーダルダイアログボックスを表示できます。 メソッドは、モーダルダイアログボックスに表示する必要があるテキスト値を受け取ります。 |
4 |
ボタンは、ボタンクラスの助けを借りて表示できます。 |
5 |
ラベルは、ラベルクラスを使用して表示できます。 |
6 |
Desktop – Displaying Text Fields テキストフィールドは、テキストクラスを使用して表示できます。 |
Webアプリケーション-はじめに
ClojureでWebアプリケーションを作成するには、次のリンクhttps://github.com/ring-clojure/ringから入手できるRingアプリケーションライブラリを使用する必要があります
サイトから必要なjarをダウンロードし、Clojureアプリケーションの依存関係として追加する必要があります。
- リングフレームワーク*は次の機能を提供します-
- http要求が通常のClojure HashMapとしてWebアプリケーションに届くように設定し、同様に応答をHashMapとして返すことができるようにします。
- それらの要求および応答マップがどのように見えるかを正確に記述する仕様を提供します。
- Webサーバー(Jetty)を持ち込み、Webアプリケーションをそれに接続します。
Ringフレームワークは自動的にWebサーバーを起動し、Clojureアプリケーションがこのサーバーで動作することを確認できます。 その後、Compojureフレームワークも使用できます。 これにより、ルートを作成できるようになりました。これが、現在の最新のWebアプリケーションの開発方法です。
最初のClojureアプリケーションの作成-次の例は、Clojureで最初のWebアプリケーションを作成する方法を示しています。
(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))
プログラムの次の側面を見てみましょう-
- *「defroutes」*はルートを作成するために使用され、異なるルートへのWebアプリケーションへのリクエストがClojureアプリケーションの異なる機能に向けられるようにします。
- 上記の例では、「/」がデフォルトルートとして知られているため、Webアプリケーションのベースを参照すると、文字列「Hello World」がWebブラウザーに送信されます。
- ユーザーがClojureアプリケーションで処理できないURLをヒットすると、文字列「Not Found」が表示されます。
Clojureアプリケーションを実行すると、デフォルトでアプリケーションはlocalhost:3000としてロードされるため、この場所を参照すると、次の出力が表示されます。
Webアプリケーション– Webアプリケーションへのルートの追加
Webアプリケーションにさらにルートを追加することもできます。 次の例は、これを実現する方法を示しています。
(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))
アプリケーションにルートを追加することは、URLルートを使用して別のGET関数を追加するのと同じくらい簡単であることがわかります。 (GET "/Tutorial" [] "これはClojureのチュートリアルです")
場所 http://localhost:3000/Tutorial を参照すると、次の出力が表示されます。
Clojure-自動テスト
この章では、Clojureが提供する自動テストオプションについて説明します。
クライアントアプリケーションのテスト
Clojureフレームワークのテストを使用するには、https://github.com/slagyr/speclj#manual-installationにある依存関係を使用する必要があります
このURLは、 speclj フレームワークを提供します。これは、Clojureのテストデータ駆動型または動作駆動型テストフレームワークとして使用されます。 「speclj」ライブラリを使用する場合は、Clojure 1.7.0フレームワークを使用する必要があります。 デフォルトでは、テストファイルはClojureコードファイルとは異なるため、「spec」ディレクトリに配置する必要があります。
以下は、テストファイルのサンプルコードです。
(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)
上記のコードについては、次のことに注意する必要があります-
- まず、「require」ステートメントを使用して、すべてのコアライブラリを「speclj」フレームワークに含めるようにする必要があります。
- 次は「説明」機能です。 これは、作成されるテストケースの説明を提供するために使用されます。
- 次の機能は「it」機能です。これは実際のテストケースです。 最初のテストケースでは、「is true」文字列はテストケースに付けられた名前です。
- shouldとshould-notは*アサーション*と呼ばれます。 すべてのアサーションはshouldで始まります。 shouldとshould-notは、利用可能な多くのアサーションのうちの2つだけです。 彼らは両方とも、それぞれ真実性と虚偽性をチェックする表現を取ります。
テストケースを実行すると、次の出力が得られます。 出力には、テストケースの実行にかかった時間がミリ秒単位で表示されます。
←[32m.←[0m←[32m.←[0m
Finished in 0.00014 seconds
Webベースのアプリケーションのテスト
*Selenium* は、現代のWebベースのアプリケーションのテストに使用される主要なフレームワークの1つです。 Webベースのアプリケーションのテストに使用できるClojureライブラリも利用できます。
ClojureのWebベースのアプリケーションをテストするためにSeleniumライブラリーを使用する方法を見てみましょう。
- ステップ1 *-最初のステップは、Ring and Compojureフレームワークを使用して、テストが必要なWebベースのアプリケーションを作成していることを確認することです。 前の章の例の1つを使用してみましょう。 次のコードは、ブラウザに「Hello World」を表示する単純なWebアプリケーションです。
(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))
- ステップ2 *-次に、セレンjarファイルhttps://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-server/2.47.0をダウンロードして、クラスパスに含めるようにしてください。
- ステップ3 *-また、次の場所からWebテストを実行するために使用される「clj」Webドライバーをダウンロードします。
https://clojars.org/clj-webdriver/versions/0.7.1
- ステップ4 *-プロジェクトディレクトリで、featuresという別のディレクトリを作成し、「config.clj」というファイルを作成します。
- ステップ5 *-次に、前のステップで作成した「config.clj」ファイルに次のコードを追加します。
ns clj-webdriver-tutorial.features.config)
(def test-port 3000)
(def test-host "localhost")
(def test-base-url (str "http://" test-host ":" test-port "/"))
上記のコードは基本的に、Webテストフレームワークにアプリケーションをテストするように指示します。アプリケーションはURL http://localhost:3000 でロードされます。
- ステップ6 *-最後に、テストを実行するコードを作成しましょう。
(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)))
上記のコードは次のアクションを実行します-
- アプリケーションのサーバーを起動します。
- ブラウザでルートパスを開きます。
- 「Hello World」メッセージがページに表示されているかどうかを確認してください。
- ブラウザを閉じます。
- サーバーをシャットダウンします。
Clojure-ライブラリ
Clojureライブラリを非常に強力にしていることの1つは、Clojureフレームワークで使用できるライブラリの数です。 Webテスト、Web開発、スイングベースのアプリケーションの開発、MySQLデータベースに接続するためのjdbcライブラリの以前の例で使用されている非常に多くのライブラリを見てきました。 以下は、さらにいくつかのライブラリのいくつかの例です。
data.xml
このライブラリにより、ClojureはXMLデータを操作できます。 使用するライブラリバージョンはorg.clojure/data.xml "0.0.8"です。 data.xmlは、XMLの解析と出力をサポートしています。 解析関数は、ReaderまたはInputStreamからXMLを読み取ります。
例
以下は、文字列から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
このライブラリにより、ClojureはJSONデータを処理できます。 使用するライブラリバージョンはorg.clojure/data.json "0.2.6"です。
例
以下は、このライブラリの使用例です。
(ns clojure.examples.example
(:require [clojure.data.json :as json])
(:gen-class))
(defn Example []
(println (json/write-str {:a 1 :b 2})))
(Example)
出力
上記のプログラムは、次の出力を生成します。
{\"a\":1,\"b\":2}
data.csv
このライブラリにより、Clojureは 'csv' データを操作できます。 使用するライブラリバージョンはorg.clojure/data.csv "0.1.3"です。
例
以下は、このライブラリの使用例です。
(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)
上記のコードでは、「csv」関数は最初に in-file.csv というファイルを読み取り、すべてのデータを変数in-fileに入れます。 次に、write-csv関数を使用して、* out-file.csv。*というファイルにすべてのデータを書き込みます。