Clojure

概要

ClojureはProgramming LanguageLISPの方言の1つ。 プログラムはJava仮想マシン、.NETで動作する。

Memo

インストール

  • Javaのランタイム
  • Leiningen…依存関係管理。
sudo apt-get install leiningen
lein repl

Hello, world

(println "hello world")

hello world

(defn hello [name] (str "Hello, " name))

#’user/hello

(defn hello-world [username]
  (println (format "Hello, %s" username)))

#’user/hello-world

状態を共有する。 セットに要素を1つ追加する。

(conj coll item)
(conj #{} "Stu")
class clojure.lang.Compiler$CompilerException
#{“Stu”}

セットを知る。 conjupdate-fn として渡す。

(def visitors (atom #{}))
(swap! visitors conj "Stu")
#’user/visitors
#{“Stu”}

atom はClojureが持つリファレンスタイプのひとつ。 ref の中身は deref で見ることができる。略記として @ を使える。

(deref visitors)
@visitors
#{“Stu”}
#{“Stu”}
(defn hello
  "Writes hello message to *out*. Calls you by username.
Knows if you have been here before."
  [username]
  (swap! visitors conj username)
  (str "Hello, " username))

#’user/hello

(hello "Rich")
@visitors
“Hello, Rich”
#{“Stu” “Rich”}

状態の問題。それまでにどういう動作をしたかによって、結果が異なってくる。 純粋な関数なら、局所的な知識だけで動作を理解できるが、状態が絡むとそこに至るすべての履歴を理解しなければならない。

ライブラリ

userequirerefer を一度にやってくれる。

(require 'clojure.java.io)
(use 'clojure.java.io)

再読込。

(use :reload 'clojure.java.io)

ドキュメント検索

(doc str)

clojure.core/str ([] [x] [x & ys]) With no args, returns the empty string. With one arg x, returns x.toString(). (str ) returns the empty string. With more than one arg, returns the concatenation of the str values of the args.

(find-doc "reduce")

cider.nrepl.middleware.track-state/fast-reduce ([f coll]) Like (reduce f {} coll), but faster. Inside f, use `assoc!` and `conj!` instead of `assoc` and `conj`.


clojure.core/areduce ([a idx ret init expr]) Macro Reduces an expression across an array a, using an index named idx, and return value named ret, initialized to init, setting ret to the evaluation of expr at each step, returning ret.


clojure.core/eduction ([xform* coll]) Returns a reducible/iterable application of the transducers to the items in coll. Transducers are applied in order as if combined with comp. Note that these applications will be performed every time reduce/iterator is called.


clojure.core/ensure-reduced ([x]) If x is already reduced?, returns it, else returns (reduced x)


clojure.core/reduce ([f coll] [f val coll]) f should be a function of 2 arguments. If val is not supplied, returns the result of applying f to the first 2 items in coll, then applying f to that result and the 3rd item, etc. If coll contains no items, f must accept no arguments as well, and reduce returns the result of calling f with no arguments. If coll has only 1 item, it is returned and f is not called. If val is supplied, returns the result of applying f to val and the first item in coll, then applying f to that result and the 2nd item, etc. If coll contains no items, returns val and f is not called.


clojure.core/reduce-kv ([f init coll]) Reduces an associative collection. f should be a function of 3 arguments. Returns the result of applying f to init, the first key and the first value in coll, then applying f to that result and the 2nd key and value, etc. If coll contains no entries, returns init and f is not called. Note that reduce-kv is supported on vectors, where the keys will be the ordinals.


clojure.core/reduced ([x]) Wraps x in a way such that a reduce will terminate with the value x


clojure.core/reduced? ([x]) Returns true if x is the result of a call to reduced


clojure.core/reductions ([f coll] [f init coll]) Returns a lazy seq of the intermediate values of the reduction (as per reduce) of coll by f, starting with init.


clojure.core/require ([& args]) Loads libs, skipping any that are already loaded. Each argument is either a libspec that identifies a lib, a prefix list that identifies multiple libs whose names share a common prefix, or a flag that modifies how all the identified libs are loaded. Use :require in the ns macro in preference to calling this directly.

Libs

A ’lib’ is a named set of resources in classpath whose contents define a library of Clojure code. Lib names are symbols and each lib is associated with a Clojure namespace and a Java package that share its name. A lib’s name also locates its root directory within classpath using Java’s package name to classpath-relative path mapping. All resources in a lib should be contained in the directory structure under its root directory. All definitions a lib makes should be in its associated namespace.

’require loads a lib by loading its root resource. The root resource path is derived from the lib name in the following manner: Consider a lib named by the symbol ’x.y.z; it has the root directory <classpath>/x/y/, and its root resource is <classpath>/x/y/z.clj, or <classpath>/x/y/z.cljc if <classpath>/x/y/z.clj does not exist. The root resource should contain code to create the lib’s namespace (usually by using the ns macro) and load any additional lib resources.

Libspecs

A libspec is a lib name or a vector containing a lib name followed by options expressed as sequential keywords and arguments.

Recognized options: :as takes a symbol as its argument and makes that symbol an alias to the lib’s namespace in the current namespace. :refer takes a list of symbols to refer from the namespace or the :all keyword to bring in all public vars.

Prefix Lists

It’s common for Clojure code to depend on several libs whose names have the same prefix. When specifying libs, prefix lists can be used to reduce repetition. A prefix list contains the shared prefix followed by libspecs with the shared prefix removed from the lib names. After removing the prefix, the names that remain must not contain any periods.

Flags

A flag is a keyword. Recognized flags: :reload, :reload-all, :verbose :reload forces loading of all the identified libs even if they are already loaded :reload-all implies :reload and also forces loading of all libs that the identified libs directly or indirectly load via require or use :verbose triggers printing information about each load, alias, and refer

Example:

The following would load the libraries clojure.zip and clojure.set abbreviated as ’s’.

(require ’(clojure zip [set :as s]))


clojure.core/run! ([proc coll]) Runs the supplied procedure (via reduce), for purposes of side effects, on successive items in the collection. Returns


clojure.core/transduce ([xform f coll] [xform f init coll]) reduce with a transformation of f (xf). If init is not supplied, (f) will be called to produce it. f should be a reducing step function that accepts both 1 and 2 arguments, if it accepts only 2 you can add the arity-1 with ’completing’. Returns the result of applying (the transformed) xf to init and the first item in coll, then applying xf to that result and the 2nd item, etc. If coll contains no items, returns init and f is not called. Note that certain transforms may inject or skip items.


clojure.core/unreduced ([x]) If x is reduced?, returns (deref x), else returns x


clojure.core.protocols/CollReduce Protocol for collection types that can implement reduce faster than first/next recursion. Called by clojure.core/reduce. Baseline implementation defined in terms of Iterable.


clojure.core.protocols/IKVReduce Protocol for concrete associative types that can reduce themselves via a function of key and val faster than first/next recursion over map entries. Called by clojure.core/reduce-kv, and has same semantics (just different arg order).


clojure.core.protocols/InternalReduce Protocol for concrete seq types that can reduce themselves faster than first/next recursion. Called by clojure.core/reduce.


clojure.core.protocols/interface-or-naive-reduce ([coll f val]) Reduces via IReduceInit if possible, else naively.


clojure.core.protocols/naive-seq-reduce ([s f val]) Reduces a seq, ignoring any opportunities to switch to a more specialized implementation.


cider.nrepl.middleware.util.instrument/strip-instrumentation-meta ([form]) Remove all tags in order to reduce java bytecode size and enjoy cleaner code printouts. We keep ::breakfunction for def symbols because that is how we identify currently instrumented vars in list-instrumented-defs.

clojure関数のソースを見る

repl ライブラリを使う。

(use 'clojure.repl)
(source identity)

ClojureのコレクションがJavaのコレクションであることを確かめる。

(ancestors (class [1 2 3]))

#{clojure.lang.IPersistentVector clojure.lang.Indexed clojure.lang.IMeta clojure.lang.ILookup java.lang.Runnable java.lang.Iterable java.util.List clojure.lang.IPersistentCollection java.io.Serializable clojure.lang.IEditableCollection java.util.Collection clojure.lang.Seqable java.util.concurrent.Callable clojure.lang.IHashEq clojure.lang.Counted java.util.RandomAccess clojure.lang.Associative clojure.lang.IFn clojure.lang.Reversible clojure.lang.IObj clojure.lang.IReduceInit clojure.lang.AFn java.lang.Object clojure.lang.IReduce clojure.lang.Sequential clojure.lang.IPersistentStack clojure.lang.IKVReduce clojure.lang.APersistentVector java.lang.Comparable}

フォーム

  • Clojureは同図像性を持つ。
  • ClojureのコードはClojureのデータによって組み立てられる。
  • Clojureのプログラムを走らせるときには、まずClojureの中の リーダ と呼ばれる部分がプログラムを フォーム と呼ばれる単位ごとに読み込んで、それをClojureのデータ構造へと変換する。そしてデータ構造をコンパイルして実行する。

フォームにはブール値、文字、キーワード、リスト、マップ…などがある。

シンボル

シンボルは、Clojure内のあらゆる種類のものの名前として使う。

ドットでJavaメソッドの呼び出しであると判断する。

(.toUpperCase "hello")
(str "hello")
“HELLO”
“hello”

リテラル表記は \{letter}

(str \h \e \y \space \y \o \u)

hey you

文字を交互に結合。

(interleave "Attack at midnight" "The purple elephant chortled")

(\A \T \t \h \t \e \a \space \c \p \k \u \space \r \a \p \t \l \space \e \m \space \i \e \d \l \n \e \i \p \g \h \h \a \t \n)

文字列に戻す。

(apply str (interleave "Attack at midnight" "The purple elephant chortled"))

ATthtea cpku raptl em iedlneipghhatn

復元する。

(apply str (take-nth 2 "ATthtea cpku raptl em iedlneipghhatn"))
“clojure.lang.LazySeq@c855d426”
“Attack at midnight”

Clojureでは空リストは偽ではない。

(if () "We are in Clojure!" "We are in Common Lisp!")

We are in Clojure!

true? は値が true そのものであるかを調べる。

(true? true)
(true? "foo")
true
false
(zero? 0.0)

true

述語一覧。

(find-doc #"\?$")

nrepl.middleware.interruptible-eval/interrupted? ([e]) Returns true if the given throwable was ultimately caused by an interrupt.


leiningen.core.classpath/ext-dependency? ([dep]) Should the given dependency be loaded in the extensions classloader?


leiningen.core.pedantic/range? ([{:keys [node]}]) Does the path point to a DependencyNode asking for a version range?


leiningen.core.pedantic/top-level? ([{:keys [parents]}]) Is the path a top level dependency in the project?


clojure.test/function? ([x]) Returns true if argument is a function or a symbol that resolves to a function (not a macro).


clojure.test/successful? ([summary]) Returns true if the given test summary indicates all tests were successful, false otherwise.


cider.nrepl.inlined-deps.toolsreader.v1v3v2.clojure.tools.reader/garg ([n]) Get a symbol for an anonymous ?argument?


dynapath.util/addable-classpath? ([cl]) Returns true if the given ClassLoader provides add-claspath-url.


dynapath.util/readable-classpath? ([cl]) Returns true if the given ClassLoader provides classpath-urls.


cider.nrepl.middleware.debug/looks-step-innable? ([form]) Decide whether a form looks like a call to a function that we could instrument and step into.


cider.nrepl.middleware.debug/safe-to-debug? ([ns]) Some namespaces are not safe to debug, because doing so can cause a stack overflow that crashes the nrepl process.


cider.nrepl.middleware.debug/skip-breaks? ([coor STATE__]) True if the breakpoint at coordinates should be skipped.

The `*skip-breaks*` map stores a `mode`, `coordinates`, the `code` that it applies to, and a `force?` flag.

Behaviour depends on the `mode`:

  • :all - return true, skipping all breaks
  • :trace - return false, skip nothing
  • :deeper - return true if the given coordinates are deeper than the coordinates stored in `*skip-breaks*`, in the same code
  • :before - return true if the given coordinates represent a place before the coordinates in `*skip-breaks*`, in the same code

For :deeper and :before, if we are not in the same code (i.e. we have stepped into another instrumented function and code argument doesn’t match old code in skip-breaks), then return the value of `force?`.


cider.nrepl.middleware.debug/step-in? ([v coor code]) Return true if we can and should step in to the function in the var `v`. The “should” part is determined by the value in `step-in-to-next?`, which gets set to true by the user sending the “step in” command.


clojure.core.specs.alpha/even-number-of-forms? ([forms]) Returns true if there are an even number of forms in a binding vector


nrepl.middleware.session/interrupted? ([e]) Returns true if the given throwable was ultimately caused by an interrupt.


cider.nrepl.inlined-deps.javaclasspath.v1v0v0.clojure.java.classpath/jar-file? ([f]) Returns true if file is a normal file with a .jar or .JAR extension.


cider.nrepl.middleware.util.error-handling/shallow-bencodable? ([item]) Returns false if `item`’s type can’t be bencoded as defined by the algorithm in `nrepl.bencode/write-bencode`. Does not examine the elements of a collection to ensure that the enclosed elements are also bencodable, and so you probably actually want to use `deep-bencodable-or-fail` or write something similar.


cider.nrepl.inlined-deps.dynapath.v1v1v0.dynapath.dynamic-classpath/can-add? ([cl]) Must return true if add-classpath-url is implemented.


cider.nrepl.inlined-deps.dynapath.v1v1v0.dynapath.dynamic-classpath/can-read? ([cl]) Must return true if classpath-urls is implemented.


clojure.spec.alpha/? ([pred-form]) Macro Returns a regex op that matches zero or one value matching pred. Produces a single value (not a collection) if matched.


clojure.spec.alpha/check-asserts? ([]) Returns the value set by check-asserts.


clojure.spec.alpha/inst-in-range? ([start end inst]) Return true if inst at or after start and before end


clojure.spec.alpha/int-in-range? ([start end val]) Return true if start <= val, val < end and val is a fixed precision integer.


clojure.spec.alpha/invalid? ([ret]) tests the validity of a conform return value


clojure.spec.alpha/pvalid? ([pred x] [pred x form]) internal helper function that returns true when x is valid for spec.


clojure.spec.alpha/regex? ([x]) returns x if x is a (clojure.spec) regex op, else logical false


clojure.spec.alpha/spec? ([x]) returns x if x is a spec object, else logical false


clojure.spec.alpha/valid? ([spec x] [spec x form]) Helper function that returns true when x is valid for spec.


cider.nrepl.inlined-deps.toolsnamespace.v1v0v0.clojure.tools.namespace.dependency/dependent? ([graph x y]) True if y is a dependent of x.


cider.nrepl.inlined-deps.toolsnamespace.v1v0v0.clojure.tools.namespace.dependency/depends? ([graph x y]) True if x is directly or transitively dependent on y.


leiningen.core.project/composite-profile? ([profile]) Returns true if the profile is composite, false otherwise.


leiningen.core.project/different-priority? ([left right]) Returns true if either left has a higher priority than right or vice versa.


leiningen.core.project/displace? ([obj]) Returns true if the object is marked as displaceable


leiningen.core.project/replace? ([obj]) Returns true if the object is marked as replaceable


leiningen.core.project/top-displace? ([obj]) Returns true if the object is marked as top-displaceable


clojure.set/subset? ([set1 set2]) Is set1 a subset of set2?


clojure.set/superset? ([set1 set2]) Is set1 a superset of set2?


cemerick.pomegranate.aether/within? ([[dep version & opts :as coord] [sdep sversion & sopts :as scoord]]) Determines if the first coordinate would be a version in the second coordinate. The first coordinate is not allowed to contain a version range.


clojure.string/blank? ([s]) True if s is , empty, or contains only whitespace.


clojure.string/ends-with? ([s substr]) True if s ends with substr.


clojure.string/includes? ([s substr]) True if s includes substr.


clojure.string/starts-with? ([s substr]) True if s starts with substr.


cider.nrepl.inlined-deps.orchard.v0v7v1.orchard.misc/boot-project? ([]) Check whether we’re dealing with a Boot project. We figure this by checking for the presence of Boot’s fake classpath.


cider.nrepl.inlined-deps.orchard.v0v7v1.orchard.misc/directory? ([f]) Whether the argument is a directory or an url that points to a directory


cider.nrepl.inlined-deps.orchard.v0v7v1.orchard.misc/file-ext? ([f & exts]) Whether the argument’s path ends in one of the specified case-insensitive file extensions


cider.nrepl.inlined-deps.orchard.v0v7v1.orchard.misc/ns-obj? ([ns]) Return true if n is a namespace object


cider.nrepl.inlined-deps.orchard.v0v7v1.orchard.misc/url? ([u]) Check whether the argument is an url


cider.nrepl.inlined-deps.orchard.v0v7v1.orchard.java/add-java-sources-via-dynapath? Should orchard use the dynapath library to use “fetch Java sources” functionality?

Note that using dynapath currently implies some bugs, so you might want to disable this option.


cider.nrepl.inlined-deps.orchard.v0v7v1.orchard.java/immutable-source-file? ([info]) Return true if the source file is effectively immutable. Specifically, this returns true if no source file is available, or if the source file is in a jar/zip archive.


cider.nrepl.inlined-deps.orchard.v0v7v1.orchard.java/initialize-cache-silently? Should `#’cache-initializer` refrain from printing to `System/out`?


cider.nrepl.inlined-deps.dynapath.v1v1v0.dynapath.util/addable-classpath? ([cl]) Returns true if the given ClassLoader provides add-claspath-url.


cider.nrepl.inlined-deps.dynapath.v1v1v0.dynapath.util/readable-classpath? ([cl]) Returns true if the given ClassLoader provides classpath-urls.


cider.nrepl.inlined-deps.toolsreader.v1v3v2.clojure.tools.reader.reader-types/indexing-reader? ([rdr]) Returns true if the reader satisfies IndexingReader


cider.nrepl.inlined-deps.toolsreader.v1v3v2.clojure.tools.reader.reader-types/line-start? ([rdr]) Returns true if rdr is an IndexingReader and the current char starts a new line


clojure.core/any? ([x]) Returns true given any argument.


clojure.core/associative? ([coll]) Returns true if coll implements Associative


clojure.core/boolean? ([x]) Return true if x is a Boolean


clojure.core/bound? ([& vars]) Returns true if all of the vars provided as arguments have any bound value, root or thread-local. Implies that deref’ing the provided vars will succeed. Returns true if no vars are provided.


clojure.core/bytes? ([x]) Return true if x is a byte array


clojure.core/char? ([x]) Return true if x is a Character


clojure.core/class? ([x]) Returns true if x is an instance of Class


clojure.core/coll? ([x]) Returns true if x implements IPersistentCollection


clojure.core/contains? ([coll key]) Returns true if key is present in the given collection, otherwise returns false. Note that for numerically indexed collections like vectors and Java arrays, this tests if the numeric key is within the range of indexes. ’contains?’ operates constant or logarithmic time; it will not perform a linear search for a value. See also ’some’.


clojure.core/counted? ([coll]) Returns true if coll implements count in constant time


clojure.core/decimal? ([n]) Returns true if n is a BigDecimal


clojure.core/delay ([& body]) Macro Takes a body of expressions and yields a Delay object that will invoke the body only the first time it is forced (with force or deref/@), and will cache the result and return it on all subsequent force calls. See also - realized?


clojure.core/delay? ([x]) returns true if x is a Delay created with delay


clojure.core/distinct? ([x] [x y] [x y & more]) Returns true if no two of the arguments are =


clojure.core/double? ([x]) Return true if x is a Double


clojure.core/empty? ([coll]) Returns true if coll has no items - same as (not (seq coll)). Please use the idiom (seq x) rather than (not (empty? x))


clojure.core/even? ([n]) Returns true if n is even, throws an exception if n is not an integer


clojure.core/every? ([pred coll]) Returns true if (pred x) is logical true for every x in coll, else false.


clojure.core/extends? ([protocol atype]) Returns true if atype extends protocol


clojure.core/false? ([x]) Returns true if x is the value false, false otherwise.


clojure.core/fits-table? ([ints]) Returns true if the collection of ints can fit within the max-table-switch-size, false otherwise.


clojure.core/float? ([n]) Returns true if n is a floating point number


clojure.core/fn? ([x]) Returns true if x implements Fn, i.e. is an object created via fn.


clojure.core/future-cancelled? ([f]) Returns true if future f is cancelled


clojure.core/future-done? ([f]) Returns true if future f is done


clojure.core/future? ([x]) Returns true if x is a future


clojure.core/ident? ([x]) Return true if x is a symbol or keyword


clojure.core/identical? ([x y]) Tests if 2 arguments are the same object


clojure.core/ifn? ([x]) Returns true if x implements IFn. Note that many data structures (e.g. sets and maps) implement IFn


clojure.core/indexed? ([coll]) Return true if coll implements Indexed, indicating efficient lookup by index


clojure.core/inst? ([x]) Return true if x satisfies Inst


clojure.core/instance? ([c x]) Evaluates x and tests if it is an instance of the class c. Returns true or false


clojure.core/int? ([x]) Return true if x is a fixed precision integer


clojure.core/integer? ([n]) Returns true if n is an integer


clojure.core/isa? ([child parent] [h child parent]) Returns true if (= child parent), or child is directly or indirectly derived from parent, either via a Java type inheritance relationship or a relationship established via derive. h must be a hierarchy obtained from make-hierarchy, if not supplied defaults to the global hierarchy


clojure.core/keyword? ([x]) Return true if x is a Keyword


clojure.core/lazy-seq ([& body]) Macro Takes a body of expressions that returns an ISeq or , and yields a Seqable object that will invoke the body only the first time seq is called, and will cache the result and return it on all subsequent seq calls. See also - realized?


clojure.core/libspec? ([x]) Returns true if x is a libspec


clojure.core/list? ([x]) Returns true if x implements IPersistentList


clojure.core/map-entry? ([x]) Return true if x is a map entry


clojure.core/map? ([x]) Return true if x implements IPersistentMap


clojure.core/nat-int? ([x]) Return true if x is a non-negative fixed precision integer


clojure.core/neg-int? ([x]) Return true if x is a negative fixed precision integer


clojure.core/neg? ([num]) Returns true if num is less than zero, else false


clojure.core/? ([x]) Returns true if x is , false otherwise.


clojure.core/not-any? ([pred coll]) Returns false if (pred x) is logical true for any x in coll, else true.


clojure.core/not-every? ([pred coll]) Returns false if (pred x) is logical true for every x in coll, else true.


clojure.core/number? ([x]) Returns true if x is a Number


clojure.core/odd? ([n]) Returns true if n is odd, throws an exception if n is not an integer


clojure.core/pos-int? ([x]) Return true if x is a positive fixed precision integer


clojure.core/pos? ([num]) Returns true if num is greater than zero, else false


clojure.core/qualified-ident? ([x]) Return true if x is a symbol or keyword with a namespace


clojure.core/qualified-keyword? ([x]) Return true if x is a keyword with a namespace


clojure.core/qualified-symbol? ([x]) Return true if x is a symbol with a namespace


clojure.core/ratio? ([n]) Returns true if n is a Ratio


clojure.core/rational? ([n]) Returns true if n is a rational number


clojure.core/reader-conditional? ([value]) Return true if the value is the data representation of a reader conditional


clojure.core/realized? ([x]) Returns true if a value has been produced for a promise, delay, future or lazy sequence.


clojure.core/record? ([x]) Returns true if x is a record


clojure.core/reduced? ([x]) Returns true if x is the result of a call to reduced


clojure.core/reversible? ([coll]) Returns true if coll implements Reversible


clojure.core/satisfies? ([protocol x]) Returns true if x satisfies the protocol


clojure.core/seq? ([x]) Return true if x implements ISeq


clojure.core/seqable? ([x]) Return true if the seq function is supported for x


clojure.core/sequential? ([coll]) Returns true if coll implements Sequential


clojure.core/set? ([x]) Returns true if x implements IPersistentSet


clojure.core/simple-ident? ([x]) Return true if x is a symbol or keyword without a namespace


clojure.core/simple-keyword? ([x]) Return true if x is a keyword without a namespace


clojure.core/simple-symbol? ([x]) Return true if x is a symbol without a namespace


clojure.core/some? ([x]) Returns true if x is not , false otherwise.


clojure.core/sorted? ([coll]) Returns true if coll implements Sorted


clojure.core/special-symbol? ([s]) Returns true if s names a special form


clojure.core/string? ([x]) Return true if x is a String


clojure.core/symbol? ([x]) Return true if x is a Symbol


clojure.core/tagged-literal? ([value]) Return true if the value is the data representation of a tagged literal


clojure.core/thread-bound? ([& vars]) Returns true if all of the vars provided as arguments have thread-local bindings. Implies that set!’ing the provided vars will succeed. Returns true if no vars are provided.


clojure.core/true? ([x]) Returns true if x is the value true, false otherwise.


clojure.core/uri? ([x]) Return true if x is a java.net.URI


clojure.core/uuid? ([x]) Return true if x is a java.util.UUID


clojure.core/var? ([v]) Returns true if v is of type clojure.lang.Var


clojure.core/vector? ([x]) Return true if x implements IPersistentVector


clojure.core/volatile? ([x]) Returns true if x is a volatile.


clojure.core/zero? ([num]) Returns true if num is zero, else false


cider.nrepl.inlined-deps.toolsreader.v1v3v2.clojure.tools.reader.impl.utils/newline? ([c]) Checks whether the character is a newline


cider.nrepl.inlined-deps.toolsreader.v1v3v2.clojure.tools.reader.impl.utils/numeric? ([ch]) Checks whether a given character is numeric


cider.nrepl.inlined-deps.toolsreader.v1v3v2.clojure.tools.reader.impl.utils/whitespace? ([ch]) Checks whether a given character is whitespace


cider.nrepl.inlined-deps.toolsreader.v1v3v2.clojure.tools.reader.impl.commons/number-literal? ([reader initch]) Checks whether the reader is at the start of a number literal


cider.nrepl.inlined-deps.orchard.v0v7v1.orchard.info/qualified-symbol? ([x]) Return true if `x` is a symbol with a namespace

This is only available from Clojure 1.9 so we backport it until we drop support for Clojure 1.8.


dynapath.dynamic-classpath/can-add? ([cl]) Must return true if add-classpath-url is implemented.


dynapath.dynamic-classpath/can-read? ([cl]) Must return true if classpath-urls is implemented.


cemerick.pomegranate/modifiable-classloader? ([cl]) Returns true iff the given ClassLoader is of a type that satisfies the dynapath.dynamic-classpath/DynamicClasspath protocol, and it can be modified.


clojure.pprint/integral? ([x]) returns true if a number is actually an integer (that is, has no fractional part)


clojure.pprint/pretty-writer? ([x]) Return true iff x is a PrettyWriter


cider.nrepl.inlined-deps.toolsnamespace.v1v0v0.clojure.tools.namespace.parse/comment? ([form]) Returns true if form is a (comment …)


cider.nrepl.inlined-deps.toolsnamespace.v1v0v0.clojure.tools.namespace.parse/ns-decl? ([form]) Returns true if form is a (ns …) declaration.


cider.nrepl.inlined-deps.toolsnamespace.v1v0v0.clojure.tools.namespace.parse/option-spec? ([form]) Returns true if form represents a libspec vector containing optional keyword arguments like [namespace :as alias] or [namespace :refer (x y)] or just [namespace]


cider.nrepl.inlined-deps.toolsnamespace.v1v0v0.clojure.tools.namespace.parse/prefix-spec? ([form]) Returns true if form represents a libspec prefix list like (prefix name1 name1) or [com.example.prefix [name1 :as name1]]


leiningen.core.utils/ancestor? ([a b]) Is a an ancestor of b?


leiningen.core.utils/symlink? ([file]) Checks if a File is a symbolic link or points to another file.


leiningen.core.user/gpg-available? ([]) Verifies (gpg-program) exists


cider.nrepl.inlined-deps.orchard.v0v7v1.orchard.namespace/has-tests? ([ns]) Returns a truthy value if the namespace has any vars with `:test` metadata.


cider.nrepl.inlined-deps.orchard.v0v7v1.orchard.namespace/in-project? ([url]) Whether the URL is in the current project’s directory.


cider.nrepl.inlined-deps.orchard.v0v7v1.orchard.namespace/inlined-dependency? ([namespace]) Returns true if the namespace matches one of our, or eastwood’s, inlined dependencies.


cider.nrepl.inlined-deps.orchard.v0v7v1.orchard.namespace/internal-namespace? ([namespace & [prefixes]]) Returns true if the namespace matches the given prefixes.


cider.nrepl.inlined-deps.toolsnamespace.v1v0v0.clojure.tools.namespace.file/clojure-file? ([file]) Returns true if the java.io.File represents a file which will be read by the Clojure (JVM) compiler.


cider.nrepl.inlined-deps.toolsnamespace.v1v0v0.clojure.tools.namespace.file/clojurescript-file? ([file]) Returns true if the java.io.File represents a file which will be read by the ClojureScript compiler.


cider.nrepl.inlined-deps.toolsnamespace.v1v0v0.clojure.tools.namespace.file/file-with-extension? ([file extensions]) Returns true if the java.io.File represents a file whose name ends with one of the Strings in extensions.


cider.nrepl.middleware.util.instrument/contains-recur? ([form]) Return true if form is not a `loop` or a `fn` and a `recur` is found in it.


cider.nrepl.middleware.util.instrument/dont-break? ([[name :as form]]) Return true if it’s NOT ok to wrap form in a breakpoint. Expressions we don’t want to wrap are those listed in `dont-break-forms` and anything containing a `recur` form (unless it’s inside a `loop`).


cider.nrepl.inlined-deps.orchard.v0v7v1.orchard.inspect Clojure data structure inspection functionality. This code has a long history and at various points of time it lived in different projects. Originally it was part of swank-clojure, afterwards it was moved to javert, then forked to another project from which it was contributed to cider-nrepl. Finally cider-nrepl was split into two libraries and the code ended up here.

Pretty wild, right?

マップ/キーワード/レコード

マップ。

(def inventors {"Lisp" "McCarthy" "Clojure" "Hickey"})

#’user/inventors

みやすさのためにコロンを置くこともできる。

(def inventors {"Lisp" "McCarthy", "Clojure" "Hickey"})

#’user/inventors

マップは関数としても動作する。

(inventors "Lisp")

McCarthy

get 関数も使える。存在しない場合の値を指定できる。

(get inventors "Lisp" "not find")
(get inventors "Foo" "not find")
“McCarthy”
“not find”

キーワード はシンボルに似ているが、コロンで始まる。評価されると自分自身を返す。

:foo

:foo

シンボルとは異なる。シンボルは評価されるとそれに結び付けられた何かを返そうとする。

foo

class clojure.lang.Compiler$CompilerException

キーワードをキーにして書き直す。

(def inventors {:Lisp "McCarthy" :Clojure "Hickey"})

#’user/inventors

defrecord を使って構造体を定義することで、各マップがどういうキーを取りうるか明示し、強制できる。

(defrecord Book [title author])
(->Book "title" "author")
user.Book
#user.Book{:title “title”, :author “author”}

マップと同じように扱える。

(def b (->Book "Anathem" "Neal Stephenson"))
(:title b)
#’user/b
“Anathem”

リーダマクロ

Clojureのフォームはリーダによって読まれて、テキストからClojureのデータに変換される。 リーダマクロは前置される特定のマクロ文字によって起動される、リーダの特殊な動作。 コメントのセミコロンや、評価抑制のクォートもリーダマクロ。

関数

関数呼び出しは単に最初の要素が関数を指すようなリストである。 自分で関数を定義するには defn を使う( def ではない)。

(defn greeting
  "Returns a greeting of the form 'Hello, username.'"
  [username]
  (str "Hello, " username))
(greeting "world")
#’user/greeting
“Hello, world”

同名の関数で受け取る引数が違うものを呼び出す。 ゼロ引数の greeting は1引数の greeting に渡して移譲できる。

(defn greeting
  "Returns a greeting of the form 'Hello, username.'
     Default username is 'world'."
  ([] (greeting "world"))
  ([username] (str "Hello, " username)))

(greeting)
#’user/greeting
“Hello, world”

フィルタ。 まず述語を定義する。

(defn indexable-word? [word]
  (> (count word) 2))

#’user/indexable-word?

適用する。

(require '[clojure.string :as str])
(filter indexable-word? (str/split "A fine day it is" #"\W+"))
fine day

無名関数バージョン。

(filter (fn [w] (> (count w) 2)) (str/split "A fine day" #"\W+"))
fine day
(defn make-greeter [greeting-prefix]
  (fn [username] (str greeting-prefix ", " username)))

(def hello-greeting (make-greeter "Hello"))
(hello-greeting "world")

(def aloha-greeting (make-greeter "Aloha"))
(aloha-greeting "Hawaii")
#’user/make-greeter
#’user/hello-greeting
“Hello, world”
#’user/aloha-greeting
“Aloha, Hawaii”

名前を与えなくてもいい。

((make-greeter "Howdy") "pardner")

Howdy, pardner

var、束縛、名前空間

オブジェクトを def defn で定義すると、オブジェクトはClojureの var に格納される。

リーダマクロで user/foo に結び付けられた var を見る。

(def foo 10)
#'foo
#’user/foo
#’user/foo

実引数と仮引数のnumberが束縛される。

(defn triple [number] (* 3 number))
(triple 10)
#’user/triple
30

関数の引数束縛はレキシカルスコープ…関数本体の中だけから見える。

コレクション全体を変数に束縛する。 姓と名を両方とも保存するけど、名だけが必要な場合。 ↓引数authorを取るが、必要なのは名だけで、ちょっとわかりにくい。

(defn greet-author-1 [author]
  (println "Hello," (:first-name author)))

#’user/greet-author-1

必要な部分だけを束縛する。

(defn greet-author-2 [{fname :first-name}]
  (println "Hello," fname))

アンダースコアは慣用的に値を気にしない束縛を示すのに使う。

(let [[_ _ z] [1 2 3]] z)

3

as でコレクション自体に名前をつけることもできる。

(let [[x y :as coords] [1 2 3 4 5 6]]
  (str "x: " x ", y: " y ", total dimensions " (count coords)))

x: 1, y: 2, total dimensions 6

分配束縛を使う。 [w1 w2 w3] への分配束縛によって最初の3つの単語が取り出される。

(require '[clojure.string :as str])
(defn ellipsize [words]
  (let [[w1 w2 w3] (str/split words #"\s+")]
    (str/join " " [w1 w2 w3 "..."])))

(ellipsize "The quick brown fox jumps over the lazy dogs.")
#’user/ellipsize
“The quick brown …”
(resolve 'foo)
(in-ns 'myapp)
#’user/foo
#namespace[myapp]
(clojure.core/use 'clojure.core)

Javaを呼び出す

(new java.util.Random)

#object[java.util.Random 0x499982f7 “java.util.Random@499982f7”]

(def rnd (new java.util.Random))

#’user/rnd

(. rnd nextInt)

1468370734

(. rnd nextInt 10)

9

. はインスタンスのメソッドだけでなく、クラスメンバへのアクセスにも使える。

(. Math PI)

3.141592653589793

ブラウザで該当ドキュメントに移動する。

(javadoc java.net.URL)

true

フロー制御

(defn is-small? [number]
  (if (< number 100) "yes" "no"))

(is-small? 50)
(is-small? 101)
#’user/is-small?
“yes”
“no”

分岐後に複数のアクションを起こす、には do を使う。 do は副作用をもたらすという明示になる。

(defn is-small? [number]
  (if (< number 100)
    "yes"
    (do
      (println "Saw a big number" number)
      "no")))
(is-small? 200)

loop を使っての再帰。

(loop [result [] x 5]
  (if (zero? x)
    result
    (recur (conj result x) (dec x))))
5 4 3 2 1
(defn countdown [result x]
  (if (zero? x)
    result
    (recur (conj result x) (dec x))))

(countdown [] 5)
#’user/countdown
[5 4 3 2 1]

さまざまなカウントダウン。

(into [] (take 5 (iterate dec 5)))
5 4 3 2 1
(into [] (drop-last (reverse (range 6))))
5 4 3 2 1
(vec (reverse (rest (range 6))))
5 4 3 2 1
(defn indexed [coll] (map-indexed vector coll))
(indexed "abcde")
#’user/indexed
([0 \a] [1 \b] [2 \c] [3 \d] [4 \e])
(indexed "abcde")

clojureの for はループではなく、シーケンスの内包表記である。

(defn index-filter [pred coll]
  (when pred
    (for [[idx elt] (indexed coll) :when (pred elt)] idx)))
(index-filter #{\a \b} "abcdbbb")
(index-filter #{\a \b} "xyz")
#’user/index-filter
(0 1 4 5 6)
()
(defn index-of-any [pred coll]
  (first (index-filter pred coll)))
(index-of-any #{\z \a} "zzabyycdxx")
(index-of-any #{\b \y} "zzabyycdxx")
#’user/index-of-any
0
3

メタデータ

(meta #'str)

’(:added “1.0” :ns #namespace(clojure.core) :name str :file “clojure/core.clj” :static true :column 1 :line 544 :tag java.lang.String :arglists (() (x) (x & ys)) :doc “With no args, returns the empty string. With one arg x, returns\\n x.toString(). (str ) returns the empty string. With more than\\n one arg, returns the concatenation of the str values of the args.”)

(defn ^{:tag String} shout [^{:tag String} s] (.toUpperCase s))
(meta #'shout)
#’user/shout
{:tag java.lang.String, :arglists ([s]), :line 1, :column 1, :file “cider-repl”, :name shout, :ns #namespace[user]}

あるいは略記法で書ける。

(defn ^String shout [^String s] (.toUpperCase s))

#’user/shout

シーケンス

シーケンスはいろんなデータ構造の抽象。

(class (rest [1 2 3]))

clojure.lang.PersistentVector$ChunkedSeq

(first ["a" "b"])
(rest ["a" "b"])
(cons "a" "b")
“a”
(“b”)
(“a” \b)

マップはキー/値のペアを要素とするシーケンスとして扱える。

(first {:fname "Aaron" :lname "Bedra"})
(rest {:fname "Aaron" :lname "Bedra"})
(cons [:mname "James"] {:fname "Aaron" :lname "Bedra"})
[:fname “Aaron”]
([:lname “Bedra”])
([:mname “James”] [:fname “Aaron”] [:lname “Bedra”])

conjinfo は効率的に追加できる位置に要素を加える。 対象となるデータ構造について一番効率の良い操作をしてくれるので、具体的な実装に結び付けなくても効率的なコードが書ける。

(conj '(1 2 3) :a)
:a 1 2 3
(into '(1 2 3) '(:a :b :c))
:c :b :a 1 2 3

シーケンスライブラリ

シーケンスを生成する関数

(range 10)
(range 10 20)
(range 10 20 2)
(0 1 2 3 4 5 6 7 8 9)
(10 11 12 13 14 15 16 17 18 19)
(10 12 14 16 18)

↓なぜか実行できない。

(repeat 5 "x")

シーケンスは無限に続くので取り出しが必要。

(take 10 (iterate inc 1))
1 2 3 4 5 6 7 8 9 10
(defn whole-numbers [] (iterate inc 1))

#’user/whole-numbers

(take 4 (repeat 1))
1 1 1 1
(take 10 (cycle (range 3)))
0 1 2 0 1 2 0 1 2 0
(interpose "," ["apple" "banana" "grapes"])
apple , banana , grapes
(use '[clojure.string :only (join)])
(join \, ["apples" "banana", "grapes"])

apples,banana,grapes

シーケンスをフィルタする関数

(take 10 (filter even? (whole-numbers)))
2 4 6 8 10 12 14 16 18 20
(take 10 (filter odd? (whole-numbers)))
1 3 5 7 9 11 13 15 17 19

最初の母音に出会うまで文字列から文字を取り出す操作。

(take-while (complement #{\a\e\i\o\u}) "the-quick-brown-fox")

(\t \h)

(drop-while (complement #{\a\e\i\o\u}) "the-quick-brown-fox")

(\e ­ \q \u \i \c \k ­ \b \r \o \w \n ­ \f \o \x)

(split-at 5 (range 10))
0 1 2 3 4
5 6 7 8 9
(split-with #(<= % 10) (range 0 20 2))
0 2 4 6 8 10
12 14 16 18    

シーケンスに対する述語

述語をそれぞれ適応して真偽値を返す。

(every? odd? [1 3 5])
(every? odd? [1 3 8])
true
false

いずれかが条件に合わないときはnilを返す。

(some even? [1 2 3])
(some even? [1 3 5])

true

(some identity [nil false 1 nil 2])

1

(not-every? even? (whole-numbers))

true

(not-any? even? (take 10 (whole-numbers)))

false

シーケンスを変換する関数

各リストに関数を適用する。

(map #(format "<p>%s</p>" %) ["the" "quick" "brown" "fox"])
<p>the</p> <p>quick</p> <p>brown</p> <p>fox</p>

シーケンスの中身をまとめ上げる。

(reduce + (range 1 11))

55

(reduce * (range 1 11))

3628800

(sort [42 1 7 11])
1 7 11 42
(sort-by #(.toString %) [42 1 7 11])
1 11 42 7

ソートの順番を変えられる。

(sort > [42 1 7 11])
(sort < [42 1 7 11])
(42 11 7 1)
(1 7 11 42)

リスト内包表記バージョン。

(for [word ["the" "quick" "brown" "fox"]]
  (format "<p>%s</p>" word))
<p>the</p> <p>quick</p> <p>brown</p> <p>fox</p>

:when 節を使うと filter をエミュレートできる。

(take 10 (for [n (whole-numbers) :when (even? n)] n))
2 4 6 8 10 12 14 16 18 20

1番右側の束縛を最初に繰り返し、1度繰り返すたびにその左側の操作を1つ進める。 なのでrankの繰り返しが先に行われる。

(for [file "ABCDEFGH" rank (range 1 9)] (format "%c%d" file rank))
A1 A2 A3 A4 A5 A6 A7 A8 B1 B2 B3 B4 B5 B6 B7 B8 C1 C2 C3 C4 C5 C6 C7 C8 D1 D2 D3 D4 D5 D6 D7 D8 E1 E2 E3 E4 E5 E6 E7 E8 F1 F2 F3 F4 F5 F6 F7 F8 G1 G2 G3 G4 G5 G6 G7 G8 H1 H2 H3 H4 H5 H6 H7 H8

遅延シーケンスと無限シーケンス

リストは必要なときに作られる。

(use 'examples.primes)
(def ordinals-and-primes (map vector (iterate inc 1) primes))
(take 5 (drop 1000 ordinals-and-primes))
#’examples.primes/ordinals-and-primes
([1001 7927] [1002 7933] [1003 7937] [1004 7949] [1005 7951])

遅延なので、副作用が動かないように見える。

(def x (for [i (range 1 3)] (do (println i) i)))
x ;; 標準入力に出ない
#’user/x
(1 2)

シーケンスの要素をすべて計算する。

(doall x)
1 2
(def x (for [i (range 1 3)] (do (println i) i)))
x
#’user/x
(1 2)

シーカブル

シーケンス関数に渡されると、Javaのコレクションは自動的にシーケンスとして振る舞う。 シーケンスとして振る舞えるコレクションをシーカブルであるという。

配列はシーカブル。

(first (.getBytes "hello"))
(rest (.getBytes "hello"))
(cons (int \h) (.getBytes "ello"))
104
(101 108 108 111)
(104 101 108 108 111)

文字列もシーカブル。

(first "Hello")
(rest "Hello")
(cons \H "ello")
\H
(\e \l \l \o)
(\H \e \l \l \o)

逆にして、戻す。

(reverse "hello")
(apply str (reverse "hello"))
(\o \l \l \e \h)
“olleh”

Javaのコレクションを使うのは、JavaのAPIを扱うときだけ(Clojure組み込みのコレクションの方が便利)。

正規表現

マッチした文字列からなる変更不可なシーケンスを作り出す。 シーケンスライブラリの関数群がただで正規表現にも使えるようになる。

(re-seq #"\w+" "the quick brown fox")
(sort (re-seq #"\w+" "the quick brown fox"))
(drop 2 (re-seq #"\w+" "the quick brown fox"))
(map #(.toUpperCase %) (re-seq #"\w+" "the quick brown fox"))
(“the” “quick” “brown” “fox”)
(“brown” “fox” “quick” “the”)
(“brown” “fox”)
(“THE” “QUICK” “BROWN” “FOX”)
(import '(java.io File))
(map #(.getName %) (.listFiles (File. "./public/css")))
java.io.File
(“site.css” “code.css”)

ディレクトリを深さ優先で辿る。

(count (file-seq (File. "./public")))

101

最近更新されたファイルだけを調べる。

(defn minutes-to-millis [mins]
  (* mins 1000 60))
(defn recently-modified? [file]
  (> (.lastModified file)
     (- (System/currentTimeMillis) (minutes-to-millis 30))))
(filter recently-modified? (file-seq (File. ".")))
#’user/minutes-to-millis
#’user/recently-modified?
(#object[java.io.File 0x6bf2183f “./20210926143813-clojure.org”] #object[java.io.File 0x70ca1df7 “./.git”])

読み込む(readerをオープンしたまま)。

(use '[clojure.java.io :only (reader)])
(take 2 (line-seq (reader "public/index.html")))
<!DOCTYPE html> <html lang=“en”>

リーダーをちゃんと閉じる。

(with-open [rdr (reader "./public/index.html")]
  (count (line-seq rdr)))

107

空行を除いた行数。

(with-open [rdr (reader "./public/index.html")]
  (count (filter #(re-find #"\S" %) (line-seq rdr))))

98

orgコードの行数を数え上げる。

(use '[clojure.java.io :only (reader)])
(defn non-blank? [line] (if (re-find #"\S" line) true false))
(defn non-svn? [file] (not (.contains (.toString file) ".svn")))
(defn org-source? [file] (.endsWith (.toString file) ".org"))
(defn org-loc [base-file]
  (reduce
   +
   (for [file (file-seq base-file)
         :when (and (org-source? file) (non-svn? file))]
     (with-open [rdr (reader file)]
       (count (filter non-blank? (line-seq rdr)))))))
(org-loc (java.io.File. "./"))
#’user/non-blank?
#’user/non-svn?
#’user/org-source?
#’user/org-loc
12299

特定の構造に特化した関数

シーケンス関数を使うと汎用性の高いコードが書ける。 リスト、ベクタ、マップ、セットに特化した関数もある。

(peek '(1 2 3))
(pop '(1 2 3))
1
(2 3)
(get [:a :b :c] 1)
(get [:a :b :c] 5) ;; nil

:b

指定のインデックスに新しい値を入れる。

(assoc [0 1 2 3 4] 2 :two)
(subvec [1 2 3 4 5] 3)
(take 2 (drop 3 [1 2 3 4 5]))
[0 1 :two 3 4]
[4 5]
(4 5)

特定の構造向けの関数がある場合、それは性能のためであることがほとんど。

(keys {:sundance "spaniel", :darwin "beagle"})
(vals {:sundance "spaniel", :darwin "beagle"})
(:sundance :darwin)
(“spaniel” “beagle”)
(get {:sundance "spaniel", :darwin "beagle"} :darwin)
({:sundance "spaniel", :darwin "beagle"} :darwin)
(:darwin {:sundance "spaniel", :darwin "beagle"})
“beagle”
“beagle”
“beagle”

キーとして持っていれば値に関わらずtrueを返す。

(def score {:stu nil :joey 100})
(contains? score :stu)
#’user/score
true
(def song {:name "Agnus Dei"
           :artist "Kryzysztof Penderecki"
           :album "Polish Requiem"
           :genre "Classical"})

song
(assoc song :kind "MPEG Audio File")
(dissoc song :genre)
(select-keys song [:name :artist])
(merge song {:size 8118166, :time 507245})
#’user/song
{:name “Agnus Dei”, :artist “Kryzysztof Penderecki”, :album “Polish Requiem”, :genre “Classical”}
{:name “Agnus Dei”, :artist “Kryzysztof Penderecki”, :album “Polish Requiem”, :genre “Classical”, :kind “MPEG Audio File”}
{:name “Agnus Dei”, :artist “Kryzysztof Penderecki”, :album “Polish Requiem”}
{:name “Agnus Dei”, :artist “Kryzysztof Penderecki”}
{:name “Agnus Dei”, :artist “Kryzysztof Penderecki”, :album “Polish Requiem”, :genre “Classical”, :size 8118166, :time 507245}

同じキーを持っていた場合、どうやって値を組み合わせるかを指定する関数を与える。

(merge-with
 concat
 {:rubble ["Barney"], :flintstone ["Fred"]}
 {:rubble ["Betty"], :flintstone ["Wilma"]}
 {:rubble ["Bam-Bam"], :flintstone ["Pebbles"]})
:rubble (Barney Betty Bam-Bam) :flintstone (Fred Wilma Pebbles)

セットを扱う関数

(use 'clojure.set)
(def languages #{"java" "c" "clojure"})
(def beverages #{"java" "chai" "pop"})
#’user/languages
#’user/beverages

与えられたセットの少なくとも片方にある要素を集める。

(union languages beverages)

#{“clojure” “pop” “java” “chai” “c”}

最初のセットに含まれ、しかし2番めのセットには含まれないような要素を集めたセット。

(difference languages beverages)

#{“clojure” “c”}

言語の名前でもあり、かつ飲み物の名前でもあるようなもの。

(intersection languages beverages)

#{“java”}

1文字だけの言語。

(select #(= 1 (.length %)) languages)

#{“c”}

関係演算はSQLなどの問い合わせ言語の基礎となっている。

関係演算 データベース Clojureの型システム
関係 テーブル セットとして動作するものすべて
タプル マップとして動作するものすべて
(def compositions
  #{{:name "The Art of the Fugue" :composer "J. S. Bach"}
    {:name "Musical Offering" :composer "J. S. Bach"}
    {:name "Requiem" :composer "Giuseppe Verdi"}
    {:name "Requiem" :composer "W. A. Mozart"}})
(def composer
  #{{:composer "J. S. Bach" :country "Germany"}
    {:composer "W. A. Mozart" :country :Austria}
    {:composer "Giuseppe Verdi" :country "Italy"}})
(def nations
  #{{:nation "Germany" :language "German"}
    {:nation "Austria" :language "German"}
    {:nation "Italy" :language "Italian"}})
#’user/compositions
#’user/composer
#’user/nations
(rename compositions {:name :title})

#{{:composer “Giuseppe Verdi”, :title “Requiem”} {:composer “W. A. Mozart”, :title “Requiem”} {:composer “J. S. Bach”, :title “The Art of the Fugue”} {:composer “J. S. Bach”, :title “Musical Offering”}}

SQL SELECT文に該当する抜き出し。

(project compositions [:name])

#{{:name “The Art of the Fugue”} {:name “Musical Offering”} {:name “Requiem”}}

Tasks

TODO プログラミングClojure

  • 37, 39, 44, 56, 67, 74, 81

Reference

Simple Made Easy

clojure開発者リッチ・ヒッキーのプレゼン。

Clojureと「Simple Made Easy」 - 紙箱

リッチ・ヒッキーのプレゼンの解説。 簡単とシンプルさを分ける。抽象化によってシンプルさを保つ。

stuarthalloway/programming-clojure: Sample code for the book

clojureの本のサンプルコード。

「名詞の王国での実行」Stevey’s Blog Rants: Execution in the Kingdom of Nouns

オブジェクト指向では名詞が重要な地位を占めている。

Clojureをつくったわけ

clojureの特徴がわかる。

Archives