読者です 読者をやめる 読者になる 読者になる

Clojure - Functional Programming for the JVM を読んでいくよ

Clojure - Functional Programming for the JVM

http://java.ociweb.com/mark/clojure/article.html

自分が読みたいところしか訳さないです。

なんでもいいんだけどLisper、Java嫌いすぎだろ。草生えるわ。

そんなLisperの大嫌いなJavaVM上で動くClojureとか倒錯しすぎだろ。ツンデレか。。。

Functional Programming

Functional programming is a style of programming that emphasizes "first-class" functions that are "pure". It was inspired by ideas from the lambda calculus.

関数型プログラミングは関数が第一オブジェクトであり、かつ純粋であることを強調するよ。ラムダ計算に影響受けてるよ。

"Pure functions" are functions that always return the same result when passed the same arguments, as opposed to depending on state that can change with time.

「純粋な関数」とは同じ引数をとったら、いつも同じ結果を返すということだよ、タイミングによって変えられるような状態に依存しないかたちでね。

This makes them much easier to understand, debug and test.

この性質によって理解とデバッグとテストが簡単になるよ

They have no side effects such as changing global state or performing any kind of I/O, including file I/O and database updates.

グローバルな状態や、入出力(ファイルとかDBとか)に対して、副作用がないってことだよ

State is maintained in the values of function parameters saved on the stack (often placed there by recursive calls) rather than in global variables saved on the heap.

状態、は関数の値としてスタックに保存されるよ 主にそれは再帰呼び出しだよ ヒープには保存しなくてよいんだよ

This allows functions to be executed repeatedly without affecting global state (an important characteristic to consider when transactions are discussed later).

この特徴は関数の実行を何度もできるグローバルなStateに依存しないでね

It also opens the door for smart compilers to improve performance by automatically reordering and parallelizing code, although the latter is not yet common.

それによって、コンパイラが自動的に並列実行コードとしてパフォーマンス最適化してくれるからさ。そんなすぐできるもんでもないんだけど。

Data in functional programming languages is typically immutable.

関数型プログラミングは一般的に、イミュータブル。

This allows data to be accessed concurrently from multiple threads without locking. There's no need to lock data that can't be changed.

これによって、データロックなしに、マルチスレッドによる、データへの並行的なアクセスを可能にするよ。 データは変えられない(イミュータブル)だから、ロックする必要なんてないんだ。

With multicore processors becoming prevalent, this simplification of programming for concurrency is perhaps the biggest benefit of functional programming.

並列プログラミングに関する単純で、でも最も関数プログラミングの恩恵でもあるこの特徴によって、マルチコアプロセスを利用したプログラミングがもっと一般的になっていくよね。

Clojure Overview

Clojure is a dynamically-typed, functional language that runs on the JVM and provides interopareability with Java.

Clojureは、

  • 動的型付けで
  • 関数型で
  • JVM上で動いて、
  • Javaとの相互利用性を持った

言語だよ。

A major goal of the language is to make it easier to implement applications that access data from multiple threads(concurrency)

この言語の大きな目標は、並行性、並列性に関して簡単にすること。

Clojure is pronounced that same as the word "closure". Clojure は クロージャ って読んでね

the creator of the language, Rick Hickey explains the name this way :"I wanted to involve C(C#),L(Lisp), andJ(Java). Once Icame up with Clojure, given the punon clocure, the acailable domains and vast enptiness of the google space, it was an easy decision."

言語開発者であるRick Hickeyはこう言ってる。 「僕は、C(C#),L(Lisp), and J(Java)を含むような単語にしたかったんだ。punon clocureという言葉から一度Clojureという名前を思いついたら、ググラビリティも良かったし、ソッコー決めたよね。」

Clojure is also available for the .NET platform. ClojureCLR is an implementation of Clojure that runs on the Microsoft Common Language Runtime instead of the JVM. See https://github.com/clojure/clojure-clr.

Clojureは.NETでも動くよ。

In July 2011, ClojureScript was announced. It compiles Clojure code to JavaScript. See https://github.com/clojure/clojurescript.

ClojureScriptっていうAltJS的なやつもあるよ。

Clojure is an open source language released under the Eclipse Public License v 1.0 (EPL). This is a very liberal license. See http://www.eclipse.org/legal/eplfaq.php for more information.

ClojureEclipse Public Licence v1.0ですよ。

Running on the JVM provides portability, stability, performance and security. It also provides access to a wealth of existing Java libraries supporting functionality including file I/O, multithreading, database access, GUIs, web applications, and much more.

JVM上で動くってことは、

  • 環境移植性
  • 安定性
  • パフォーマンス
  • セキュリティー

を提供できるってことや。 そして、幸いな事にそれは、既存のJavaのライブラリの機能、file I/O, マルチスレッディング、データベースアクセス、GUIライブラリ、webアプリケーション、とか、色々にアクセスできるってことももたらしてくれてるっちゅうわけや。

Each "operation" in Clojure is implemented as either a function, macro or special form. Nearly all functions and macros are implemented in Clojure source code. The differences between functions and macros are explained later.

Clojureにおけるそれぞれの操作は、関数、マクロ、特殊形式として実装されるやで。 ほとんど全ての関数とマクロは、Clojureのソースとして実装されるもの。 マクロと関数の違いについてはあとで説明するやで。

Special forms are recognized by the Clojure compiler and not implemented in Clojure source code.

特殊形式は、クロージャソースコードとしては実装されないもので、Clojureコンパイラが認識するものなんや。

There are a relatively small number of special forms and new ones cannot be implemented. They include catch, def, do, dot ('.'), finally, fn, if, let, loop, monitor-enter, monitor-exit, new, quote, recur, set!, throw, try and var.

少数の特殊形式があって、特殊形式は新しく作ることができない。 例えば、catch, def, do, dot ('.'), finally, fn, if, let, loop, monitor-enter, monitor-exit, new, quote, recur, set!, throw, try and varみたいなものがそうだ。

Clojure provides many functions that make it easy to operate on "sequences" which are logical views of collections. Many things can be treated as sequences.

Clojureは、コレクションの論理的な見方で構成された、"sequence"というものにおいて簡単に操作できる沢山の関数を提供している。 多くのものはsequenceとして扱われる。

These include Java collections, Clojure-specific collections, strings, streams, directory structures and XML trees. New instances of Clojure collections can be created from existing ones in an efficient manner because they are persistent data structures.

それは、Javaのコレクション型、Clojure-specificなコレクション型、文字列、ストリーム、ディレクトリ構造、XMLツリーなんかを含む。 堅牢なデータ型であるかどうか、という効果的な決まり事に従って、Clojureの新しいコレクション型は作ることができる。

Clojure provides three ways of safely sharing mutable data, all of which use mutable references to immutable data.

Clojure は全てのイミュータブルなデータのミュータブルな参照に関して、安全な3つの方法を提供している。

Refs provide synchronous access to multiple pieces of shared data ("coordinated") by using Software Transactional Memory (STM).

「レフ(Ref)」は、データのいくつかの集まりに同期的にアクセスする方法を、ソフトウェアトランザクションメモリを用いて提供する。

Atoms provide synchronous access to a single piece of shared data.

「アトム」はひとつのシェアされたデータに同期的にアクセスする方法として提供される。

Agents provide asynchronous access to a single piece of shared data.

「エージェント」は、ひとつのシェアされたデータに非同期的にアクセスする方法として提供される。

These are discussed in more detail in the "Reference Types" section.

これらについては、より詳しくは "Reference Types" の項で触れる。

Clojure is a Lisp dialect. However, it makes some departures from older Lisps. For example, older Lisps use the car function to get the first item in a list. Clojure calls this first as does Common Lisp. For a list of other differences, see http://clojure.org/lisps.

ClojureLispの方言だよ。 だけど、よく知られたLisp表現から発展しているものもいくつかある。 たとえば、よく知られたLispでいうところのcarは、リストの一番初めの要素を取ってくる関数だ。 Clojureでは、firstというキーワードでそのCommon Lispの機能を表現する。
他の違いについてのリストは、これ.をみてね。

Lisp has a syntax that many people love ... and many people hate, mainly due to its use of parentheses and prefix notation. If you tend toward the latter camp, consider these facts.

Lispシンタックスは、多くの人に愛され,,,,多くの人に憎まれている。それは多くのところは、カッコの多用と、前置記法によるところが大きい。 もしあなたがその主張を推進する陣営なのだとしたら、現実について少し考慮しよう。

Many text editors and IDEs highlight matching parentheses, so it isn't necessary to count them in order to ensure they are balanced.

多くのテキストエディタIDEでは、カッコの自動補完をしてくれるから、カッコがきちんと閉じているかどうかいちいち数える必要というのはない。

Clojure function calls are less noisy than Java method calls. A Java method call looks like this:

Clojureの関数はJavaメソッドコールに比べて簡潔だ。 Javaメソッドコールはこんなかんじ。

methodName(arg1, arg2, arg3);

A Clojure function call looks like this:

クロージャだとこうなる。

(function-name arg1 arg2 arg3)

The open paren moves to the front and the commas and semicolon disappear. This syntax is referred to as a "form". There is simple beauty in the fact that everything in Lisp has this form. Note that the naming convention in Clojure is to use all lowercase with hyphens separating words in multi-word names, unlike the Java convention of using camelcase.

カッコのはじまりが、先頭に動き、コンマとセミコロンが消え去った!!!!!!!!!! このシンタックスは”フォーム”って呼ばれるよ。 全てのLispはこのフォームで動くよね、っていう事実は、簡潔な美しさを生む。 Clojureでの命名規則Javaのキャメルケースとちがって、全ての名前を小文字で書いて、ハイフンで分ける、っていうかんじ。

Defining functions is similarly less noisy in Clojure. The Clojure println function adds a space between the output from each of its arguments. To avoid this, pass the same arguments to the str function and pass its result to println.

関数定義も同様にClojureのほうが簡潔。 Clojureprintln関数は、出力したい項の間にそれぞれスペースを入れるだけでよい。 これを排除することによって、同じ項を持つ出力関数はprintlnをとおる

// Java
public void hello(String name) {
    System.out.println("Hello, " + name);
}
; Clojure
(defn hello [name]
  (println "Hello," name))

Clojure makes heavy use of lazy evaluation. This allows functions to be invoked only when their result is needed. "Lazy sequences" are collections of results that are not computed until needed. This supports the efficient creation of infinite collections.

Clojrueは遅延評価を多用する。 これはその値が必要になった時にその関数が実行するのを許す、ということだ。 "遅延 sequence"は必要になるまで計算されないものの集まりだ。 これは無限コレクションみたいのを作るのを容易にするよ。

Clojure code is processed in three phases: read-time, compile-time and run-time. At read-time the Reader reads source code and converts it to a data structure, mostly a list of lists of lists. At compile-time this data structure is converted to Java bytecode. At run-time the bytecode is executed. Functions are only invoked at run-time. Macros are special constructs whose invocation looks similar to that of functions, but are expanded into new Clojure code at compile-time.

Clojureのコードは3つの段階を経て実行される。

読み取り時というのは、Clojureのリーダがソースコードをよみ、リストのリストのリストというデータ構造に変換するときのことだ。 コンパイル時というのは、このデータ構造をJavaバイトコードに変換するときのこと。 ランタイム、というのは言わずもがな、実行じのことだ。 関数は、ランタイムでのみ実行される。 マクロは、一見関数と同じように実行されるように見えるが、コンパイル時に新しくClojureのコードとして展開される、特別な構造を持ったものだ。

Is Clojure code hard to understand? Imagine if every time you read Java source code and encountered syntax elements like if statements, for loops, and anonymous classes, you had to pause and puzzle over what they mean.

Clojureのコードを理解するのが難しいって? ステートメントコード、forループ、よくわかんないクラス、みたいな、Javaソースコードを読んでる時に遭遇する構文要素のことを想像してみなよ。 あなたは、一旦立ち止まり、それらがなにを意味しているのかいちいち考えなきゃいけないでしょ。

There are certain things that must be obvious to a person who wants to be a productive Java developer. Likewise there are parts of Clojure syntax that must be obvious for one to efficiently read and understand code. Examples include being comfortable with the use of let, apply, map, filter, reduce and anonymous functions ... all of which are described later.

それは生産的でありたいJavaの開発者にとって、深刻な問題であることは明白だよね。 Clojureシンタックスも同様に考えなきゃいけないけど、それが寄り効果的に読み進めることができて、コードの意味を理解しやすいことは明白さ。 let, apply, map, filter, reduce, その他の関数...これらがどんなに快適なものなのか、っていうことの実例は、これから説明していくよん!