(ns my.namespace
(:require-macros [my.macros :as my]))
以下は、https://clojure.dokyumento.jp/about と https://clojure.dokyumento.jp/reference の左側のナビゲーションパネルにあるセクションをセクションごとにレビューし、ClojureScriptで何が異なり、場合によっては類似点についても列挙しています。
ClojureScriptの理論的根拠は、プラットフォームとしての役割をJavaScriptが担っていることを除けば、Clojureとほぼ同じです。また、JSのリーチが明らかにプラットフォームほど豊富ではないため、JSのリーチにも重点が置かれています。
ClojureScriptの理論的根拠に関するより深い議論は、このサイトの別の場所にあります。
Clojureと同様に、ClojureScriptはREPL駆動開発をサポートしており、さまざまなJavaScript環境で簡単に起動できるREPLを提供しています。詳細はクイックスタートを参照してください。
さらに、ClojureScriptのセルフホスティング機能は、サードパーティのREPLやその他の動的機能を作成できる純粋なJavaScript環境に動的な性質を拡張することをサポートしています。
Clojureの値、状態、同一性、時間のモデルは、シングルスレッド環境でも貴重です。
アトムはClojureと同じように動作します
RefsとSTMはありません
bindingのユーザーエクスペリエンスはClojureと似ています
Vars
実行時には具象化されません
具象化の多くの開発時の用途は、アナライザーを介したClojureデータ構造へのアクセスによって不要になります
defは通常のJS変数を生成します
エージェントは現在実装されていません
ClojureScriptはJavaScript VM上でホストされています
オプションで、最適化のためにGoogleのClosureコンパイラを使用できます
GoogleのClosureライブラリを活用するように設計されており、その依存関係/require/provideメカニズムに参加します
クイックスタートを参照してください
数値
ClojureScriptは現在、JavaScriptプリミティブにマップする整数と浮動小数点リテラルのみをサポートしています
Ratio、BigDecimal、BigIntegerリテラルは現在サポートされていません
数値の等価性は、ClojureではなくJavaScriptのように機能します。 (= 0.0 0) ⇒ true
文字
ClojureScriptには文字リテラルがありません。代わりに、文字はJavaScriptと同じです(つまり、単一文字の文字列です)
リスト、ベクター、マップ、およびセットリテラルはClojureと同じです
マクロ文字
ClojureScriptには文字型がないため、\は単一文字の文字列を生成します。
read
read関数とread-string関数は、cljs.reader名前空間にあります
タグ付きリテラル
Clojureタグ付きリテラルと同じですが、コンパイルステージで使用されるリーダー関数はClojurescriptマクロに似ており、Clojurescriptコードフォーム(または文字列や数値などのリテラル)を返す必要があります。
Clojureコンパイラは、data_readers.clj/cで参照されるリーダー関数を自動的に必要としませんが、Clojurescriptコンパイラは必要とします。
詳細はリーダーを参照してください
ClojureScript REPLの使用方法については、クイックスタートを参照してください。
標準のClojureScript REPLは、Clojureのmainパターンをサポートしています。
ClojureScriptはClojureと同じ評価規則を持っています
loadは存在しますが、REPL特殊関数としてのみ存在します
load-fileは存在しますが、REPL特殊関数としてのみ存在します
Clojureはローカルクリアを実行しますが、ClojureScriptは実行しません
次のClojureScript特殊形式は、Clojureの対応するものと同じです。if、do、let、letfn、quote、loop、recur、throw、およびtry。
varに関する注意事項
Varsは実行時には具象化されません。コンパイラがvar特殊形式に遭遇すると、**コンパイル時**メタデータを反映したVarインスタンスを発行します。(これは多くの一般的な**静的**ユースケースを満たします。)
defに関する注意事項
defは通常のJS変数を生成します
:privateメタデータはコンパイラによって強制されません
プライベート変数アクセスは分析警告をトリガーします
:constメタデータ
コンパイル時静的EDN値のインライン化を行います
caseテスト定数(^:const Varsに解決されるシンボル)がそれらの値でインライン化されるようになります
defフォームは、:def-emits-varコンパイラオプションが設定されていない限り(REPLではデフォルトでtrue)、varではなくinitフォームの値に評価されます
ifに関する注意事項
Javaのブールボックスに関するセクションは、ClojureScriptには関係ありません
fnに関する注意事項
現在、fnを呼び出す際のarityの実行時強制はありません
monitor-enter、monitor-exit、およびlockingは実装されていません
ClojureScriptのマクロは、それらが使用されるものとは異なる*コンパイルステージ*で定義する必要があります。これを達成する1つの方法は、それらを1つの名前空間で定義し、別の名前空間から使用することです。
マクロは、名前空間宣言の:require-macrosキーワードを介して参照されます
(ns my.namespace
(:require-macros [my.macros :as my]))
:require-macrosプリミティブを使用する代わりに、Sugaredやその他のnsバリアントを使用できます。詳細は以下の名前空間を参照してください。
マクロは*.cljまたは*.cljcファイルに記述され、通常のClojureScriptを使用する場合はClojureとして、ブートストラップ/セルフホストClojureScriptを使用する場合はClojureScriptとしてコンパイルされます。1つの注意点として、ClojureベースのClojureScriptマクロによって生成されるコードは、ClojureScriptの機能をターゲットにする必要があるということです。
|
ClojureScript名前空間は、異なるコンパイルステージに保持されている限り、同じ名前空間からマクロを必要とする*こと*ができます。そのため、たとえば、 |
Clojureとは異なり、ClojureScriptでは、マクロと関数は同じ名前を持つことができます(たとえば、cljs.core/+マクロとcljs.core/+関数は共存できます)。
|
「もしそうなら、どちらを取得するのですか?」と疑問に思うかもしれません。ClojureScript(Clojureとは異なり)には、相互作用しない2つの個別の名前空間を使用する2つの異なるステージがあります。マクロ展開が最初に発生するため、 |
印刷
*out*と*err*は現在実装されていません
正規表現のサポート
ClojureScriptの正規表現サポートはJavaScriptのものです
アサーション
JVM ClojureScriptでは、実行時に*assert*を動的にfalseに設定することはできません。代わりに、:elide-assertsコンパイラオプションを使用して省略を実行する必要があります。(一方、セルフホストClojureScriptでは、*assert*はClojureと同様に動作します。)
nil
Clojureでは、nilはJavaのnullと同じですが、ClojureScriptでは、nilはJavaScriptのnullとundefinedに相当します。
数値
現在、ClojureScriptの数値はJavaScriptの数値です
現在、強制する型がないため、強制は実装されていません
文字
JavaScriptには文字型がありません。Clojure文字は内部で単一文字の文字列として表されます
キーワード
ClojureScriptキーワードはidentical?であることが保証されていないため、高速な等価性テストにはkeyword-identical?を使用してください
コレクション
永続コレクションが利用可能です
Clojureの実装の移植
永続ベクター、ハッシュマップ、ハッシュセットの過渡的サポートが導入されています
ほとんどすべてのコレクション関数が実装されていますが、すべてではありません
StructMaps
ClojureScriptは、defstruct、create-struct、struct-map、struct、またはaccessorを実装していません。
defprotocol、deftype、extend-type、extend-protocolはClojureと同じように動作します
プロトコルはClojureのように具象化されておらず、ランタイムプロトコルオブジェクトはありません
一部の反射機能(satisfies?)はClojureと同じように動作します
satisfies?はマクロであり、プロトコル名を渡す必要があります
extendは現在実装されていません
specify、不変の値をプロトコルに拡張します - ラッパーのないインスタンスレベルのextend-type
ClojureScriptの名前空間は、入れ子になったJavaScriptオブジェクトとして表されるGoogle Closure名前空間にコンパイルされます。重要なことは、これは名前空間と変数が衝突する可能性があることを意味しますが、コンパイラはこれらの問題のあるケースを検出し、発生した場合に警告を発します。
現在、以下の注意事項に従ってのみnsフォームを使用する必要があります
:useの:onlyフォームを使用する必要があります
:requireは、:as、:refer、および:renameをサポートしています
:refer :allはサポートされていません
すべてのオプションをスキップできます
この場合、シンボルをlibspecとして直接使用できます
つまり、(:require lib.foo)と(:require [lib.foo])はどちらもサポートされており、同じ意味です
:renameは、参照される変数名から異なるシンボルへのマップを指定します(衝突を防ぐために使用できます)
プレフィックスリストはサポートされていません
:refer-clojure で使用できるオプションは :exclude と :rename のみです。
:import は Google Closure クラスのインポートにのみ使用できます。
ClojureScript の型とレコードは、:import ではなく、:use または :require :refer を使用して取り込む必要があります。
マクロは、それらが使用されるコンパイルステージとは異なる*コンパイルステージ*で定義する必要があります。 これを実現する1つの方法は、1つの名前空間でマクロを定義し、別の名前空間からそれらを使用することです。 マクロは、ns の :require-macros / :use-macros オプションを介して参照されます。
:require-macros と :use-macros は、:require と :use と同じ形式をサポートします。
***暗黙的なマクロのロード***: 名前空間が require または use され、その名前空間自体が自身の名前空間からマクロを require または use する場合、マクロは同じ仕様を使用して暗黙的に require または use されます。 さらに、この場合、マクロ var は :refer または :only 仕様に含めることができます。 これにより、ライブラリの使用が簡素化され、使用する名前空間が特定の var が関数かマクロかを明示的に区別する必要がなくなることがよくあります。 例:
(ns testme.core (:require [cljs.test :as test :refer [test-var deftest]]))
は、test/is が正しく解決され、test-var 関数と deftest マクロが修飾なしで使用可能になります。
***インラインマクロ指定***: 便宜上、:require には :include-macros true または :refer-macros [syms…] を指定できます。 どちらも、マクロを含む対応する Clojure ファイルを明示的にロードする形式に糖衣構文変換されます。 (これは、require されている名前空間が内部的に自身のマクロを require または use するかどうかに関係なく機能します。) 例:
(ns testme.core
(:require [foo.core :as foo :refer [foo-fn] :include-macros true]
[woz.core :as woz :refer [woz-fn] :refer-macros [apple jax]]))
は、以下の糖衣構文です。
(ns testme.core
(:require [foo.core :as foo :refer [foo-fn]]
[woz.core :as woz :refer [woz-fn]])
(:require-macros [foo.core :as foo]
[woz.core :as woz :refer [apple jax]]))
***Clojure 名前空間の自動エイリアシング***: 存在しない clojure.* 名前空間が require または use され、対応する cljs.* 名前空間が存在する場合、cljs.* 名前空間がロードされ、clojure.* 名前空間から cljs.* 名前空間へのエイリアスが自動的に確立されます。 例:
(ns testme.core (:require [clojure.test]))
は、自動的に以下に変換されます。
(ns testme.core (:require [cljs.test :as clojure.test]))
既存の Clojure ライブラリは、ClojureScript で動作するためには、ClojureScript のサブセットに準拠する必要があります。
さらに、Clojure ライブラリのマクロは、cljs.js/*load-fn* 機能を介してセルフホスト/ブートストラップされた ClojureScript で使用できるように、ClojureScript としてコンパイル可能である必要があります。
def と binding は Clojure と同様に動作します。
ただし、通常の js 変数に対してです。
Clojure は未束縛の var を表現できます。 ClojureScript では、(def x) は (nil? x) が true になることを意味します。 (この場合、(identical? nil x) は false ですが、(identical? js/undefined x) は true です。)
Clojure では、def は *var 自体* を返します。 ClojureScript では、REPL オプション :def-emits-var が設定されていない限り、def は *値* を返します(REPL のデフォルトは true です)。
アトムはClojureと同じように動作します
Refs と Agents は現在実装されていません。
バリデータは Clojure と同様に動作します。
intern は実装されていません - 再化された Vars はありません。
ホスト言語の相互運用機能(new、/、. など)は、可能な限り Clojure と同様に動作します。例:
goog/LOCALE
=> "en"
(let [sb (goog.string.StringBuffer. "hello, ")]
(.append sb "world")
(.toString sb))
=> "hello, world"
ClojureScript では、Foo/bar は常に Foo が名前空間であることを意味します。 JavaScript にはこれを判断するためのリフレクション情報がないため、Clojure で一般的な Java 静的フィールドアクセス パターンには使用できません。
特別な名前空間 js は、グローバルプロパティへのアクセスを提供します。
js/Infinity
=> Infinity
オブジェクトプロパティ(実行するのではなく値として必要な関数を含む)にアクセスするには、先頭にハイフンを使用します。
(.-NEGATIVE_INFINITY js/Number)
=> -Infinity
コンパイルは Clojure とは異なります。
すべての ClojureScript プログラムは、(オプションで最適化された)JavaScript にコンパイルされます。
個々のファイルは、出力の分析のために個々の JS ファイルにコンパイルできます。
本番コンパイルは、Google Closure コンパイラを介したプログラム全体のコンパイルです。
gen-class、gen-interface などは、ClojureScript では不要であり、実装されていません。
ClojureScript には現在、Clojure から移植された次の非コア名前空間が含まれています。
clojure.set
clojure.string
clojure.walk
clojure.zip
clojure.data
clojure.core.reducers
fold は現在 reduce のエイリアスです。
cljs.pprint (clojure.pprint の移植版)
cljs.spec (clojure.spec の移植版)
cljs.test (clojure.test の移植版)
Clojure と ClojureScript は、同じ貢献者契約と開発プロセスを共有しています。