仕様との差異
準拠は設計上部分的です。Clojure オラクル(Clojure CLI 1.12)と動作が異なる箇所は ここに列挙され、どのバックエッドでも同じです:
-
falseはnilとは別のオブジェクトです。両者とも偽なのでif/when/cond/and/or/notは同じ扱いにしますが、=とnil?は区別します。false?/true?/boolean?がそれに応じて返します。 -
println/printは部分を単一スペースでつなぎ、3 値true/false/nilをその綴りで 出力します。strは素の連結でtrue/false/""と綴ります(strの中の コレクションは、オラクルのtoString同様、文字列をクォートした可読の綴りです)。pr/prn/pr-strは 可読の系列です(文字列はクォート付きで印字、pr-strはprと同様スペース区切り)。print-str/prn-str/println-strは同じ系列を文字列で答えます。 print 系はオラクルと同様にnilを返します。 -
コレクションは Clojure 記法で印字されます(
[1 :a s]、{:a 1}、#{1}、(true false nil :k))。クオートされたシンボルはc%の後ろからマングル解除されます。nilはnilのまま(決して()にならない)で、map/set の走査順は未規定 (keys/valsと同じ)なので、1 エントリの map と 1 メンバーの set だけが決定的に 印字されます。循環を閉じる値は Scheme のwriteと同様のデータラベル (#0=(1 . #0#))で印字され、循環なしの共有は 2 度印字されます。atom は可読でない 形(#<Atom value>)、関数は#<procedure>、例外はそのtoString(clojure.lang.ExceptionInfo: m {}。オラクルは#error {...})、未束縛の var のルートは#<Unbound: #'user/x>(オラクルの#objectはハッシュを含みます)と印字されます。ストリームは種類に対応するホストクラスの#objectとして、オラクルの印字から識別ハッシュを除いた形で印字されます (#object[java.io.StringWriter "ab"]、#object[java.io.OutputStreamWriter "java.io.OutputStreamWriter"])。strも同じ形のtoStringを答えます。文字列入力ストリームはwith-in-strのclojure.lang.LineNumberingPushbackReaderで、オラクルがStringReaderの上のjava.io.PushbackReaderを答える場合も同じです。 -
*print-meta*はオラクル同様に値のメタデータを値の前に書きますが、クォートしたリストは オラクルのリーダーが付ける:line/:columnメタデータを持ちません。*print-dup*は プリンタが読まないただの値です。assertは展開される時点の*assert*を読むため、 トップレベルでリテラルにset!すると以降のassertが無効になります。関数の中のset!や計算した値へのset!では無効になりません(オラクルでは実行された時点で効きます)。 Clojure 値に対する~S/~Aは Common Lisp 記法のままです(formatは CL サーフェス)。print-method/pprintはありません。 -
マップ・セット・memoize のキーは、ベクター・リスト・マップ・セットも含めて本家と同じく
=で一致するキーを見つけます。ただし格納されるコレクションのキーは、プログラムが最初に 格納した同じ種類(ベクター・リスト・遅延 seq)の=なキーなので、メタデータと入れ子の 要素の綴りはその先のオブジェクトに従います。これらのキーは異なる値と種類ごとに1つずつ、 実行の終わりまで保持されます。セットリテラルの重複要素は綴り単位で拒否されます。=はベクター、リスト、遅延 seq を本家と同じく要素単位で比較します。nilが空リスト なので、本家がfalseを返す(= [] nil)と(= (java.util.ArrayList.) nil)はtrueに なります。=は本家と同じく左辺の Java オブジェクトにequalsで尋ねますが、渡すのは数値、文字列、 文字、true、nil、Java オブジェクトだけです。false、キーワード、シンボル、コレクションは、 同じ種類の Java のList、Map、Setを除き、どの Java オブジェクトとも=になりません。 マップとセットは Java のコレクションのキーを本家のハッシュマップ・セットと同じくそれ自身のequalsで探し、本家の小さな配列マップが使う=では探しません。(get {[1 2] :v} (java.util.ArrayList. [1 2]))はここではnil、本家では:vです。 -
seqとその上の操作、count、empty?、get、contains?、keys、valsは本家と同じく Java のIterable、Map、CharSequenceを読み、find、select-keys、reduce-kv、update-vals、update-keys、conj、merge、merge-withは Java のMapをマップとして 読みます。ただし seq は取った時点ですべて読み(本家はイテレータを遅延で辿ります)、Mapの エントリは[k v]ベクターです(本家は Java のエントリで、#object[...]と表示されます)。 -
最も大きい入力がマップである
clojure.set/unionはシグナルします。本家は他の入力の[k v]メンバーをそこへ conj します。clojure.setの結果はメタデータを持ちません。 -
マップエントリは単なる2要素のベクターなので、
map-entry?はすべての[k v]に対してtrueを返し (本家はプログラムが作ったものにfalse)、key/valはそのようなベクターを読みます。 同じ理由で(conj {} #{[1 2]})と(conj {} (seq [[1 2]]))・(merge {} (seq [[1 2]]))は{1 2}を返します(本家はClassCastException。要素は本物のエントリでなければなりません)。 キーワードはインターンされないため、find-keywordは一度も使われていない綴りにもそのキーワードを 返します(本家はnil)。 -
型述語は値の表現に従います。
nilが空リストなので、seq?・list?・coll?・sequential?・counted?は()にfalseを返します。strict な入力に対して操作が返す seq はリストなので、list?・counted?・realized?はそれにtrueを返します(本家の lazy seq や chunked seq はfalse)。チャンク化された seq はなく(chunked-seq?は常にfalse)、iterate/cycleの seq は 一度強制されてからrealized?になります。decimal とNのリテラルは通常の有理数なので、decimal?は常にfalseで、ratio?・integer?・int?はその有理数に対して答えます ((ratio? 1.5M)と(int? 2N)はtrue)。identical?は数値・文字・シンボルを値で比較し ((identical? 1000 1000)はtrue)、綴りが同じ2つのキーワードを同じオブジェクトとして扱います。 -
プログラム自身がトップレベルで定義したコア名(
(defn peek ...))は、定義より上の呼び出しも 含めてファイル全体でコアの関数を隠します(オラクルでは定義より上の呼び出しはコアに届きます)。 ローカル束縛はオラクル同様にそのスコープで隠します。 -
seq 群の空に対する
rest/nextはnilです(オラクルは()を印字)。範囲外のnthは投げずにデフォルトを返します。map/set seq の順序はテーブルの走査順です。 文字列の seq は Common Lisp 記法で印字される文字になります。lazy seq は1要素ずつ realize します(chunk 化なし)。lazy seq のstrは要素を綴ります(オラクルはclojure.lang.LazySeq@<hash>)。mapは任意個数のコレクションを取ります。 -
strict なコレクション上の
forは strict なリストを答え、forの実行時に realize されます(オラクルは消費まで待ちます)。要素がなければnilで、オラクルが()と 印字する点と異なります(rest/next/takeと同じ empty-as-nilの立場)。最初の lazy なコレクションから先はオラクル同様に lazy です。 -
condは寛容な読みを保ちます:奇数の末尾 arm はデフォルトです(Clojure はシグナル)。 コレクションリテラル上のスレッディングステップはシグナルします(ここではコレクションは 関数ではない)。 -
末尾位置で自分を名前で呼ぶ関数(
defn、名前付きfn、letfnの項目)は、recurと 同じくどのバックエンドでも定数スタックで動きます。末尾位置で互いを呼び合う関数(letfnの項目同士、defn同士)も同様です。本家はこの呼び出しごとにフレームを積むため、深い 呼び出しは本家ではスタックオーバーフローし、ここでは最後まで実行されます。 そのオーバーフローを確かめるテスト((is (thrown? StackOverflowError (tail-fibo 1000000N)))) は失敗します。 -
clojure.testはテストを定義順に実行します(本家の順序は名前空間のマップの順です)。 エラー報告は例外のtoString(実行時エラーはその report)を表示し、 スタックトレースは表示しません。位置はis式の行で、本家は例外を投げたフレームを示します。 失敗したthrown-with-msg?はコンディションのメッセージを表示し、本家は#error {...}を 表示します。ホストのスタックオーバーフロー(catch StackOverflowError、(is (thrown? StackOverflowError ...)))は、インタプリタではコンディションではないため 1 行の報告でプログラムが終了し、WASM ではトラップになります。本家と同じく捕捉するのは JVM バックエンドだけです。use-fixturesは名前を挙げて拒否します。 -
catch(とthrown?)は、ランタイムが Common Lisp のコンディションをシグナルする箇所で オラクルが投げるクラスとして実行時エラーを捕捉し、Clojure ランタイム自身の拒否は同じ呼び出しで オラクルが投げるクラスとして捕捉します((first 5)はIllegalArgumentException、失敗したassertはExceptionの catch が捕捉しないAssertionError)。クラスを示さないエラー -- オラクルが受け付ける構文の拒否(正規表現の先読み、(partition 0 coll))-- は、clojure.lang.ExceptionInfo以外のどのクラスの catch でも最初のものが捕捉します。 下位の関数が先に拒否する誤用は、その関数のクラスになります。(shuffle 5)はseqのIllegalArgumentExceptionで、オラクルはjava.util.Collectionへのキャストで失敗します。範囲外の添字はIndexOutOfBoundsExceptionで、 そのサブクラスの catch も捕捉します(オラクルのagetはArrayIndexOutOfBoundsException、.charAtはStringIndexOutOfBoundsExceptionを投げます)。catch が名指すクラスはこの ホストで解決できなければなりません(java.*、clojure.langの throwable)。オラクルの クラスパスにしかないクラスは拒否します。 -
例外はクラス、メッセージ、データ、cause を持つコンディションです。実行時エラーは ランタイムがシグナルする Common Lisp のコンディションで、そのメッセージは Common Lisp の report(失敗した
(inc nil)の(.getMessage e)は+: The value NIL is not of type NUMBERで、オラクルではNullPointerExceptionの文言)、strはオラクルのクラス名の 接頭辞を持たないその report です。throwable の構築が例外になるのは、メッセージと cause 以外に何も持たないクラスだけです。独自のメンバーを持つクラス (java.net.URISyntaxException)はホストオブジェクトのままです。インタプリタと JVM では、 Java のメンバが投げた例外と throw されたホストオブジェクトはオラクルと同じくホスト自身の ものです。catch はそのクラスで捕捉し、そのオブジェクト自体を束縛します。 プログラムが作った例外のclassはクラス名をキーワードで返し(:java.lang.Exception。オラクルはホストの クラスを返します)、クラスを示さないエラーには:java.lang.RuntimeExceptionを返します。.printStackTraceはtoStringの行を*err*に書き(オラクルはそれとフレーム ごとの行を、*err*の束縛に関わらずプロセスの標準エラーに書きます)、.getStackTraceは 空のベクターを返します。.getClassはclassと同じ値を返します。インタプリタと JVM では、 それ以外のメソッドは、例外のクラスのホストの例外に対して呼び出され、Java のメンバに渡した 例外もそのホストの例外として渡ります。ホストの例外はメッセージと cause から一度だけ作り、ex-infoのものはRuntimeExceptionです。そのため(.getCause (UncheckedIOException. "u" e))が返すのはそのホストの例外で、e自体ではありません(オラクルではeとidentical?です)。 実行時エラーとランタイムの拒否にはそのようなホストの例外がないため、Throwableを受け取る Java のメンバはそれに一致しません。例外でない値のthrowは、値のレンダリングをメッセージとするClassCastExceptionになります(オラクルのメッセージは 2 つのクラス名を挙げます)。 -
multimethod のディスパッチ値はマップのキーと同じく(ベクターも含めて
=で)比較されます。 階層経由のディスパッチは厳密に最も具体的なメソッドを優先し、その後prefer-methodの選択に従います。ホストクラス上のdefmethodはclassが答える キーワードの下に格納され、すべての数値綴りは:numberにまとまります(オラクルはLongとDoubleを区別します)。真の nil は(:C%NIL)マーカーへ写されるので、 どの表も nil をキーにしません。一方リテラルに:nilな値はキーワード行のままです (オラクル通り。ディスパッチ関数の中のclass呼び出しは nil 引数に nil 自身を答えるので、 null 判定でそこでもマーカーへ写ります。素のものでも他の関数で包んだものでも、記録した定義から再降低される名前付きdefn・def済み関数経由でも、インラインなディスパッチ datum の中でそれらを呼び出す場合(呼び出し位置で同じ降低をインライン化)でも同様です)。Objectメソッドは検索の後・デフォルトの先に捕まえます。throwable やストリームのクラスは その名前のキーワード(classが答えるもの)の下に格納され、検索はオラクルの継承と同じく Java のスーパータイプをたどります。インタフェース(java.io.Serializable、java.io.Closeable)とObjectも含みます。isa?・derive・underive・parents・ancestors・descendantsはクラス名を同じキーワードとして読むので(isa? (class "a") String)はtrueで、クラスのparents/ancestorsはオラクルと同じく Java のスーパータイプを加えます。コアの種類(:string、:numberなど)、record、deftype は ここでは 1 つの値にならないホストクラス群を表します。Objectにisa?で、ancestorsはObjectを加えますが、ホストクラスのそれ以外のスーパータイプはモデル化しません。これらの 位置にクラス名を書かずホスト相互運用も使わないプログラムは階層だけを読むので、そこでの(ancestors (class e))はderiveが記録したものを返します。ここではキーワードがクラス そのものなので、:java.lang.Exceptionと綴ったキーワードもそのクラスです。ホストの クラスオブジェクト(ホストオブジェクトのclass、インタプリタと JVM)はその名前の キーワードと、単純名を通じてコアの種類のキーワードと同じクラスなので、(isa? (class (java.util.ArrayList.)) java.util.List)はtrueです。同じく:listと 綴るclojure.lang.IPersistentListにもisa?で、オラクルはfalseを返します。それ以外の クラス(java.io.File)はディスパッチ値でもクラスオブジェクトで、オラクル通りです。プロトコルの ディスパッチは階層を読まず(タグの 完全一致とObject既定)、Long・Doubleを:numberにまとめます(オラクルは 区別します)。 -
(methods mt)とget-method・remove-method・prefer-methodは式ではなく multimethod の 名前(defmultiの var。alias や refer 経由も可)を取ります。multimethod を束縛した ローカルは降低時に拒否されます。methodsが返すマップはホストクラスの行をclassが 答えるキーワードで引き、オラクルはClass自身で引きます。 -
record はオラクル同様リテラルで印字されます(
#user.R{:a 7})。ただしstrも そのリテラルを綴ります(オラクルはuser.R@<hash>)。deftype はラッパーリスト ((:C%TYPE ...))、reify は(:C%REIFY ...)で印字されます。決定的に印字されるのは エントリのマップだけです。 -
deftype の
^:volatile-mutableフィールドは^:unsynchronized-mutableと同じ素の スロットです(スレッド間の順序保証はありません)。 -
split/replaceは seq を返しベクターにはなりません。素の文字列は文字通りのままです(パターン値だけがパターンマッチします)。index-ofは 見つからないときオラクル同様に-1を返します(clojure.string/index-ofはnil)。 -
本体内の
defは本体が走るときにグローバルを設定します。本体内のdefnは文位置の みで動きます(複数アリティはトップレベルのみ)。 -
操作は正しいコレクション種別を仮定します。誤用はオラクルの代わりに Common Lisp の 型エラーをシグナルすることがあります。
-
マクロは lower 中に展開されるため、すべてのバックエンドは展開後のコードを実行します。 マクロ呼び出しに対するインタプリタ自身の
evalも同様に展開します。マクロ本体に 見えるのは核の built-in とclojure.lispライブラリであり、プログラム自身の定義は 見えません。定義より上での呼び出しは拒否され、マクロに関数値はありません。special form(if、do、let*、newなど)、リーダーが綴る先頭(deref、syntax-quote、ns、in-ns)のdefmacroは名前を挙げて拒否されます。oracle はこれを 受け付けます(special form なら呼び出し位置では無視します)。 -
#(...)はソース、クオートの下、read-string/readのいずれでもオラクルと同じ(fn* [p1__N# ...] (body))と読まれますが、N はトップレベルのフォーム(読む datum) ごとに 1 から数え直します。オラクルのカウンタはプロセス全体で進むため、引数名が異なり、 同じテキストを 2 回読んだ結果はこちらでは=になります。マクロに渡した正規表現 リテラルは、同じソースからコンパイルし直した新しいパターンとして展開に届きます (オラクルの展開は同じPatternオブジェクトを持ちます)。 -
syntax-quote が限定するのは special form 以外のすべてのシンボルであり、oracle と 同じです。核の名前は
clojure.core/nameと綴り((:refer-clojure ...)で隠され たものは自身の名前空間で綴ります)、その他の解決できない綴りは定義側の名前空間、 エイリアス先頭はその名前空間、クラス先頭は完全限定名で綴ります。各x#は展開ごとに 1 つの gensym を束縛します。オラクルはコンパイル ごとに 1 つを解決するため、2 つの展開が suffix を共有するところ、こちらは異なります (より新鮮であり、capture されません)。macroexpand-1/macroexpandは mangle された データそのものを答えるため、quote したフォームとの=が成り立ち、表示は oracle と 同じ小文字綴りになります。ネストした syntax-quote は 1 回の展開の中で 各レベルを評価します。 -
var のメタデータは
#'の位置より上で lowering された定義から来ます。再定義より上で lowering された本体は古い docstring を見ます(オラクルの var は最新を見ます。呼び出しと 同じ分かれ方です)。:nsは名前空間のシンボルです(オラクルは Namespace オブジェクト)。 入口ファイルの:fileは与えたままのパスです(オラクルは絶対パスにします)。def/defn/defn-/defmacro以外(defmulti、deftest、レコードのファクトリなど)で 定義された var は:nameと:nsだけを持ちます。マクロの var の deref はシグナルを 上げます(オラクルは展開関数を答えます)。clojure.coreの var のメタデータは:name、:nsとマクロの:macroだけです(オラクルは:arglists、:doc、:addedと位置も 持ちます)。ここで値を持たない core の var(#'all-ns)は拒否されます。 -
名前空間は oracle の
#object[clojure.lang.Namespace "user"]から identity hash を除いた 形で印字され、そのclassは:clojure.lang.Namespaceを答えます。the-nsとfind-nsが 知っているのは、呼び出しより上でプログラムが作った名前空間、require したライブラリ、clj -Mが先にロードする 4 つ(clojure.core、clojure.edn、clojure.java.io、clojure.string)です。in-nsはnilを答えます(oracle は名前空間を答えます)。*ns*へのset!やbindingは*ns*が読む値を変えますが、以降のフォームが解決される 名前空間は変えません。それはリテラルの名前をとるnsとin-nsが決めます。コンパイル したプログラムの*file*は、コンパイル時のエントリファイルのパスです。 -
classは種類名のキーワードで答えます(:string・:number・:keyword等)。オラクルは ホストクラスを返しますが、wasm バックエンドにはありません。record/deftype は タグのキーワードで、ホストオブジェクト(インタプリタと JVM)はホストクラスで答えます。 -
コレクション・キーワード・シンボル・比・atom へのインスタンス呼び出しは core 関数を通して 答えるため、その逸脱も引き継ぎます(
.getClassはclassと同じ値を返します)。対応づけて いないメソッドはMethod m taking N args is not supported for class Cとして拒否し、 オラクルが答える場合(.hashCode)もあります。map のクラス名は件数だけで決め、8 件までは array map、それを超えると hash map とします。ここではnilが空リストなので、コレクションの メソッドはnilにも答えます((.count nil)は0)が、オラクルはNullPointerExceptionを投げます。nilへのそれ以外のメソッドはNullPointerExceptionです。 record・deftype・reify でも、プログラムが定義したどの record・deftype のプロトコルメソッドでも フィールドでもない名前は同じように拒否します(オラクルはNo matching field found)。 後の REPL 入力が record・deftype を定義しても、それより前に lower された呼び出し箇所は そのメソッドもフィールドも見ません。 -
instance?は値の種類ごとのオラクルのクラスで答えます。リストと正格な seq はclojure.lang.PersistentListなので、(map inc [1])についてIPersistentListとCountedはtrue、LazySeqはfalseです(オラクルではLazySeq)。2要素のベクタはすべてjava.util.Map$Entryです(map-entry?)。整数は(int 1)も含めてLongで、Integerには なりません。どの種類の値もインスタンスにならないclojure.langのクラス (clojure.lang.PersistentQueue)は未知の名前になります(オラクルはfalse)。プロトコルの インタフェース(user.P)が知るのはその箇所を lower した時点で定義済みの record と deftype なので、後の REPL 入力で定義したものはそこではインスタンスになりません。プロトコル自身の名前 (var であるP)は未知の名前になります(オラクルはClassCastException)。 -
unchecked-の算術は整数を64ビット(-int系は32ビット)に折り返し、型変換(int・long・short・byte・char・double・float)と合わせてオラクルと同じです。ただし64ビットを超える整数もここでは 通常の整数なので、オラクルでは折り返されない bigint のオペランド ((unchecked-add 9223372036854775807N 1))も折り返します。inc・decと検査付きの演算は 桁あふれしません(整数は bignum です)。 -
bigintとbigintegerは通常の整数、bigdecは通常の有理数を返します((bigdec "1.5")は3/2と表示され、オラクルは1.5M)。N・Mリテラルと同じです。10進展開が無限になる比のbigdecはオラクル同様シグナルします。 -
formatは%s・%d・%x・%X・%o・%c・%b・%f・%%・%nを描画します (幅・浮動小数点精度付き)。%e・%g・フラグ・非リテラルは名前付きで拒否されます。%sのnilはオラクル同様"null"です。 -
line-seqはパスか開かれたリーダー(clojure.java.io/readerなど。閉じるのはwith-open)を取って、どちらも strict に答えます(オラクルはリーダーを取って遅延です)。spit・slurp・line-seq・readerはインタプリタと JVM、wasm ではパスを含む--dirプリオープン付きで動きます。 -
ソート済みのマップとセットは、順序付け・表示・キーの検索がオラクルと同じですが、どの操作も コピーを作ります(関連付けにはハッシュマップと同じくコレクションの大きさ分のコストが かかります)。
nthはオラクルが拒否する場面でも要素を順にたどり、classは:map/:setを返します。先頭から走査して何も残らないsubseq/rsubseqはnilを返します(オラクルは())。値としてsubseqに渡したテストは(1 0)・(0 0)・(-1 0)への答え方で判別します (オラクルはコアの関数との同一性で判別します)。compareは文字列をコードポイントで比べます (オラクルは UTF-16 の単位で比べるので、U+FFFF を超える文字で答えが変わります)。 -
floatは倍精度の値を返すので、(float 1/3)は0.3333333333333333です(オラクルの Float は0.33333334と表示します)。float の範囲を超える値は同様にシグナルします。intとlongは 切り捨てるだけで、範囲外の値を拒否しません(オラクルはinteger overflow、Value out of range for long: ...)。 -
vector-ofは通常のベクターを返します。あとのconjやassocは値をそのまま格納し (オラクルは型変換を続けます)、:floatも倍精度で保持します。 -
リスト・遅延シーケンス・シーケンスの
emptyはnilを返し(オラクルは()。restと同じ、空をnilとする扱い)、メタデータも持ちません。マップエントリのemptyは[]です(オラクルはnil)。 -
partitionに pad はありません。非正のサイズや step のpartition-allはシグナルします (オラクルは()の無限 seq を返します)。pmapはmapで、呼び出し元のスレッドで順に 走ります。take-nthは step が 0 だとシグナルし、seq 形は負の step を絶対値で進みます。 オラクルの seq 形は先頭要素を無限に繰り返します。 -
トランスデューサーはオラクルと同じく畳み込み関数に対する関数ですが、
eductionは入力を それへ通したsequenceで、一度だけ計算します(strict な入力には strict に、lazy な入力 には lazy に)。オラクルは reduce のたびに変換をやり直します。printlnはその seq を 表示し、オラクルはオブジェクトを表示します。reduced値はラッパーのリストとして表示 されます。 -
トランザクションは単一スレッドのエクステントです。
dosyncはリトライせず、commuteは関数を1回だけ走らせ(オラクルは2回走らせうる)、validator は書き込み時に走って 失敗時は古い値を残します。dosyncの外側でのalter等はシグナルします。 -
agent は同期アトムです。
send/send-offは即時に適用して agent を答えにし (印字は unreadable な#<Atom ...>で、オラクルのオブジェクトではありません)、awaitとshutdown-agentsはnilを答えます。*agent*は送信実行中にだけ 束縛され(外側はnil。オラクルでは unbound です)。 -
bindingが再束縛できるのは^:dynamicな var だけです(それ以外はオラクルの 非 dynamic エラー同様に拒否)。^:dynamicなdefnも再束縛できます(定義は 直接のまま、呼び出しは var 経由になります)。それ以外の名前やローカルについた リーダーメタデータは解析して捨てられ、ディスパッチに影響しません。 -
REPL では、後の入力が
^:dynamicとして定義する var と同じ名前のローカルは、 その定義以後、エクステントの間その var を束縛します。そこで呼ばれた関数は ローカルの値を読みます。オラクルではローカルはレキシカルに束縛され、関数は var を 読みます。ファイルではこのローカルはレキシカルです。 -
with-metaはメタデータを持つコピーを返します。そこから導いた値(assoc、conjなど)はメタデータなしで始まり(オラクルは引き継ぎます)、シンボルはメタデータを 持ちません(with-metaはシンボルを返します)。コレクションリテラルのリーダー メタデータの:tagは書いたままのシンボル(String)で、オラクルはクラス (java.lang.String)に解決します。 -
with-openはcloseメソッド越しに閉じるため、バックエンドの届く closeable だけが動きます(Java の closeable は JVM が要ります)。timeは値を答えますが、 ミリ秒数は固定されません。数えるのは整数ミリ秒(42.0)で、オラクルの値には ナノ秒の桁が付きます。 -
read-string/readはクオートと同じ答えを返します。@xは(deref x)と読まれ、 構文クォートは展開されません(オラクルは(clojure.core/deref x)と読み、展開します)。 レコードリテラルは プログラムが定義するどのクラスでも読め、後のrequireが読み込むクラスも読めます (オラクルは先にクラスが読み込まれている必要があります)。deftype のリテラルは 拒否されます。readはストリームを取り、素のclojure.java.io/readerも受け付けます (オラクルはPushbackReaderを要求します)。ホストのリーダは拒否します。 -
*out*/*in*/*err*は*standard-output*/*standard-input*/*error-output*です(再束縛は標準ストリームの再束縛になります)。ルートで読んだ*out*と*in*は プロセスの標準ストリームを指すストリーム値です。defonceはリロードでルートを保ちます(defはリセットします)。 -
ホストオブジェクトの boolean は、lowering 時に receiver のクラスがわかり (構築リテラル、それを束縛した
let/if-let/when-letローカル、または..ステップの宣言戻り値型)、その引数個数の オーバーロードがすべてプリミティブ boolean を答える場合と、receiver が文字列・数値・ 文字で、そのクラスのその引数個数のオーバーロードがすべてプリミティブ boolean を答える 場合((.matches "abc" "x"))だけfalseを答えます。 それ以外のホスト boolean は共有のjava:unmarshal のままとなり、falseはnilと表示されます。 -
整数の receiver は
Integerに収まればInteger、収まらなければLongとして 呼ばれます(オラクルでは常にLongです)。(.getClass 1)はjava.lang.Integerを答えます。 -
パラメータタグの
_はその引数をjava:サーフェスのコスト規則に任せるため、(^[_] Math/abs -2)は2を答えます。オラクルは複数のオーバーロードが残るタグを 拒否します。 -
読むのはソースルート以下の
.cljファイルだけです(.cljcと classpath は対象外です)。 -
2 つの名前空間で同じ単純名を持つ record と deftype はディスパッチタグを共有し、
classの答え、プロトコルディスパッチ、=の比較はこのタグに基づきます。 -
同じ名前を 2 つの名前空間から refer すると後の refer が有効になります(oracle は拒否 します)。refer した名前を定義すると、その定義が oracle の警告なしに refer を置き換えます。