1.ボックス
Jの名詞は配列であるという事実に既に直面しています。 単一の定数値でも、ベクトル演算は許可されます。 一緒に、これらすべてが便利なベクトル同種プログラミング環境を構成します。
ただし、配列には独自の制限があることは明らかです。 Jでは、デフォルトでは長方形の配列しか存在しないため、いわゆる ギザギザの配列。 また、配列は、異なる要素で構成されるリストには適していません。
これらの問題を解決するために、Jは異種シーケンス-ボックスを作成および使用するためのツールを提供します。 ボックスは、任意の要素を格納できる一種のコンテナです。 したがって、ボックスの配列は、タイプ(void *)の要素の一種の配列です。 したがって、たとえば、ボックス化されたシーケンスの最初の要素は1次元配列、2番目は数値、3番目は整数の行列です。
ボックスを作成するには、モナドの動詞「<」を呼び出して、ボックスから要素を抽出(「開く」)する必要があります-モナドの動詞「>」:
]x =. <1 2 3 +-----+ |1 2 3| +-----+
ボックス自体はASCIIグラフィックスで描画されます。 次に、ボックスの値を抽出します。
>x 1 2 3
ボックスにいくつかの要素を追加するために、要素を一連のボックスに接続する動詞「;」が意図されています。
1;2;2 +-+-+-+ |1|2|2| +-+-+-+ (i.10) ; 42 ; (i. 2 3) +-------------------+--+-----+ |0 1 2 3 4 5 6 7 8 9|42|0 1 2| | | |3 4 5| +-------------------+--+-----+
このようなボックス化されたシーケンスの要素をリストするには、既知の品詞を使用できます。 たとえば、副詞「の間に」:
;/ i.3 +-+-+-+ |0|1|2| +-+-+-+
または動詞の構成:
(#@>)"0 (1 2 3; 2; 3 4) NB. ( = 0) 3 1 2
次に、動詞「{」を使用して、ボックスの2番目の要素を抽出します。
1 { ;/i.3 +-+ |1| +-+
この例では、次の瞬間に注意を払う必要があります。インデックス呼び出しは、配列のボックス化された要素を自動的にアンパックせずに返します。
前の式から、特定の動詞をボックスの各要素に適用する場合、その動詞がボックス名詞にラップされたオペランドを取るたびに結論付けることができます。 各呼び出しで配列から要素を「引き出し」、結果をボックスに「移動」するアクションの後に、既知のユニオン「&。」を使用できます。
ユニオン&。は、右動詞をオペランドに適用し、左動詞を結果に適用します。 次に、正しい動詞と逆の動詞が結果に適用されます。 したがって、上記の段落で説明したアルゴリズムを実際に繰り返しました。 このスキームを使用して、ボックスの各要素を2倍にします。
(+: &. >) ;/ i.3 +-+-+-+ |0|2|4| +-+-+-+
式&。>は非常に頻繁に使用されるため、デフォルトでは各シンボルに関連付けられています。
each &.> (+: each) ;/ i.3 +-+-+-+ |0|2|4| +-+-+-+
データ処理速度では、ボックスが大幅に(最大3桁!)数値配列に遅れていることに注意してください。
2.複数行動詞の定義
「エレガントなプログラミング言語を作成するには何が必要ですか?」
アイバーソン:「秘密はあなたが彼に期待することをすることです。」
フレッドブルックス、ケネスアイバーソンのお祝い、2004-11-30
動詞を暗黙の形式で提示することは常に可能とは限りません。 このために、Jには特別な構造があり、これを命令型と呼びます。 まず、これらは「3:」および「4:」という操作です(定数動詞「3:」および「4:」と混同しないでください)。 デフォルトのオペランドは「y」、左側は「x」です。 例:
v1 =: 3 : '- y' NB. v2 =: 4 : 'x + y' NB.
命令的な定義をタクティックな形式で記述できると感じているが、方法がわからない場合は、すばらしい標準動詞変換を使用できます。
13 : 'x + y' + 13 : 'x - (y + 1)' [ - 1 + ]
複数行の動詞を作成するには、同様の構成が使用されます。 さらに、ほとんどの関数型言語と同様に、最後に計算された値が返されるため、returnステートメントの類似物は必要ありません。 複数行の動詞では、ローカル変数も使用できます。「=。」操作を使用して決定されます。 動詞の定義を終了するための記号は、記号「)」です。
v =: 4 : 0 NB. z =. y + 1 NB. "z =: ..." z x - z ) NB. , . 3 4 v 1 2 1 1
Jには、条件(.if)、ループ(.while)などをチェックするための特別な構造もあります。 詳細については、ドキュメントを参照することをお勧めします。
3.再帰
再帰的クイックソート機能は、導入部で説明しました。 別の例を見てみましょう。 Pythonには、そのような関数が組み込まれていないかのようにシーケンスの長さを決定するための簡単な関数を記述します。
def len(xs): """>>> len([1,2,3]) 3""" if xs == []: return 0 return 1+len(xs[1:])
Jのベクトルの長さを計算するための再帰関数を作成するには、追加の述語動詞を導入して、名詞が少なくとも1つの要素を持つシーケンスであるかどうかを判断する必要があります。 「is array」というフレーズからこの述語isaを呼び出します。 最初に、この動詞の使用例を示します。
isa 1 NB. 0 isa i.0 NB. 0 isa 1 2 3 NB. 3
特定の位置でベクトルから要素を抽出する動詞を通じて、オペランドが1を超える長さのベクトルであるかどうかを判断します。 これは動詞「{」です
isa =: ((1: 1&{) :: 0:) : [:
したがって、式「1&{」が正しく満たされる場合、オペランドは長さが1より大きい配列であると見なされます。そうでない場合はfalse(ゼロ)を返します。 また、動詞の二項呼び出しの禁止を定義に追加しました。
条件チェックをシミュレートするために、@。Unionを使用し、右側のオペランドによって決定される、その位置で動詞をボックスから呼び出します。 つまり
3:`4: @. 1 4: 3:`4: @. 0 3:
右のオペランドがlength = 1のベクトルである場合、length = 1を返す必要があります。 この名詞の述語isaが0を返す場合。
len =: 1:`(.....) @. isa
省略記号の代わりに、再帰呼び出しを実装して、送信されたシーケンスのテールの長さを計算する必要があります。 Jの再帰呼び出しが動詞「$:」によって実装されるという事実を利用します。 T.O. 私たちは得る
len =: 1:`(>:@$:@}.) @. isa len 1 2 3 3 len 17 1
次のステップは、再帰呼び出しが末尾になるように動詞を書き換えることです。 これを行うには、左のオペランドに累積値を格納します。したがって、動詞は二項になります。
len2 =: [`((>:@[) $: (}.@])) @. (isa@]) 1 len2 i.7 7
動詞の定義は食欲をそそらないように見えますが、実際はそうです。 Pythonの例を使用して、動詞len2のアルゴリズムを説明します。
def len2(acc,xs): if xs == []: return acc else: return len2(acc+1, xs[1:])
書いたコードの速度を比較することは興味深いです。 これを行うには、動詞「6 !: 2」を使用します。これは、左オペランドに示されている回数だけ右オペランドを実行し、各実行の平均実行時間を秒単位で返します。
time =: 6!:2 x =: i.1000 10 time 'len x' NB. 0.00614873 10 time '1 len2 x' NB. 0.00553225 10 time '# x' NB. 1.67641e_6
ご覧のとおり、この場合、組み込みのJツールの使用は、独立した実装よりも3桁高速です。 さらに、Jには再帰の深さに制限があり、末尾再帰の最適化はありません。
このような再帰的表現の使用は、トレーニングおよび緊急の場合にのみ推奨されることに注意してください。
4.名前空間
Jでのプログラミングへのオブジェクト指向アプローチの使用については説明しません。 興味がある人のために、JでOOPのサポートがあるとしましょう。 詳細については、例えばLearning Jをご覧ください。
ただし、Jには、OOPツールキットに似た構文を持つ名前空間を使用するための特別な構成体があることに注意してください。
新しい名前空間の始まりは、式で始まる必要があります。
cocurrent 'name'
引用符で囲まれた名前空間名を記述する必要がありますが、これが現在の名前になります。 デフォルトの名前空間は '
base
'です。 したがって、名前空間のコードブロックが終了したらすぐに、式を使用してデフォルトのスコープに戻る必要があります。
cocurrent 'base'
カプセル化された名前空間のメンバーにアクセスする場合、各要素に_name_という接尾辞を追加する必要があります。「name」は名前空間の名前です。 大文字の名前空間が推奨されます。 これが良い例です:
cocurrent 'INNER' rate =: 10 v =: 3 : 'rate + y' cocurrent 'base' v_INNER_ 1 11 rate_INNER_ =: 1 v_INNER_ 1 2
5.例
セクションの最後に、1つの教科書の例-クイックソート動詞を示します。 JのHoarソートは次のように記述できます。
sel=: 1 : 'x # [' quicksort=: 3 : 0 if. 1 >: #y do. y else. (quicksort y <sel e),(y =sel e),quicksort y >sel e=.y{~?#y end. )
行ごとに定義を分析してみましょう。
- 1行。 最初に、この例の最初の行で定義されている補助式selについて説明します。 まず、次のような式に注意してください
1 : ''
引用符で囲まれた式が副詞であることを示します。 副詞とは、この副詞が適用される動詞の動作を変更する特別な構造を意味することを思い出してください。 この場合、副詞selは、左オペランド(動詞「[」)から「x」で示される要素をコピー(動詞「#」)します。
- 2行。 クイックソート動詞の定義そのものは、3:0という式で始まります。つまり、この動詞には1つの引数しか許可されません。
- 3行。 次の行では、1がオペランドの長さ( ">")以上( ">:")であるかどうかをチェックし、このオペランドの値が返されます。 ソートは必要ありません。
- 4-6ライン。 それ以外の場合、動詞「、」は、3つの再帰クイックソート呼び出しの結果を配列に結合します。 さらに、最初の要素はランダムに選択された要素「e」よりも小さく、次に「e」に等しい要素があり、次に要素が大きい「e」です。 式の最後に、値「e」が定義されます。 さらに、「{」は、セグメント0 ... operand_length(「#y」)上のランダム(「?」)位置にある要素の選択を意味します。
- 7行。 動詞定義を終了します。
前に示したように、クイックソートは1行で記述できます。
quicksort=: (($:@(<#[) , (=#[) , $:@(>#[)) ({~ ?@#)) ^: (1<#)
「$:」は動詞の再帰呼び出しを意味し、「@」という表現は動詞の逐次計算を定義することを思い出してください。
6.ヒント
記事を書く秘secretをよく知りたいですか? 500件の記事を作成します。
ロジャー・ホイ、ケン・アイバーソンを思い出す、2004
- ソースコードは、書かれているよりもはるかに頻繁に読み取られることに注意してください。 Jの場合、これは特に当てはまります。
- 動詞に意味のある名前を付けます。 v1、v2などの名前を使用しないでください。
- 動詞呼び出しの例を使用して、各動詞のコメントを必ず書いてください。
- 単体テストを必ず書いてください。
- タシティックな動詞には、オプションであってもスペースとブラケットを入れます。 式「+ /:+ *:〜1:」および「+ /:(+ *:〜1 :)」は同じように計算されますが、後者の方が読みやすくなっています。
ここで、Jの第一人者プログラマーのコードは、上記の推奨事項のすべてに違反することが多いことに注意してください。
- 動詞は、意図したとおりに呼び出されない可能性があることに注意してください。モナドとダイアドの両方の呼び出しを含めます。 Jのエラーメッセージはあまり有益ではありません。
- コンパクトな動詞定義を作成します。 長さが20文字の2つの動詞は、長さが40文字の1つの動詞よりも読みやすくなっています。
- 動詞が「本」の数式を計算する場合、計算の効率を大幅に向上させる場合にのみ暗黙の形式で記述します。 それ以外の場合は、明示的なオペランドを使用して書き込みます。
- 必要な場合にのみ、巡回命令および再帰構造を使用してください。 プログラムを読みやすくすることもありますが、非常に遅いです。 副詞「/」、「\」などを使用します。
- すべてのファイルをOOPモジュールとして定義することを検討してください。
- 可能であれば、グローバル変数を使用しないでください。
- 「J for Cプログラマー」という本を読んでください。 「ループレスコード」というタイトルの章に特に注意してください。
7.さらに読むこと
何が起こっているのかについて複数の説明を決して与えない-後者は常に正しい
ケネス・アイバーソン。
- http://vector.org.ukは、英国APL専門家協会の非常に評判の良い雑誌です。 記事は主にAPL言語に関するものですが、言語J、Q、Kに関する多くの記事があります。すべては電子的にダウンロードできます。 強くお勧めします。
- http://nsl.com-サイトの名前は「悪臭を放つループ」を表しています。 このサイトには、さまざまな複雑さの例が数多くあります。 主にKにあります。たとえば、KのKの遅延サブセットの実装があります。
- http://www.jsoftware.com/jwiki/Links-J言語の有用なリソースへのリンク集
- http://jsoftware.com/forums.htm-J .メーリングリスト(アクティビティが非常に多い-たとえば、メインのプログラミングセクションでは、1日あたり平均8〜12のメッセージ)。
- http://www.jsoftware.com/jwiki/Essays-この「尽きることのない知恵の源」-コメント付きの記事と例のコレクションを忘れないでください。 エッセイの中には、たとえば30行の数独ソルバーがあります。
結論の代わりに
私はかつてケンに言った、「ケン、あなたは私のお気に入りのプログラミング言語のデザイナーであり、ドン・クナットは私のお気に入りのプログラマーです。」 ケンはすぐに尋ねました:「私のプログラミングの何が問題なのですか?」
-ジョーイタトル、ケネスアイバーソンのお祝い、2004-11-30