Clojure - Functional Programming for the JVM 続き(1)

シンタックスのところとか、試しながらやってるので、あってるかどうか知りません。

Getting Started ~Clojureをはじめよう〜

Clojure code for your own library and application projects will typically reside in its own directory (named after the project) and will be managed by the Leiningen project management tool. Leiningen (or "lein" for short) will take care of downloading Clojure for you and making it available to your projects. To start using Clojure, you don't need to install Clojure, nor deal with jar files or the java command — just install and use lein (instructions on the Leiningen homepage, linked to above).

あなたのライブラリなり、アプリケーションなり、Clojureソースコードは、プロジェクト名のついたディレクトリに格納される。また、Leiningenというプロジェクト管理ツールで管理されるよ。 Leiningen(または単にLein)はClojure処理系のダウンロード、プロジェクトごとに使えるものはどれか、ということをやってくれる。 Clojureを使いはじめるには、Clojure処理系を直接インストールしてくるとか、jarファイルを扱ったり、javaコマンドを打ったりする必要はないよ。ただ、Leinを使えばよいのである。

Once you've installed lein, create a trivial project to start playing around with:

Leinをインストールしたら、簡単なプロジェクトをつくってみよう。

cd ~/temp
lein new my-proj
cd my-proj
lein repl # starts up the interactive REPL

To create a new application project, do "lein new app my-app" For more about getting started, see http://dev.clojure.org/display/doc/Getting+Started.

新しくプロジェクトを作る際には、lein new app my-appとやればいいよ。 くわしくはこっちみてね

Clojure Syntax

Lisp dialects have a very simple, some would say beautiful, syntax. Data and code have the same representation, lists of lists that can be represented in memory quite naturally as a tree. (a b c) is a call to a function named a with arguments b and c. To make this data instead of code, the list needs to be quoted. '(a b c) or (quote (a b c)) is a list of the values a, b and c. That's it except for some special cases. The number of special cases there are depends on the dialect.

Lispの言い回しはとてもシンプルで、美しいとさえ言われるほど。 データとコードは同じ表現で、リストのリストはメモリの表現としても、単純なツリー構造だ。 (a b c)aという関数をbcという引数を伴って呼んでるっちゅうこと。 コードとしてではなく、データとしていまのを表現したいときは、クォートが必要だよ。 '(a b c)(quote (a b c))みたいに書いてね。こうすると、a,b,cという3つの値を持ったリストになるよ。

そうではない、特別な場合もあるから、注意しよう。 特別な場合っていうのは、Clojureの方言に依存するところだよ。

The special cases are seen by some as syntactic sugar. The more of them there are, the shorter certain kinds of code become and the more readers of the code have to learn and remember. It's a tricky balance. Many of them have an equivalent function name that can be used instead. I'll leave it to you to decide if Clojure has too much or too little syntactic sugar.

特別な場合っていうのは、糖衣構文として存在するよ。 それらのほとんどの場合っていうのは、よりコードを短く、コードを読む側の人間が理解しやすく、覚えやすいようになっているよ。 それは結構バランスの難しい問題だ。 糖衣構文によって短くするような構文の大多数は、代わりに使える他の関数が存在している。 そのシンタックスシュガーが良いものか、悪いものかの決断の余地を、ユーザに残しておくよ☆

The table below briefly describes each of the special cases encountered in Clojure code. These will be described in more detail later. Don't try to understand everything in the table now.

はい、基本的な特殊なシンタックスをみてきます。

--

  • ○ Purpose(目的)
  • ■ Suger(糖衣構文)
  • □ Function(関数本体)

--

  • ○ 一行コメント
  • ; text
  • (comment text)

--

  • ○ charリテラル
  • \char \tab \newline \space\unicode-hex-value
  • (char ascii-code) (char \uunicode)

--

  • ○string
  • "text"
  • (str char1 char2 ..)

--

  • ○ キーワード、埋め込み文字列?、同じオブジェクトを参照する同じ名前のキーワード、マップオブジェクトのキーとしてよく使われる
  • :name
  • (keyword "name")

--

  • ○ 対象の名前空間でかいけつされる名前
  • ::name
  • □ 対応する関数なし

  • 正規表現

  • #"pattern" 関数を使う時とクォートのルールが違う
  • (re-pattern pattern)

--

  • ○ ホワイトスペース。可読性向上のためにコレクションなどで使う
  • ,, (a comma)
  • □ 概念として存在しない

--

  • ○ リスト構文 [CLとおなじ]
  • '(items) 要素を評価しない
  • (list items) 要素を評価する

--

  • vector 配列に似ている
  • [items]
  • (vector items)

--

  • ○ set 集合
  • #{items} ハッシュ集合の生成
  • (hash-set items) (sorted-set items)

--

  • ○ map 連想配列
  • {key-value-pairs}
  • (hash-map key-value-pairs) (sorted-map key-value-pairs)

--

  • ○ シンボルやコレクションにメタデータを付加する
  • ^{key-value-pairs} object 読み取り時プロセス
  • (with-meta object metadata-map) ランタイムプロセス

--

  • ○ シンボルやコレクションからメタデータをマップとして取り出す
  • (meta object)

--

  • ○ 関数の引数の数だけ云々。よくわからんちん
  • gather a variable number of arguments in a function parameter list
  • ■ & name
  • □ N/A

--

  • ○ conventional name given to function parameters that aren't used
  • ■  _ (an underscore)
  • □ N/A

--

  • ○ construct a Java object; note the period after the class name
  • (class-name. args)
  • (new class-name args)

--

  • Javaメソッドを呼ぶ
  • ■ (. class-or-instance method-name args)or(.method-name class-or-instance args)
  • □ なし

--

  • ○ いくつかのJavaメソッドを、それぞれの項の要素の結果を、次の要素のはじめの引数としてマルチスレッディングで実行する?どのメソッドもカッコの中にいろいろ追加できる。..のいちに。(よくわかんない)
  • ■ (.. class-or-object (method1 args) (method2 args) ...)
  • □ none

--

  • ○ create an anonymous function
  • ■ #(single-expression) use % (same as %1), %1, %2 and so on for arguments
  • (fn [arg-names] expressions)

--

  • ○ 「レフ」「アトム」「エージェント」の参照
  • ■ @ref
  • □ (deref ref)

--

  • ○ シンボルの値のかわりに、Varオブジェクトを得る
  • #'name
  • (var name)

--

  • ○ バッククォート
  • ■ `
  • □ none

--

  • ○ アンクォート
  • ■ ~value
  • □ (unquote value)

--

--

  • ○ シンボルの自動作成
  • ■ prefix#
  • □ (gensym prefix?)

--

Lisp dialects use prefix notation rather than the typical infix notation used by most programming languages for binary operators such as + and *. For example, in Java one might write a + b + c, whereas in a Lisp dialect this becomes (+ a b c). One benefit of this notation is that any number of arguments can be specified without repeating the operator. Binary operators from other languages are Lisp functions that aren't restricted to two operands.

Lispの書き方では二項演算子について、ほとんどのプログラミング言語で見られる典型的な中置記法の代わりに、前置記法を使います。 例えば、Javaだとa + b + cと書かなければならないところを、Lispなら、(+ a b c)と書けます。 この記法の利点のひとつは、値の数が多くなっても、演算子をいちいち取り替えなくてすむことです。 他のプログラミング言語での二項演算子では2つしか置くことのできない演算子でも、Lispなら2つに縛られることはないのです!

One reason Lisp code contains more parentheses than code in other languages is that it also uses them where languages like Java use curly braces. For example, the statements in a Java method are inside curly braces, whereas the expressions in a Lisp function are inside the function definition which is surrounded by parentheses.

Lispが他の言語に比べて、沢山のカッコを用いいる理由のうちのひとつは、Javaのような言語で波括弧として使われているところでも丸括弧を使うからです。 例えば、Javaステートメントはブレースの中にありますが、Lispの場合はカッコのなか?

Compare the following snippets of Java and Clojure code that each define a simple function and invoke it. The output from both is "edray" and "orangeay".

ClojureJavaの2つの簡単な関数、処理のコードスニペットを見てくだせ。 どっちもアウトプットは、"edray"と"orangeay".


// This is Java code.
public class PigLatin {

    public static String pigLatin(String word) {
        char firstLetter = word.charAt(0);
        if ("aeiou".indexOf(firstLetter) != -1) return word + "ay";
        return word.substring(1) + firstLetter + "ay";
    }

    public static void main(String args[]) {
        System.out.println(pigLatin("red"));
        System.out.println(pigLatin("orange"));
    }
}
; This is Clojure code.
; When a set is used as a function, it returns the argument if it is
; in the set and nil otherwise.  When used in a boolean context,
; that indicates whether the argument is in the set.
(def vowel? (set "aeiou"))

(defn pig-latin [word] ; defines a function
  ; word is expected to be a string
  ; which can be treated like a sequence of characters.
  (let [first-letter (first word)] ; assigns a local binding
    (if (vowel? first-letter)
      (str word "ay") ; then part of if
      (str (subs word 1) first-letter "ay")))) ; else part of if

(println (pig-latin "red"))
(println (pig-latin "orange"))

Clojure supports all the common data types such as booleans (with literal values of true and false), integers, decimals, characters (see "character literal" in the table above) and strings. It also supports ratios which retain a numerator and denominator so numeric precision is not lost when they are used in calculations.

Clojureも、Javaが持っているようなboolとかintegerとかのデータ型を持っているよ。 分数云々だから計算によってあれして値がシカトされることもないよ。

Symbols are used to name things. These names are scoped in a namespace, either one that is specified or the default namespace. Symbols evaluate to their value. To access the Symbol object itself, it must be quoted.

シンボルはものに名付ける、ということに使われるよ。それらの名前は、指定した、またはデフォルトの名前空間の中にスコープをもつよ。 シンボルはその値に評価されるよ。シンボル、というデータそのものにアクセスしたいときは、クォートしなきゃだめや。

Keywords begin with a colon and are used as unique identifiers. Examples include keys in maps and enumerated values (such as :red, :green and :blue).

キーワードっていうのは、コロンから始まり、唯一のものじゃなきゃならん。 たとえば、マップのキーとか、列挙された値として使うよ。

It is possible in Clojure, as it is in any programming language, to write code that is difficult to understand. Following a few guidelines can make a big difference. Write short, well-focused functions to make them easier to read, test and reuse. Use the "extract method" refactoring pattern often. Deeply nested function calls can be hard to read. Limit this nesting where possible, often by using let to break complicated expressions into several less complicated expressions. Passing anonymous functions to named functions is common. However, avoid passing anonymous functions to other anonymous functions because such code is difficult to read.

Clojureであっても、他の言語と同様に、理解不能なわかりにくいコードを書くことはできる。 しかし、いくつかのガイドラインに従って書いていくことで、イイカンジにできるよ。 短く記述し、よく機能にフォーカスされた関数はそれを解読すること、テストすること、再利用することを簡単にするよね! ネストされまくったコードは読みづれえよ。 深いネストってのは大体いつも制御することが可能で、複雑な表現は、いくつかのもう少し複雑さが減少した表現に砕くことができる。 無名関数を有名関数にすることはよくあるテクニック しかしながら、無名関数をべつの無名関数に与えることは、チョー読みづらくなるから気をつけろ。