(1 "two" 3.0)
( … )
- リスト[ … ]
- ベクトル{ … }
- マップ#
- ディスパッチ文字#{ … }
- セット#_
- 破棄#"…"
- 正規表現#(…)
- 匿名関数#'
- Varクォート##
- シンボリック値#inst
、#uuid
、#js
など - タグ付きリテラル%
、%n
、%&
- 匿名関数引数@
- Deref^
(および#^
) - メタデータ'
- クォート;
- コメント:
- キーワード::
- 自動解決キーワード#:
および#::
- 名前空間マップ構文/
- 名前空間区切り文字\
- 文字リテラル$
- 内部クラス参照->
、->>
、some->
、cond->
、as->
など - スレッドマクロ`
- シンタックスクォート~
- アンコート~@
- アンコートスプライシング<symbol>#
- Gensym#?
- リーダー条件式#?@
- スプライシングリーダー条件式*var-name*
- "イヤーマフ">!!
、<!!
、>!
、<!
- core.asyncチャネルマクロ<symbol>?
-述語サフィックス<symbol>!
- 安全でない操作_
- 使用されていない引数,
- 空白文字このページでは、「Google検索」が難しいClojureの構文について説明します。セクションは特定の順序ではありませんが、関連する項目は理解しやすくするためにグループ化されています。Clojureリーダーに関する権威あるリファレンスとして、リーダーリファレンスページを参照してください。このガイドは、James Hughesの元のブログ投稿に基づいており、著者の許可を得て更新および拡張されています。
[ … ]
- ベクトルベクトルは、順序付けられた、インデックス付きの、異種コレクションです。インデックスは0ベースです。
3つの値のベクトルのインデックス1の値を取得する例
user=> (get ["a" 13.7 :foo] 1)
13.7
#{ … }
- セット詳細は#
を参照してください。
#{…}
は、セット(一意の値のコレクション)、具体的にはhash-set
を定義します。以下は同等です。
user=> #{1 2 3 4}
#{1 2 3 4}
user=> (hash-set 1 2 3 4)
#{1 2 3 4}
セットには重複を含めることができないため、set
リーダーは、無効なリテラルであるため、この場合例外をスローします。アイテムがセットに追加されると、値が既に存在する場合は単に削除されます。
user=> #{1 2 3 4 1}
Syntax error reading source at (REPL:83:13).
Duplicate key: 1
#_
- 破棄詳細は#
を参照してください。
#_
は、リーダーに次のフォームを完全に無視するように指示します。
user=> [1 2 3 #_ 4 5]
[1 2 3 5]
#_
の後のスペースは省略可能です。
user=> [1 2 3 #_4 5]
[1 2 3 5]
も機能します。また、破棄文字はednでも機能します。
便利なテクニックとして、複数の#_
を積み重ねて複数のフォームを省略することができます。
user=> {:a 1, #_#_ :b 2, :c 3}
{:a 1, :c 3}
ドキュメントでは、「#_
の後のフォームはリーダーによって完全にスキップされます(これは、nil
を生成するcomment
マクロよりも完全な削除です)。」と示唆されています。これは、デバッグ状況や複数行コメントに役立ちます。
#"…"
- 正規表現詳細は#
を参照してください。
#"
は正規表現の開始を示します。
user=> (re-matches #"^test$" "test")
"test"
このフォームは、*読み込み時*にホスト固有の正規表現機構にコンパイルされますが、ednでは使用できません。Clojureで正規表現を使用する場合、Java文字列のエスケープは必要ありません。
#(…)
- 匿名関数詳細は#
を参照してください。
#(
は、インライン関数定義の簡略構文の開始です。次の2つのコードスニペットは似ています。
; anonymous function taking a single argument and printing it
(fn [line] (println line))
; anonymous function taking a single argument and printing it - shorthand
#(println %)
リーダーは、匿名関数を関数定義に展開します。そのアリティ(取る引数の数)は、%
プレースホルダーの宣言方法によって定義されます。アリティに関する説明については、%
文字を参照してください。
user=> (macroexpand `#(println %))
(fn* [arg] (clojure.core/println arg)) ; argument names shortened for clarity
#'
- Varクォート#'
は、var
関数の呼び出しに展開されるVarクォートです。
user=> (read-string "#'foo")
(var foo)
user=> (def nine 9)
#'user/nine
user=> nine
9
user=> (var nine)
#'user/nine
user=> #'nine
#'user/nine
使用されると、参照されたVarを返すことを試みます。これは、それが表す値ではなく、参照/宣言について話したい場合に役立ちます。メタデータ(^
)の議論におけるmeta
の使用を参照してください。
Varクォートはednでは使用できません。
##
- シンボリック値Clojureは、シンボリック値##Inf
、##-Inf
、##NaN
を読み書きできます。これらはednでも使用できます。
user=> (/ 1.0 0.0)
##Inf
user=> (/ -1.0 0.0)
##-Inf
user=> (Math/sqrt -1.0)
##NaN
#inst
、#uuid
、#js
など - タグ付きリテラルタグ付きリテラルはednで定義され、ClojureおよびClojureScriptリーダーによってネイティブにサポートされています。#inst
および#uuid
タグはednによって定義されますが、#js
タグはClojureScriptによって定義されます。
Clojureのread-string
を使用してタグ付きリテラルを読み取ることができます(または直接使用することもできます)。
user=> (type #inst "2014-05-19T19:12:37.925-00:00")
java.util.Date ;; this is host dependent
user=> (read-string "#inst \"2014-05-19T19:12:37.925-00:00\"")
#inst "2014-05-19T19:12:37.925-00:00"
タグ付きリテラルは、リーダーにリテラル値をどのように解析するかを指示します。他の一般的な用途には、UUIDを表す#uuid
が含まれ、ClojureScriptの世界では、タグ付きリテラルの非常に一般的な用途は#js
であり、これを使用してClojureScriptデータ構造をJavaScript構造に直接変換できます。#js
は再帰的に変換されないため、ネストされたデータ構造がある場合は、clj->js
を使用してください。
#inst
と#uuid
はednで使用できますが、#js
は使用できません。
%
、%n
、%&
- 匿名関数引数%
は、#(* % %)
のような匿名関数#(...)
の引数です。
匿名関数が展開されると、fn
フォームになり、%
引数はgensymされた名前に置き換えられます(ここでは、可読性のためにarg1などを使用します)。
user=> (macroexpand `#(println %))
(fn* [arg1] (clojure.core/println arg1))
引数の位置(1ベース)を示すために、数字を%
の直後に配置できます。匿名関数のアリティは、最も高い番号の%
引数に基づいて決定されます。
user=> (#(println %1 %2) "Hello " "Clojure")
Hello Clojure ; takes 2 args
user=> (macroexpand `#(println %1 %2))
(fn* [arg1 arg2] (clojure.core/println arg1 arg2)) ; takes 2 args
user=> (#(println %4) "Hello " "Clojure " ", Thank " "You!!")
You!! ; takes 4 args, doesn't use first 3 args
user=> (macroexpand `#(println %4))
(fn* [arg1 arg2 arg3 arg4] (clojure.core/println arg4)) ; takes 4 args doesn't use 3
引数を使用する必要はありませんが、外部の呼び出し元が渡すことを期待する順序で宣言する必要があります。
%
と%1
は互換性があります。
user=> (macroexpand `#(println % %1)) ; use both % and %1
(fn* [arg1] (clojure.core/println arg1 arg1)) ; still only takes 1 argument
可変長匿名関数で「残りの」引数(最も高い名前付き匿名引数の後)を表すために使用される%&
もあります。
user=> (#(println %&) "Hello " "Clojure " ", Thank " "You!!")
(Hello Clojure , Thank You!! ) ; takes n args
user=> (macroexpand '#(println %&))
(fn* [& rest__11#] (println rest__11#))
匿名関数と%
はednの一部ではありません。
@
- Deref@
はderef
関数の呼び出しに展開されるため、この2つのフォームは同じです。
user=> (def x (atom 1))
#'user/x
user=> @x
1
user=> (deref x)
1
user=>
@
は、参照の現在の値を取得するために使用されます。上記の例では、@
を使用してatomの現在の値を取得していますが、計算を強制し、場合によってはブロックするために、@
をfuture
、delay
、promises
などにも適用できます。
@
はednでは使用できません。
^
(および#^
) - メタデータ^
はメタデータマーカーです。メタデータは、Clojureのさまざまなフォームに添付できる値のマップ(省略記法付き)です。これはこれらのフォームに追加情報を提供し、ドキュメント、コンパイル時の警告、タイプヒント、その他の機能に使用できます。
user=> (def ^{:debug true} five 5) ; meta map with single boolean value
#'user/five
meta
関数を使用してメタデータにアクセスできます。これは、返された値ではなく、宣言自体に対して実行する必要があります。
user=> (def ^{:debug true} five 5)
#'user/five
user=> (meta #'five)
{:ns #<Namespace user>, :name five, :column 1, :debug true, :line 1, :file "NO_SOURCE_PATH"}
ここでは単一の値を使用しているため、メタデータ^:name
を宣言するための省略記法を使用できます。これは、値がtrueに設定されるフラグに役立ちます。
user=> (def ^:debug five 5)
#'user/five
user=> (meta #'five)
{:ns #<Namespace user>, :name five, :column 1, :debug true, :line 1, :file "NO_SOURCE_PATH"}
^
のもう1つの用途は、タイプヒントです。これらは、コンパイラに値の型を伝え、型固有の最適化を実行できるようにするため、結果のコードを高速化できます。
user=> (def ^Integer five 5)
#'user/five
user=> (meta #'five)
{:ns #<Namespace user>, :name five, :column 1, :line 1, :file "NO_SOURCE_PATH", :tag java.lang.Integer}
その例では、:tag
プロパティが設定されていることがわかります。
省略記法を積み重ねることもできます。
user=> (def ^Integer ^:debug ^:private five 5)
#'user/five
user=> (meta #'five)
{:ns #<Namespace user>, :name five, :column 1, :private true, :debug true, :line 1, :file "NO_SOURCE_PATH", :tag java.lang.Integer}
元々は、メタデータは#^
で宣言されていましたが、現在は非推奨になっています(ただし、まだ機能します)。その後、これは単なる^
に簡素化され、ほとんどのClojureでそれが使用されますが、古いコードでは時折#^
構文に出くわすことがあります。
メタデータはednで使用できますが、タイプヒントは使用できません。
'
- クォートクォートは、次のフォームを読み込むが評価しないことを示すために使用されます。リーダーは'
をquote
特殊フォームへの呼び出しに展開します。
user=> (1 3 4) ; fails as it tries to invoke 1 as a function
Execution error (ClassCastException) at myproject.person-names/eval230 (REPL:1).
class java.lang.Long cannot be cast to class clojure.lang.IFn
user=> '(1 3 4) ; quote
(1 3 4)
user=> (quote (1 2 3)) ; using the longer quote method
(1 2 3)
user=>
;
- コメント;
は行コメントを開始し、その開始点から行末までのすべての入力を無視します。
user=> (def x "x") ; this is a comment
#'user/x
user=> ; this is a comment too
<returns nothing>
Clojureでは、可読性や強調のために複数のセミコロンを使用することが一般的ですが、Clojureにとってはすべて同じです。
;; This is probably more important than
; this
:
- キーワード:
はキーワードを示す指標です。キーワードはマップのキーとして頻繁に使用され、文字列よりも高速な比較と低いメモリオーバーヘッドを提供します(インスタンスがキャッシュされ、再利用されるため)。
user=> (type :test)
clojure.lang.Keyword
あるいは、keyword
関数を使用して、文字列からキーワードを作成することもできます。
user=> (keyword "test")
:test
キーワードは、マップ内のキーとして自分自身を検索する関数として呼び出すこともできます。
user=> (def my-map {:one 1 :two 2})
#'user/my-map
user=> (:one my-map) ; get the value for :one by invoking it as function
1
user=> (:three my-map) ; it can safely check for missing keys
nil
user=> (:three my-map 3) ; it can return a default if specified
3
user => (get my-map :three 3) ; same as above, but using get
3
::
- 自動解決キーワード::
は、現在の名前空間でキーワードを自動解決するために使用されます。修飾子が指定されていない場合、現在の名前空間に自動解決されます。修飾子が指定されている場合、現在の名前空間のエイリアスを使用することがあります。
user=> :my-keyword
:my-keyword
user=> ::my-keyword
:user/my-keyword
user=> (= ::my-keyword :my-keyword)
false
これはマクロを作成する場合に役立ちます。マクロ名前空間内の別の関数を呼び出すマクロが、関数を正しく呼び出すように展開されるようにしたい場合、::my-function
を使用して完全修飾名を参照できます。
::
はednでは使用できないことに注意してください。
#:
と#::
- 名前空間マップ構文名前空間マップ構文はClojure 1.9で追加され、マップ内のキーやシンボルが共通の名前空間を共有する場合のデフォルトの名前空間コンテキストを指定するために使用されます。
#:ns
構文は、完全修飾された名前空間マッププレフィックスnを、名前空間マッププレフィックスでエイリアスを指定します。ここで、nsは名前空間の名前であり、プレフィックスはマップの開始中括弧{
の前に置かれます。
たとえば、次の名前空間構文を持つマップリテラル
#:person{:first "Han"
:last "Solo"
:ship #:ship{:name "Millennium Falcon"
:model "YT-1300f light freighter"}}
は、次のように読み取られます。
{:person/first "Han"
:person/last "Solo"
:person/ship {:ship/name "Millennium Falcon"
:ship/model "YT-1300f light freighter"}}
これらのマップは同一のオブジェクトを表していることに注意してください。これらは単なる代替構文です。
#::
は、現在の名前空間を使用して、マップ内のキーワードまたはシンボルのキーの名前空間を自動解決するために使用できます。
これらの2つの例は同等です。
user=> (keys {:user/a 1, :user/b 2})
(:user/a :user/b)
user=> (keys #::{:a 1, :b 2})
(:user/a :user/b)
自動解決キーワードと同様に、#::alias
を使用して、ns
フォームで定義された名前空間エイリアスで自動解決することもできます。
(ns rebel.core
(:require
[rebel.person :as p]
[rebel.ship :as s] ))
#::p{:first "Han"
:last "Solo"
:ship #::s{:name "Millennium Falcon"
:model "YT-1300f light freighter"}}
は、次と同じように読み取られます。
{:rebel.person/first "Han"
:rebel.person/last "Solo"
:rebel.person/ship {:rebel.ship/name "Millennium Falcon"
:rebel.ship/model "YT-1300f light freighter"}}
/
- 名前空間セパレータ/
は除算関数clojure.core//
になることもありますが、シンボルの名前と名前空間修飾子を分離するシンボル名でのセパレータとしても機能します(例:my-namespace/utils
)。したがって、名前空間修飾子は、単純な名前の命名衝突を防ぐことができます。
\
- 文字リテラル\
は、次のように文字リテラルを示します。
user=> (str \h \i)
"hi"
特殊なASCII文字を指定するための特殊文字も少量あります。\newline
、\space
、\tab
、\formfeed
、\backspace
、\return
です。
\
の後に、\uNNNN
形式のUnicodeリテラルを付けることもできます。たとえば、\u03A9
はΩのリテラルです。
$
- 内部クラス参照Javaの内部クラスとインターフェースを参照するために使用されます。コンテナクラス名と内部クラス名を区切ります。
(import (basex.core BaseXClient$EventNotifier)
(defn- build-notifier [notifier-action]
(reify BaseXClient$EventNotifier
(notify [this value]
(notifier-action value))))
EventNotifier
は、インポートされたJavaクラスであるBaseXClient
クラスの内部インターフェースです。
->
、->>
、some->
、cond->
、as->
など - スレッディングマクロこれらはスレッディングマクロです。Clojure公式ドキュメントを参照してください。
`
- シンタックスクォート`
はシンタックスクォートです。シンタックスクォートはクォート(評価を遅延させる)に似ていますが、いくつかの追加効果があります。
基本的なシンタックスクォートは、通常のクォートと似ているように見えます。
user=> (1 2 3)
Execution error (ClassCastException) at myproject.person-names/eval232 (REPL:1).
class java.lang.Long cannot be cast to class clojure.lang.IFn
user=> `(1 2 3)
(1 2 3)
ただし、シンタックスクォート内で使用されるシンボルは、現在の名前空間に関して完全に解決されます。
user=> (def five 5)
#'user/five
user=> `five
user/five
シンタックスクォートは、マクロ内の「テンプレート」メカニズムとして最もよく使用されます。今すぐ1つ書くことができます。
user=> (defmacro debug [body]
#_=> `(let [val# ~body]
#_=> (println "DEBUG: " val#)
#_=> val#))
#'user/debug
user=> (debug (+ 2 2))
DEBUG: 4
4
マクロは、コードをデータとして受け取るコンパイラによって呼び出される関数です。コード(データとして)を返し、さらにコンパイルして評価できることが期待されています。このマクロは単一の本体式を受け取り、本体を評価し、その値を出力し、その値を返すlet
フォームを返します。ここでは、シンタックスクォートはリストを作成しますが、評価しません。そのリストは実際にはコードです。
~
- アンォート`
を参照して、追加情報を確認してください。
~
はアンクォートです。シンタックスクォートはクォートと同様に、シンタックスクォートされたフォーム内では評価が行われません。アンクォートはクォートをオフにし、シンタックスクォートされた式内の式を評価します。
user=> (def five 5) ; create a named var with the value 5
#'user/five
user=> five ; the symbol five is evaluated to its value
5
user=> `five ; syntax quoting five will avoid evaluating the symbol, and fully resolve it
user/five
user=> `~five ; within a syntax quoted block, ~ will turn evaluation back on just for the next form
5
user=> `[inc ~(+ 1 five)]
[clojure.core/inc 6]
シンタックスクォートとアンクォートは、コードを受け取ってコードを返すコンパイル時に呼び出される関数であるマクロを作成するための不可欠なツールです。
~@
- アンォートスプライシング~@
はアンクォートスプライシングです。アンクォート(~
)はフォームを評価して結果をクォートされた結果に配置しますが、~@
は評価された値がコレクションであることを期待し、そのコレクションの内容をクォートされた結果にスプライスします。
user=> (def three-and-four (list 3 4))
#'user/three-and-four
user=> `(1 ~three-and-four) ; evaluates `three-and-four` and places it in the result
(1 (3 4))
user=> `(1 ~@three-and-four) ; evaluates `three-and-four` and places its contents in the result
(1 3 4)
これもまた、マクロを作成するための強力なツールです。
<symbol>#
- ゲンシンシンボルの末尾にある#
は、新しいシンボルを自動的に生成するために使用されます。これは、マクロ内で、マクロ固有のものがユーザー空間へ漏れるのを防ぐために役立ちます。通常のlet
はマクロ定義では失敗します。
user=> (defmacro m [] `(let [x 1] x))
#'user/m
user=> (m)
Syntax error macroexpanding clojure.core/let at (REPL:1:1).
myproject.person-names/x - failed: simple-symbol? at: [:bindings :form :local-symbol]
spec: :clojure.core.specs.alpha/local-name
myproject.person-names/x - failed: vector? at: [:bindings :form :seq-destructure]
spec: :clojure.core.specs.alpha/seq-binding-form
myproject.person-names/x - failed: map? at: [:bindings :form :map-destructure]
spec: :clojure.core.specs.alpha/map-bindings
myproject.person-names/x - failed: map? at: [:bindings :form :map-destructure]
spec: :clojure.core.specs.alpha/map-special-binding
これは、シンタックスクォート内のシンボルは、ここのローカルバインディングx
を含む、完全に解決されるためです。
代わりに、変数名の末尾に#
を追加し、Clojureが一意の(非修飾)シンボルを生成させます。
user=> (defmacro m [] `(let [x# 1] x#))
#'user/m
user=> (m)
1
user=>
重要なのは、特定のx#
が単一のシンタックスクォート内で使用されるたびに、同じ生成名が使用されることです。
このマクロを展開すると、gensym
で生成された名前を確認できます。
user=> (macroexpand '(m))
(let* [x__681__auto__ 1] x__681__auto__)
#?
- リーダー条件リーダー条件は、異なるClojureの方言が共通のコードを共有できるように設計されています。リーダー条件は、従来のcond
と同様に動作します。使用構文は#?
であり、次のようになります。
#?(:clj (Clojure expression)
:cljs (ClojureScript expression)
:cljr (Clojure CLR expression)
:default (fallthrough expression))
#?@
- スプライシングリーダー条件スプライシングリーダー条件の構文は#?@
です。これはリストを包含するフォームにスプライスするために使用されます。そのため、Clojureリーダーはこれを次のように読み取ります。
(defn build-list []
(list #?@(:clj [5 6 7 8]
:cljs [1 2 3 4])))
これはこれと同じです。
(defn build-list []
(list 5 6 7 8))
*var-name*
- 「イヤーマフ」イヤーマフ(アスタリスクのペアでvar名を囲む)は、多くのLISPで使用される命名規則であり、特殊varを示します。Clojureでは、最も一般的に動的var、つまり動的スコープによって変化する可能性のあるvarを示すために使用されます。イヤーマフは、「ここにドラゴンがいる」という警告として機能し、varの状態を絶対に想定しないようにします。これは規則ではなく規約であることを忘れないでください。
Clojureのコア例には、Clojureの標準入出力ストリームを表す*out*
と*in*
が含まれています。
>!!
、<!!
、>!
、<!
- core.asyncチャンネルマクロこれらのシンボルは、チャンネルベースの非同期プログラミング(特にCSP - Communicating Sequential Processes)のためのClojure/ClojureScriptライブラリであるcore.async
のチャンネル操作です。
仮に、チャンネルが物事を追加したり削除したりできるキューのようなものだとすると、これらのシンボルはその単純なAPIをサポートします。
>!!
と<!!
はそれぞれブロッキングputとtakeです。
>!
と<!
は、単にputとtakeです。
違いは、ブロッキングバージョンはgo
ブロックの外で動作し、動作しているスレッドをブロックすることです。
user=> (def my-channel (chan 10)) ; create a channel
user=> (>!! my-channel "hello") ; put stuff on the channel
user=> (println (<!! my-channel)) ; take stuff off the channel
hello
非ブロッキングバージョンはgo
ブロック内で実行する必要があります。それ以外の場合、例外がスローされます。
user=> (def c (chan))
#'user/c
user=> (>! c "nope")
AssertionError Assert failed: >! used not in (go ...) block
nil clojure.core.async/>! (async.clj:123)
これらの違いは、このガイドの範囲外ですが、基本的にgo
ブロックは独自の資源を管理し、スレッドをブロックせずにコードの実行を一時停止します。これにより、非同期で実行されるコードが同期的に見えるようになり、コードベースから非同期コードを管理する負担を取り除きます。
<symbol>?
- 述語サフィックスシンボルの末尾に?
を付けることは、シンボル名に特殊文字をサポートする多くの言語で一般的な命名規則です。これは、それが述語であること、つまり質問を提起することを示すために使用されます。たとえば、バッファ操作を扱うAPIを使用しているとします。
(def my-buffer (buffers/create-buffer [1 2 3]))
(buffers/empty my-buffer)
一見して、この場合の関数empty
が、
渡されたバッファが空の場合はtrue
を返し、
バッファをクリアします。
作成者はempty
をis-empty
に名前変更できたかもしれませんが、Clojureのシンボル命名の豊富さにより、意図をより象徴的に表現できます。
(def my-buffer (buffers/create-buffer [1 2 3]))
(buffers/empty? my-buffer)
false
これは単なる推奨される規約であり、必須ではありません。
<symbol>!
- 安全でない操作STMトランザクションで安全ではない関数/マクロの名前は、感嘆符で終わる必要があります(例:reset!
)。
これは、データストアへの接続、アトムの更新、ファイルストリームのクローズなど、状態を変化させる目的の関数名に付加されているのを最も頻繁に見かけます。
user=> (def my-stateful-thing (atom 0))
#'user/my-stateful-thing
user=> (swap! my-stateful-thing inc)
1
user=> @my-stateful-thing
1
これは単なる推奨される規約であり、必須ではありません。
感嘆符はしばしば「bang」と発音されることに注意してください。
_
- 使用されていない引数下線文字が関数引数またはlet
バインディングで使用されている場合、_
は、この引数を使用しないことを示す一般的な命名規則です。
これは、アトムの値が変化したときにコールバックスタイルの動作を追加するために使用できるadd-watch
関数の例です。アトムが与えられた場合、それが変化するたびに新しい値を出力したいとします。
(def value (atom 0))
(add-watch value nil (fn [_ _ _ new-value]
(println new-value))
(reset! value 6)
; prints 6
(reset! value 9)
; prints 9
add-watch
は4つの引数を取りますが、私たちの場合は最後の引数、つまりアトムの新しい値だけが重要なので、他の引数には_
を使用します。
,
- 空白文字Clojureにおいて、,
はスペース、タブ、改行と全く同じように空白文字として扱われます。そのため、リテラルコレクションではコンマは必須ではありませんが、可読性を高めるために頻繁に使用されます。
user=>(def m {:a 1, :b 2, :c 3}
{:a 1, :b 2, :c 3}
アイデアと[大量の]スペルチェックにご協力いただいた皆様に心から感謝いたします(スペルミスが多いので、Michael R. Mayneさん、lobsang_luddさん、本当にありがとうございます)。特定の機能をリクエストしてくださった方々には、名前を挙げさせていただきました。もし抜けている方がいたら申し訳ありません。
原著者: James Hughes