(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 は、同じ貢献者契約と開発プロセスを共有しています。