热门问题
时间线
聊天
视角
J語言
来自维基百科,自由的百科全书
Remove ads
J語言,是一種陣列編程語言,由肯尼斯·艾佛森和許國華於1990年代初發明。J語言是APL語言的一種方言[5][6],延續了APL鮮明的簡潔性,它在數學和統計學程式設計上十分高效,特別是在需要進行矩陣運算的場合。
J語言最初起步於肯尼斯·艾佛森在1987年發表的《APL字典》[7],它實現了其中至關重要的秩的概念[8]。J語言提供隱式定義機制包括秩、鈎子[9]、叉子[10]和多種函數複合[11],並介入了作為頭等對象的動名詞,用以建立控制結構[12],它常被作為隱式編程的典範之一[13]。
Remove ads
簡介
Ken Iverson(右)和Roger Hui在1996年的照片[14]
J語言的運算符,承襲APL傳統,沒有優先級並且最右先行,2 * 3 + 4
按照2 * (3 + 4)
來運算。以歷史上APL使用的典型符號為例,符號/
被用來指示摺疊函數foldr1
,所以+/1 2 3
等價於1 + (2 + 3)
;在APL中,除法被表示為數學除號÷
,它將減號和冒號一起重複打印在EBCDIC和ASCII二者的紙質文本終端上;J語言使用%
表示除法,是對除號的一種近似或提示。
為了避免APL使用特殊的字符而遇到的問題,J語言只需基本的ASCII字符集,但使用點號.
和冒號:
作為「屈折」[15]。點號和冒號除了前導着空白字符的情況之外,都與緊前字符形成類似雙字符組的短字。多數「基礎」或「原始」的J單字,都充當數學符號,通過點號或冒號來擴展這些可用基本字符的含義。在其他語言中經常是成對的很多字符,比如[] {} "" `` <>
,在J語言中被當作單獨的字,或者在有屈折的時候,作為多字符字的單字符字根。
J語言不再支持從1968年的APL\360就有的[;]
形式的方括號索引,轉而支持叫做「來自」(from)的索引機制[16],它起源自Kenneth E. Iverson於1978年在《算子和函數》中提出的,依據基數解碼定義[17],並用符號⌷
表示的索引[18]。
J語言承襲IBM APL\360採用了平坦陣列模型[19],不支持由NARS(嵌套陣列研究系統)於1981年介入[20],並被IBM APL2所採納的嵌套陣列模型[21];J語言增加了Kenneth E. Iverson於1978年在《算子和函數》中提出的盒裝數據類型[22],它由SHARP APL於1981年介入,並於1983年在I. P. Sharp協會研究報告《理性化APL》中,列入與APL2相比較的「限定子集」(RS)而著重強調[23]。
J語言支持AVX2指令集進行SIMD運算[24]。為了包裝用面向對象編程語言開發的API和框架,J語言提供了層級命名空間機制[25],這裡所有名字都存在於特定語境(locale)中[26],可以避免軟件包之間的名字衝突,並能有效的用作基於類的面向對象編程的框架[27]。
J語言解釋器默認裝載標準庫[28]。通過包管理器[29],還可以安裝各種插件[30],如果是在管理員權限下安裝的J語言解釋器,則安裝插件也需要同樣的管理員權限。J語言擁有常規調試機制,還有叫做Dissect的可視調試器[31]。除了科學計算和統計分析,它還被用於關係數據庫管理系統如Jd[32]、極限編程[33]和網絡性能分析[34]。
2011年3月,J語言採用了GNU通用公共許可證版本3,從而成為自由和開源軟件[35],人們還可以在Jsoftware的商業許可證下利用源代碼[36]。
Remove ads
文檔與詞類
J語言的文檔包括在官網的NuVoc中[37],在其中將主要的字羅列為「J原語」,並使用顏色標示出它們分別的詞類[38]。早期的文檔還有入門和字典。在J語言中的字,被識別為名詞[39]、動詞[40]、定語[41](副詞和連詞)、系詞、標點、控制字。一個程序或例程,如果接受數據作為輸入並產生數據作為輸出,則被稱為「動詞」,與之相對,數據參數被稱為「名詞」。
動詞有兩種形式:只有右側一個參數的一元(monad)形式,和有左右兩側參數的二元(dyad)形式,例如在-1
中減號是一元動詞,而在3-2
中減號是二元動詞。J語言預定義了很豐富的動詞,它們都自動的作用於多種數據類型之上。用戶定義的程序可以自行命名,並用在任何允許使用原始動詞的地方。無論原始動詞還是派生動詞,它們的一元定義與二元定義,在很大程度上是獨立的。
Remove ads
起步示例
J語言可以寫出非常精簡的程序,特別是存在重度的對符號的函數重載,以至於一些編程者將它稱為難以閱讀的只寫語言。在計算機的終端上執行ijconsole
,即可進入J語言的REPL解釋器界面。
J語言的「Hello, World!」程序:
'Hello, world!'
Hello, world!
這個Hello World的實現反映了J語言的傳統用法,就是把程序錄入到J解釋器會話中,顯示出表達式結果。還可以準備J腳本來作為獨立程序來執行,比如在Linux系統上,可以編輯如下內容的一個文本文件,並命名為比如test01.ijs
:
#!/usr/bin/ijconsole
echo 'Hello, world!'
exit ''
注意第一行的#!
必須頂頭,這裡的echo
和exit
,是與Unix shell中同名命令功能類似的動詞。然後在終端界面中執行這個文件:
$ ijconsole test01.ijs
Hello, world!
$ chmod +x test01.ijs # 另一种执行方式,授予这个文件可执行权限
$ ./test01.ijs
Hello, world!
Remove ads
在J語言中函數一般稱為動詞,例如定義一個叫做avg
的動詞,計算一序列數的平均:
avg=: +/ % #
avg 1 2 3 4
2.5
一元動詞#
「計數」(tally),總計陣列中項目的總個數。動詞+
「加」(plus)和副詞/
「插入」(insert),派生出的動詞+/
,合計這個陣列的項目的總和。二元動詞%
「除」(divide)將這個總和除以這個總個數。而用戶定義的動詞avg
,用到了由連串(strand)的三個動詞(+/
、%
和 #
)構成的一個「叉子」(fork)。叉子(f g h) y
↔(f y) g (h y)
,這裡的f
、g
和h
指示動詞,而y
指示一個名詞。
使用avg
的一些例子:
]a=: ?. 20 $100 NB. 产生100以内20个随机整数的一个向量
94 56 8 6 85 48 66 96 76 59 33 72 63 1 89 52 17 20 9 65
avg a
50.75
4 avg\ a NB. 周期大小为4的移动平均
41 38.75 36.75 51.25 73.75 71.5 74.25 66 60 56.75 42.25 56.25 51.25 39.75 44.5 24.5 27.75
]b=: ?. 4 5 $50 NB. 产生50以内20个随机整数的一个矩阵
44 6 8 6 35
48 16 46 26 9
33 22 13 1 39
2 17 20 9 15
avg b
31.75 15.25 21.75 10.5 24.5
avg"1 b NB. 应用avg于m的每个秩为1的子阵列
19.8 29 21.6 12.6
一元副詞/
「插入」(insert),接受位於它左側的一個運算元,並產生將這個動詞應用於其參數的每個項目之間的一個動詞。就是說,+/
是一個動詞,定義為應用+
於給它的參數的各個項目之間。計算移動平均用到的二元副詞\
「中綴」(infix),將作為數據參數的列表劃分成一系列的指定大小的連續項目的子列表,將所修飾動詞應用於其上,並將這些結果形成一個列表。
一元動詞]
「相同」(same),恆等於給它的單一右參數,常像這樣用來在賦值之後顯示變量的內容。一元動詞?.
「擲骰/固定種子」(roll/fixed seed),不同於一元動詞?
「擲骰」(roll),在生成數據參數項目所指定大小範圍內的隨機數之時,採用固定的種子。這裡確定對矩陣按行還是按列進行平均,用到了連詞"
「秩」(rank),它在後面的定語章節和單獨條目中論述。
Remove ads
二元動詞i.
「出現索引」(index of),和二元動詞i:
「最後出現索引」(index of last),在任何大小的陣列內查找匹配者,並返回它的位置索引,如果未找到匹配者,則返回這個陣列的大小。例如:
a=: 3 1 4 1 5 9
a i. 1 2 NB. 找到1和2的第一次出现的索引
1 6
a i: 1 2 NB. 找到1和2的最后一次出现的索引
3 6
在J語言中,排序可以按APL傳統的兩步驟方式[42],使用一元動詞/:
「升序索引」(grade up)或\:
「降序索引」(grade down),和用二元副詞~
「被動」修飾的二元動詞{
「出自」(from),二者連串(strand)形成的一個「鈎子」來完成。一元鈎子(f g) y
↔y f (g y)
;副詞~
「反身·被動」,其一元定義為f~ y
↔y f y
,二元定義為x f~ y
↔y f x
。J語言還提供專用的二元動詞/:
「上升排序」(sort up)或\:
「下降排序」(sort down)。下面是用例:
a=: 2 0 4 7 15 9 8 0 4 9 18 8 1 18
/: a NB. 产生参数阵列的升序索引
1 7 12 0 2 8 3 6 11 5 9 4 10 13
({~ /:) a NB. 从参数阵列中按升序索引选取出各个项目
0 0 1 2 4 4 7 8 8 9 9 15 18 18
/:~ a
0 0 1 2 4 4 7 8 8 9 9 15 18 18
(a - 10) /: a
_10 _10 _9 _8 _6 _6 _3 _2 _2 _1 _1 5 8 8
Remove ads
load 'pacman' NB. 加载包管理器
'install' jpkg 'tables/csv' NB. 安装CSV文件插件
'showinstalled' jpkg '' NB. 查看已经安装插件
一個CSV文件簡單用例:
load 'tables/csv' NB. 加载CSV插件
a=: i. 2 3
a writecsv jpath '~/test01.csv' NB. 将一个阵列写入一个CSV文件
12
]b=: readcsv jpath '~/test01.csv' NB. 从一个CSV文件读入一个盒子阵列
┌─┬─┬─┐
│0│1│2│
├─┼─┼─┤
│3│4│5│
└─┴─┴─┘
]c=: makenum b NB. 尽可能的将盒子阵列转换成数值阵列
0 1 2
3 4 5
下面演示使用J語言編寫在管道中的過濾器,例如,在具有隱式編程機制Unix管道的Linux系統中,建立如下內容的文本文件,並命名為比如filter01.ijs
:
#!/usr/bin/ijconsole
load 'tables/csv'
stdout makecsv 10 + makenum fixcsv stdin ''
exit ''
然後在終端界面中執行如下命令行:
$ cat test01.csv | ijconsole filter01.ijs
10,11,12
13,14,15
Remove ads
數據類型
J語言支持三種簡單類型:
- 數值
- 文字(字符)
- 盒裝
其中數值有很多變種。J語言提供的唯一搜集(collection)類型,是任意維度的陣列。多數算法可以使用這些陣列來簡潔的表達。
J語言的數值類型之一是「位」。位有兩個值:0
和1
。位還可以形成列表,例如1 0 1 0 1 1 0 0
,是8個位的列表。在語法上,J分析器將位當作一個字。空格字符被識別為字形成字符,它處在屬於其他數值字的字符之間。
J語言支持任意長度的列表。J語言進一步的在這些位列表之上,支持所有常見二元運算,比如動詞*.
「與」(and)、+.
「或」(or)、-.
「非」(not)、|.
「反轉·旋轉」(reverse·rotate)、|.!.f
「移位」(shift)等。J語言還支持位的二維、三維等陣列。上面的運算同樣運行在這些陣列之上。
其他數值類型包括整數(比如3、42)、浮點數(3.14、8.8e22)、複數(0j1、2.5j3e88)、擴展精度整數(12345678901234567890x)和(擴展精度)有理分數(1r2、3r4)。同位一樣,它們可以形成列表或任意維度的陣列。同位的情況一樣,運算可以在一個陣列的所有數值之上。下面例子展示π的前50位,超出了IEEE 754雙精度浮點數的53位二進制尾數能精確表示的最大範圍,這就要用到J語言的擴展精度整數:
0j15 ": o. 1 NB. π在双精度浮点数下精确值的位数
3.141592653589793
<.@o. 10x ^50 NB. π乘以扩展精度10的50次幂
314159265358979323846264338327950288419716939937510
這裡採用一元動詞o.
「π乘以」(pi times),和一元動詞<.
「下取整」(floor)二者的複合,得到預期的結果[44]。位的列表可以使用一元動詞#.
「基數2」(base 2)解碼成整數[17]。整數可以使用一元動詞#:
「反基數2」(antibase 2)編碼為位的列表。
J語言還支持文字即字符類型。文字包圍在撇號'
之間,比如'a'
或'b'
。文字的列表,通過將多個字符用撇號包圍起來的常規字符串約定來表示,比如'abcdefg'
。在字符串內的''
表示'
字符本身。單個的文字,典型的是8
位寬即單字節的ASCII字符,此外J語言還支持Unicode文字。
不支持在文字上的數值和布爾運算,但支持面向搜集的運算,比如旋轉等。使用動詞".
「執行·數值」(do·numbers),將字節陣列轉換成數值;使用動詞":
「缺省格式·格式」(default format·format),將數值轉換成字節陣列。
盒裝類型的值是0維標量[22],而不管所包含的是怎樣的數據結構。使用一元動詞<
「盒裝」(box),將數據放置入盒子中;使用一元動詞>
「打開」(open),打開盒子中取出其中數據。還可以通過二元動詞;
「鏈接」(link)建立盒子的列表,通過一元動詞;
「拆除」(raze)移除一層盒子的列表。盒子內可以裝入其他盒子,還可以通過二元動詞$
「重製形狀」(reshape)和二元動詞#
「計件複製」(copy)等操作盒子及其列表。
J語言的陣列,具有同質(homogeneous)的項目類型,例如列表1 2 3
是整數的列表,儘管1
還可以是一個位。這種類型問題,在極大程度上對於編程者是透明的。只有特定的特殊運算,會顯露出在類型上的不同。例如列表1.0 0.0 1.0 0.0
,對大多數運算,將被當作是完全同於列表1 0 1 0
。
J語言支持數值稀疏陣列,通過它們的下標存儲非零數值。這在非零數值相對很少的情況下,是有效率的機制。
簡要詞彙表
下面的表格簡要列出了常用詞彙。如果含義中用了間隔號( · )分隔,通常前者是只有一個右側參數的一元含義,後者是左右兩側都有參數的二元含義。列出的對應APL符號,是Dyalog等現代APL所採用的符號。
定語
J語言的能力,很大程度上來自它的「定語」(modifier:修飾詞),這個範疇包括「副詞」和「連詞」:這些符號接受名詞和動詞作為運算元(operand),並以指定方式應用這些運算元。定語都可以應用於任何動詞,包括用戶寫的動詞,用戶可以寫自己的定語。
J語言的二元動詞有右結合性,或稱為儘量長右作用域,即它有儘可能多的右參數。定語即算子有左結合性,或稱為儘量長左作用域,即它有儘可能多的左運算元。如果表達式中存在定語即算子,首先應用這些定語,然後應用其生成的動詞。
一元副詞/
「插入」(insert),副詞\
「前綴·中綴」(prefix·infix),副詞\.
「後綴·外綴」(suffix·outfix),和連詞;.
「剪切」(cut)[49],指定參數的諸個規則或不規則子集,並在其上執行運算。在J語言實現中,前綴和+/\
、極小值<./\
和極大值>./\
運算,是典型的會對其進行速度優化的特殊組合[50]。
副詞~
「反身·被動」(reflex·passive),其一元形式f~ y
↔y f y
,將提供給動詞的右參數重複放置在左參數位置上;二元形式x f~ y
↔y f x
,將提供給動詞的左右兩個參數對換位置。
名詞的秩(rank)是排布其原子所依據的軸的數目,即它的形狀中項目的數目。動詞的秩是它能夠在其上直接運算的右(和左)名詞參數的最高秩,典型的表示為三個原子的一個列表:一元秩 二元左秩 二元右秩
。對副詞和連詞標示的秩,是所形成的動詞的秩。
秩在特定動詞和特定名詞的上下文下,將名詞的諸維,劃分成前綴諸維的序列,稱為框架(frame);和後綴諸維的序列,稱為單元(cell)。秩採用連詞"
「秩」來操縱[51],對應於APL符號⍤
,它有三種形式:u"n
「指定秩」(assign),m"n
「常量動詞」(constant),u"v
和m"v
「複製秩」(copy),這裡的u
、v
表示動詞運算元,而m
、n
表示名詞運算元。正數動詞秩,指示單元諸維的數目,負數動詞秩,指示框架諸維的數目,_
指示整體。
二元動詞的左右參數的框架經常是匹配的,就是說二者有相同的形狀,從而保證了它們有相同數目的單元。如果左右參數的框架不匹配,有三種可以運算的情況[52]:
- 標量一致,如果指定了兩參數中某一側的框架為空,即秩為
_
,這一個整體單元被應用於另一側參數的所有單元。 - 前綴一致,兩參數中有一側的短框架是另一側長框架的前綴,短框架的每個單元,被應用於對應的長框架去掉前綴餘下諸維形成的單元陣列的所有單元。
- 後綴一致,兩參數中有一側的短框架是另一側長框架的後綴,這時需要以兩側加上相同正數增量的方式指定秩,使原短框架側的框架為空,原短框架的諸維形成的這一個單元陣列,被應用於原長框架去掉後綴餘下諸維形成陣列的每個單元陣列。
連詞@:
「在於」(at)、@
「頂上」(atop)、&:
「並列」(appose)、&
「合成」(compose),是四種複合(composition)。J語言支持叫作「鈎子」(hook)和「叉子」(fork)的隱形連詞[9][10],二種隱形連詞和四種複合連詞,規定了如何將參數或將所飾動詞應用於參數的結果,提供給所飾動詞來進行應用的規則。下表列出它們的定義:
在上面表格中,mv=: 0{v b.0
,lv=: 1{v b.0
,rv=: 2{v b.0
,這裡的副詞b.0
給出動詞v
的三個秩[53]。在應用四種複合連詞形成新動詞的表達式中,@:
和&:
,要對第一步運算的中間結果,按所在子表達式的秩或整個表達式的秩_
進行匯集(assembly),並在有需要的情況下進行框架填充[54],然後在這個匯集成的框架內進行第二步運算;而@
和&
,直接在第一步運算的框架內,對中間結果進行第二步運算[55];在整個表達式求值結束時,最終結果在有需要的情況下要進行整體填充。
在x (u @ v) y
中,一元u
直接在二元v
所劃分的框架內進行自己的運算。在x (u @: v)"v y
中,@:
將二元v
的運算結果,匯集成"v
所指定的框架。在x (u & v) y
,二元u
直接在一元v
所劃分的兩個框架內進行自己的運算。在x (u &: v)"mv y
中,&:
將一元v
的兩個運算結果,匯集成"mv
所指定的框架。
下面例子展示四種複合的中間結果的單元差異:
] a =: >:i. 2 3
1 2 3
4 5 6
] b =: 0.1*>:i. 2
0.1 0.2
a (< @: +) b
┌───────────┐
│1.1 2.1 3.1│
│4.2 5.2 6.2│
└───────────┘
a (< @ +) b
┌───┬───┬───┐
│1.1│2.1│3.1│
├───┼───┼───┤
│4.2│5.2│6.2│
└───┴───┴───┘
a (; &: |) b
┌─────┬───────┐
│1 2 3│0.1 0.2│
│4 5 6│ │
└─────┴───────┘
a (; & |) b NB. 这里的框架仍是2 3
┌─┬───┐
│1│0.1│
├─┼───┤
│2│0.1│
├─┼───┤
│3│0.1│
└─┴───┘
┌─┬───┐
│4│0.2│
├─┼───┤
│5│0.2│
├─┼───┤
│6│0.2│
└─┴───┘
當連詞&
的一個運算元是名詞的時候,表示「粘上」(bond),它通過向二元動詞固定提供其一個參數的值而產生一個動詞:
&
派生的動詞經常作為一元動詞使用,即m&v y
或u&n y
;如果作為二元動詞使用,即x m&v y
或x u&n y
,左參數表示應用這個派生動詞於右參數的次數。需要確保通過&
定義的一元動詞,不出現在能夠取用左右兩個的參數的上下文中;如此定義的二元動詞,也不應該出現在只能取用一個右參數的上下文中。需要注意m&v
、v/
和v\
等的左參數的作用域,有時遇到其左側的複合連詞會產生並非預期的效果,經常需要將表達式整體加以圓括號包圍。
J語言還提供連詞&.:
「底下」(under)和&.
「對偶」(dual)[56]。下面定義中的動詞冪^:_1
表示逆運算:
@
、&
和&.
合稱為「緊密複合」(close composition)。現代APL中另有¨
「每個」(each),f¨
相當於J語言中的f &.>
[57]。例如:
1 2 + &.:> 0.1 0.2
┌───────┐
│1.1 2.2│
└───────┘
1 2 + &.> 0.1 0.2
┌───┬───┐
│1.1│2.2│
└───┴───┘
在J語言中,孤立的動詞序列叫做「列車」(train)[13], e f g h
意味着(e (f g h))
,d e f g h
意味着(d e (f g h))
;以此類推,動詞列車的一般模式(a b c ...)
,依賴於動詞的數目,在偶數時形式為(a (b c ...))
,最外層是個鈎子;而在奇數時形式為(a b (c ...))
,最外層是個叉子;二者的內部都是可能有多層的嵌套的叉子。
叉子、@:
再加上[
和]
,可以將很多常用複合寫為列車。在慣用法([: f g)
中,並不實際執行的隱式動詞[:
「遮帽」(cap),屏蔽了叉子的左分支,形成了等價於f @: g
的特殊化叉子[58]。
與現代APL如Dyalog等對照,複合連詞@:
對應於同秩連詞共享APL符號⍤
的「頂上」(atop),而&:
對應於⍥
「上方」(over),共享&
符號的「粘上」,對應於APL中的「綁上」(bind),APL的「綁上」和「邊上」(beside)共享符號∘
[59],「邊上」的一元形式同於⍤
,而二元形式同於鈎子。在《APL字典》中,@
對應其⍥
[60],而&
列入秩連詞⍤
之內[61],鈎子對應於符號⍩
「枝條」(withe)[62],&.
對應於符號¨
[63]。
下面的簡單例子是計算歐幾里得範數,和生成數位與維度坐標一致的整數:
]d=: (1 1),(1 1 1),:(3 4)
1 1 0
1 1 1
3 4 0
norm=: %: @ (+/) @: *:"1 NB. 它可加圆括号为((%: @ (+/)) @: *:)"1
norm d
1.41421 1.73205 5
coor=: 10&#. @ > @ { @: (< @: >: @ i."0)
coor 2 3 4
111 112 113 114
121 122 123 124
131 132 133 134
211 212 213 214
221 222 223 224
231 232 233 234
在coor
中採用的圓括號包圍,使得@:
處在整個表達式的最外層,從而形成了兩步驟運算;右側的第一步是圓括號包圍的子表達式,它的完全加圓括號(fully-parenthesized)形式為:(((< @: >:) @ i.)"0)
;左側的第二步是{
與複合到其上諸運算構成的子表達式,它的完全加圓括號形式為:(((10 & #.) @ >) @ {)
。一元動詞{
「目錄匯編」(catalogue),應用在盒裝列表的列表之上,是接受可變數目的變長參數的典型的動詞。
下面通過對圓括號包圍的子表達式加以變化,辨析秩連詞和複合連詞的特性。這裡的動詞]
,劃分開了給連詞或副詞的名詞運算元,和給所生成的動詞的名詞參數:
]a=: < @: >: @ i."0 ] 2 3 4 NB. 运算式可加圆括号为((< @: >:) @ i.)"0
┌───┬─────┬───────┐
│1 2│1 2 3│1 2 3 4│
└───┴─────┴───────┘
a -: < @: (>: @ i.)"0 ] 2 3 4 NB. 运算式可加圆括号为(< @: (>: @ i.))"0
1
a -: < @ (>: @ i."0) 2 3 4 NB. 运算式可加圆括号为< @ ((>: @ i.)"0)
1
< @ >: @ i."0 ] 2 3 4 NB. 运算式可加圆括号为((< @ >:) @ i.)"0
┌─┬─┬─┬─┐
│1│2│ │ │
├─┼─┼─┼─┤
│1│2│3│ │
├─┼─┼─┼─┤
│1│2│3│4│
└─┴─┴─┴─┘
< @: (>: @ i."0) 2 3 4 NB. 运算式可加圆括号为< @: ((>: @ i.)"0)
┌───────┐
│1 2 0 0│
│1 2 3 0│
│1 2 3 4│
└───────┘
下面的例子展示並聯電阻電路計算:,它可以如下這樣表達[64]:
Rtotal=: +/ &.: %
Rtotal 10 5 15
2.72727
連詞^:
動詞冪」(power of verb)[65],有兩種形式:
^:n
,是運算元為名詞的「固定冪」。^:v
,是運算元為動詞的「動態冪」。
對於固定冪u ^:n
,如果x
缺席,u ^:n y
在以y
為運算對象的迭代中,將動詞u
應用n
次;如果x
存在,x u ^:n y
在以y
為運算對象的迭代中,將動詞x&u
應用n
次。如果n
是陣列,則按每個原子項目都執行一次動詞冪,結果的框架為這個陣列的形狀;如果n
是取值為0
或1
的變量,則形成布爾值條件執行;如果n
是_1
,則進行u
的逆運算[66];如果n
是_
,則意味着「收斂」(converge),即反覆應用u
直到結果不再變化。例如:
(1+*&3) ^:0 1 ] 1 2 3 4
1 2 3 4
4 7 10 13
' ' , ^:4 'abc'
abc
(1+*&3) ^:_1 ] 4 7 10 13
1 2 3 4
(-:@(]+%)) ^:_ &1 ] 0.25 3 25 NB. 以巴比伦方法即一种牛顿法特例来计算平方根
0.5 1.73205 5
對於動態冪u ^:v
,如果x
缺席,u ^:v y
在以y
為運算對象的迭代中,將動詞u
應用v y
次;如果x
存在,x u ^:v y
在以y
為運算對象的迭代中,將動詞x&u
應用x v y
次。動詞冪可以形成動態條件執行,這裡的動詞v
必須總是產生布爾值結果,應用動詞u
當且僅當v
返回1
。進而u ^:v ^:_ y
可以形成while循環構造,只要v
返回1
,就反覆的執行u
,直到v
返回0
,或者u
將它的參數無變化的返回。例如:
-&2 ^:(>&4) "0 ] 1 3 6 12 NB. 对大于阈值4的列表项目减去2
1 3 4 10
4 (0.25&*@[+(1-0.25)&*@]) ^:< "0 ] 1 3 6 12 NB. 对大于阈值4的列表项目在其超出部份上扣除25%
1 3 5.5 10
+&3 ^:(<&100) ^:_ "0 ] 2 3 100 NB. 只要列表项目小于100就对它加上3
101 102 100
下面的例子用來辨析秩指定與框架劃分及匯集的性質,其中涉及的直接定義等內容可見於後面的定義章節:
itemize=: ,: : {{,: ^:x ] y}}"(0 _) NB. 定义具有一元和二元两种形式的项目化扩秩运算
<@itemize~ i.3
┌─────┬─────┬─────┐
│0 1 2│0 1 2│0 1 2│
└─────┴─────┴─────┘
$&.> <@itemize~ i.3
┌─┬───┬─────┐
│3│1 3│1 1 3│
└─┴───┴─────┘
$ <"2@itemize~ i.3
3 1
$&.> <"2@itemize~ i.3
┌───┐
│3 │
├───┤
│1 3│
├───┤
│1 3│
└───┘
$ <"_1@itemize~ i.3
3 3
$&.> <"_1@itemize~ i.3
┌───┬─┬─┐
│ │ │ │
├───┼─┼─┤
│3 │0│0│
├───┼─┼─┤
│1 3│0│0│
└───┴─┴─┘
#&.>@<"_1@itemize~ i.3
┌─┬─┬─┐
│1│1│1│
├─┼─┼─┤
│3│ │ │
├─┼─┼─┤
│1│ │ │
└─┴─┴─┘
$ 1
$ 0$0
0
# 0$0
0
$ <"1@itemize~ i.3
3 1 1
$ <"_2@itemize~ i.3
3 1 3
$ <"0@itemize~ i.3
3 1 1 3
$ <"_3@itemize~ i.3
3 1 1 3
在J語言中,動名詞(gerund)是叫做「原子表示」的特殊盒子的一個列表,這種盒子可以像任何其他盒子一樣使用,並可以最終轉變回到要執行的動詞。關於動名詞的運算有:
- 連詞
`
「連結動名詞」(tie or gerund),建立動名詞。 - 連詞
`:
「喚起動名詞」(evoke gerund),在加以運算元之後成為:`:6
,將動名詞轉變成動詞列車;`:0
,將轉變回來的這些動詞分別單獨應用,並將它們的結果收集入一個列表。
- 連詞
@.
「議程」(agenda),m @. n
從動名詞m
中,選擇出第n
個原子表示,將它轉變回到動詞並執行它。
下面是動名詞簡單示例和考拉茲猜想示例:
grd =: * ` (+&2) NB. 建立一个动名词
grd NB. 显示原子表示,这里的符号'0'标识名词
┌─┬─────────────┐
│*│┌─┬─────────┐│
│ ││&│┌─┬─────┐││
│ ││ ││+│┌─┬─┐│││
│ ││ ││ ││0│2││││
│ ││ ││ │└─┴─┘│││
│ ││ │└─┴─────┘││
│ │└─┴─────────┘│
└─┴─────────────┘
{. grd NB. 动名词可以像普通盒子一样操纵
┌─┐
│*│
└─┘
grd `:6 i. 4 NB. 将动名词转换成动词列车来执行
0 3 8 15
grd `:0 i. 4 NB. 将动名词转换成并行执行的动词
0 1 1 1
2 3 4 5
Collatz=: -: ` (1+*&3) @. (2&|) NB. 考拉兹猜想的算式
Collatz "0 ] 1 2 3 4 5 6 7
4 1 10 2 16 3 22
>./@(Collatz^:(>&1)^:_"0@>:@?@$&1e6) 1000 NB. 取1000个在1e6内的随机数测试考拉兹猜想
1
定義
J語言支持用戶進行顯式定義[67],和{{
……}}
形式的直接定義[68]。下面以五種複合作為顯式定義的例子:
at=: conjunction define
u (v y)
:
u (x v y)
)
atop=: conjunction def '(u at v)"v'
beside=: conjunction define
u (v y)
:
x u (v y)
)
appose=: conjunction define
u (v y)
:
(v x) u (v y)
)
compose=: conjunction def '(u appose v)"(0{v b.0)'
a=: ? @ $&1000 @: >: 4?10
b=: |: a
p=: a (+/ . *) b
matmul=: {{x u@:v"(1 _) y}}
(a (+/ matmul *) b) -: p
1
inner=: {{x (u@:v"1)"(1 _) y}}
(a (+/ inner * 0&|:) b) -: p
1
outer=: {{x u@(v/"_1~ |:)~"(2 _) y}}
(a (+/ outer *) b) -: p
1
revmul=: {{x (i.<:#$y)&|:@(u@:v"(_ 1)~ |:)~"(2 _) y}}
(a (+/ revmul * 0&|:) b) -: p
1
APL傳統上的將內積Pf.gQ
解釋為f/PgQ
[47],J語言的矩陣乘法要求寫為Pf/ .gQ
,不隱含的為左運算元f
附加一元/
。轉置也是有較大開銷的運算,不同的矩陣乘法算法有不同的參照局部性。
matmul
通過"(1 _)
將u@:v
的右參數從向量擴展為一般陣列,它用於右參數為行主序陣列的情況。在向量與向量列表二者諸項之間逐對的進行乘積累加運算,是BLAS的標準算法[69]。inner
採用了兩向量之間的點積運算u@:v"1
,它適宜直接用於右參數為列主序陣列的情況。在右參數為行主序陣列之時,需要如例子代碼這樣,對右參數陣列進行二元轉置0&|:
,這裡的0
指示將第一軸安排至最後位置而其他軸保持原序前移。這種基於點積的實現,通常需要進一步加以循環鑲嵌。outer
可以看作matmul
的變體,它首先對左參數陣列進行轉置,然後進行多組的向量與一般陣列之間二元的張量積運算v/"_1
[48],最後在各組結果的列表上進行u
計算,每組運算之後參與其中的左右兩陣列的元素不會被其他組的運算再次訪問。revmul
同inner
一樣適宜直接用於右參數為列主序陣列的情況,但採用了同matmul
類似的計算方法,它在乘法之前對左參數陣列和在乘法之後對結果要做轉置,matmul
與revmul
的關係如同。matmul
一次性訪問左參數陣列,反覆多次訪問右參數陣列;revmul
一次性訪問右參數陣列,反覆多次訪問左參數陣列。
在隱式定義中,遞歸定義可以不通過名字引用自身,轉而使用動詞$:
「自引用」。例如遞歸的計算斐波那契數列:
fibonacci=: 1: ` ($:@-&2 + $:@<:) @. (>&2) "0 : [:
fibonacci >:i.9
1 1 2 3 5 8 13 21 34
_9:
到9:
是常量動詞。動詞[:
「遮帽」,用在連詞u : v
「一元與二元定義」所應用的動詞位置上,即充任了一元動詞u
或二元動詞v
,可分別在如下兩種情況下報錯:定義的是二元動詞,卻不適當的被用作一元動詞;或定義的是一元動詞,卻不適當被用作二元動詞。
在顯式定義和直接定義中,提供了類似其他過程語言的控制結構[70]。這裡列出的是每個範疇內的代表性控制字:
索引
J語言的索引機制採用二元{
「來自」(from)動詞來完成,它的秩為0 _
,它有兩種形式,分別為左參數為索引陣列的主軸索引,和左參數為二層或一層盒裝結構的逐軸索引,二者分別對應APL中,方括號內為單個軸的主軸索引選取,和方括號內為;
分隔的多個軸的逐軸索引選取。
索引陣列的每個項目指定對主軸的項目單元的一個選取,將它們的結果再匯合為一個陣列。負值索引表示從末尾往前記數。在APL中,這種形式的索引被稱為「來自」(from),也叫做「選取」(select)或幽默地稱為「明智」(sane)索引,最早出現在SAX(SHARP APL for UNIX)對其@
「來自」索引的擴展中,部份現代APL,將它表示為符號⊇
。例如:
i. 2 3
0 1 2
3 4 5
1 0 { i. 2 3
3 4 5
0 1 2
1 0 {"1 i. 2 3
1 0
4 3
(i. 2 3) { 'abcdefg'
abc
def
_1 { 'abcdefg'
g
逐軸選取可以形成子陣列[16],在現代APL中,它被表示為⌷
,故而也被稱為「扁方塊」(squad:squish quad)索引(indexing)或就叫做「索引」(index)函數。裝在二層盒裝結構中的,是對應諸軸的一層盒裝子結構的列表,其中每個一層盒裝子結構內都是數值列表,它對應在此軸內一個或多個項目選擇。默認全選使用名詞a:
「麼點」(ace)指示,它是盒裝空列表<0$0
。在尾部的連續多個默認全選不需要寫出。例如:
i. 3 4
0 1 2 3
4 5 6 7
8 9 10 11
(<<1 2) { i. 3 4
4 5 6 7
8 9 10 11
(<1 2;0 2 3) { i. 3 4
4 6 7
8 10 11
(<a:;0 2 3) { i. 3 4
0 2 3
4 6 7
8 10 11
(<a:;0 2 3)
┌──────────┐
│┌──┬─────┐│
││┌┐│0 2 3││
│││││ ││
││└┘│ ││
│└──┴─────┘│
└──────────┘
它還支持一層盒裝結構,裝在其中的是數值列表,它的元素指示每軸選取一個項目,如果單選了所有軸,則指定一個原子項目。一層盒裝結構中的這個數值列表,等價於二層盒裝結構中一層盒裝的單一數值的列表。兩種索引形式可以結合使用,即可以將盒裝結構的陣列作為給{
的左參數,它按這個陣列的形狀匯合多個逐軸選取的結果。例如:
(<1 2) { i. 3 4
6
((<0 0),(<2 2),(<1 1)) { i. 3 4
0 10 5
(<0 0),(<2 2),(<1 1)
┌───┬───┬───┐
│0 0│2 2│1 1│
└───┴───┴───┘
例如(<<1 2),(<a:;0 2 3)
這樣的選取是合法的,將形狀不一致的選取結果匯合在一起,會導致結果值填充[54]。
重排軸也叫做二元轉置。APL的二元轉置對軸次序的指定,類似於組合數學中置換的一行形式的柯西表示法[71],它被稱為「可能是APL編程者最後掌握的原始運算之一」[72]。J語言的二元轉置對軸次序的指定,不涉及將多個軸映射到結果中的一個軸的情況,使用了普通的索引形式的置換向量[73]。在置換向量的元素個數小於陣列軸的數目之時,J語言在置換結果中將其指定的諸軸安排在尾部,而其他軸保持原來相對次序前移。
針對向量的索引運算,是不加盒裝的主軸索引。要訪問一般陣列的特定原子項目,其選取向量需要一層盒裝,從而對其進行逐軸索引。置換向量p
所對應的逆向置換向量是/:p
[42],對於兩個置換向量p
和q
,則有/:p{q
↔ (/:q){/:p
。
二元轉置與索引機制有密切關聯[18],它有兩個重要性質[74]:
- 兩次連續的二元轉置,可以變換成等價形式:
p|:q|:A
↔(p{q)|:A
,即先將後者置換向量p
對前者置換向量q
進行置換,然後用結果的置換向量做一次二元轉置。 - 對二元轉置後的陣列,進行原子項目的選取,可以變換成等價形式:
(<k){p|:A
↔(<(/:p){k){A
,即先用置換向量p
的逆置換向量/:p
,對選取向量k
進行置換,然後用結果的選取向量來選取未轉置陣列。
下面是演示例子代碼:
a=: ? @ $&1000 @: >: 4?10
n=: # @ $ a
p=: ?~ n
q=: ?~ n
(/:/:p) -: p
1
((/:p) { p) -: i. n
1
(/: p{q) -: (/:q) { /:p
1
(p |: q|:a) -: (p{q) |: a
1
k=: ? $ p |: a
((<k) { p|:a) -: (<(/:p){k) { a
1
示例
下面例子形成帕斯卡三角的二項式係數的直接定義[75],並順帶展示基本的矩陣與盒裝運算:
pascal=: {{(0&, + ,&0) ^: y 1}}"0
pascal @ i. ] 5
1 0 0 0 0
1 1 0 0 0
1 2 1 0 0
1 3 3 1 0
1 4 6 4 1
({. (+//. @: pascal @ i.)) 9 NB. 斐波那契数列
1 1 2 3 5 8 13 21 34
((+/ . *) |:) @: pascal @ i. ] 5 NB. 帕斯卡矩阵
1 1 1 1 1
1 2 3 4 5
1 3 6 10 15
1 4 10 20 35
1 5 15 35 70
<"0 @ pascal @ i. ] 5
┌─┬─┬─┬─┬─┐
│1│ │ │ │ │
├─┼─┼─┼─┼─┤
│1│1│ │ │ │
├─┼─┼─┼─┼─┤
│1│2│1│ │ │
├─┼─┼─┼─┼─┤
│1│3│3│1│ │
├─┼─┼─┼─┼─┤
│1│4│6│4│1│
└─┴─┴─┴─┴─┘
]t=: < @ pascal @ i. ] 5
┌─┬───┬─────┬───────┬─────────┐
│1│1 1│1 2 1│1 3 3 1│1 4 6 4 1│
└─┴───┴─────┴───────┴─────────┘
(<@#&a:"0@|.@i.@# ,&> }:@,@:(,.&a:@<"0)&.>) t
┌─┬─┬─┬─┬─┬─┬─┬─┬─┐
│ │ │ │ │1│ │ │ │ │
├─┼─┼─┼─┼─┼─┼─┼─┼─┤
│ │ │ │1│ │1│ │ │ │
├─┼─┼─┼─┼─┼─┼─┼─┼─┤
│ │ │1│ │2│ │1│ │ │
├─┼─┼─┼─┼─┼─┼─┼─┼─┤
│ │1│ │3│ │3│ │1│ │
├─┼─┼─┼─┼─┼─┼─┼─┼─┤
│1│ │4│ │6│ │4│ │1│
└─┴─┴─┴─┴─┴─┴─┴─┴─┘
二項式係數也可以寫成隱式定義形式:
pascal=: ((0&, + ,&0)@] ^:[ 1:)"0 : [:
下面是基於二元副詞/
「形成表格」(table),製作條形圖和散點圖的簡易圖表例子[76]:
barChartH=: {&('.',u:16b2584) @ (>/ i.@(>./)) : [:
barChartH 3 1 4 1 5 9 2 6 5
▄▄▄......
▄........
▄▄▄▄.....
▄........
▄▄▄▄▄....
▄▄▄▄▄▄▄▄▄
▄▄.......
▄▄▄▄▄▄...
▄▄▄▄▄....
barChartV=: {&('.',u:16b258c) @ (</~ |.@i.@(>./)) : [:
barChartV 3 1 4 1 5 9 2 6 5
.....▌...
.....▌...
.....▌...
.....▌.▌.
....▌▌.▌▌
..▌.▌▌.▌▌
▌.▌.▌▌.▌▌
▌.▌.▌▌▌▌▌
▌▌▌▌▌▌▌▌▌
scatterChart=: {&('.',u:16b2588) @ (=/~ >:@|.@i.@(>./)) : [:
scatterChart 3 1 4 1 5 9 2 6 5
.....█...
.........
.........
.......█.
....█...█
..█......
█........
......█..
.█.█.....
這裡用到的Unicode方塊元素字符也出現在IBM PC代碼頁437之中。
這裡的scatterChart
可以使用二元副詞}
「修改」(amend)來實現:
scatterChart=: {&('.',u:16b2588) @ ((>./ , #) {{
1 y } $&0 x}} (#~ <&9@{."1)@((-~ >./) ,. i.@#)) : [:
APL的二元轉置,在多個軸映射到結果中的一個軸的情況下,將其依次安排到前導位置上並進行對角線選取[77]。下面基於一元動詞I.
「真值位置索引」,定義進行對角線選取的動詞diag
,它的左參數是布爾值列表,其中的真值1
指示與其位置對應的軸,要依次安排在前導位置上並進行對角線選取,其他的假值0
所對應的軸相對位置不變。
diag=: {{
s=. (I. , I.@:-.) @ ({.~ #@$)
t=. <"1 @ (i.@(<./)@({. $) */ #&1@[)
({~ (+/x)&t) @ (|:~ x&s) y}}
這裡局部定義了s
,它的左右參數同於給diag
的參數,它生成二元轉置需要的置換向量,這是由要安排到前導位置上的那些軸的位置索引,和餘下其他軸的位置索引串接而成。這裡的{.~ #@$
以右參數的諸軸數目選取左參數,用來在左參數的真值和假值的總數小於右參數的諸軸數目之時,對左參數填充上假值。
接着局部定義了t
,它的左參數是給diag
的布爾值列表中真值1
的個數,右參數是要對其指定數目的前導軸進行對角線選取的陣列,它生成對角線選取所需要的一層盒裝選取列表。這裡的(<./)@({. $)
選取出要進行對角線選取的前導諸軸的最小長度,用i.
形成這個長度的整數數列,再用#&1@[
形成其長度為左參數的全為1
的列表,通過*/
在二者之上形成表格矩陣。
最後的表達式先進行指定的二元轉置,再對其結果進行相應的對角線選取。下面是簡單用例:
>:i. 3 5
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
1 1 diag >:i. 3 5
1 7 13
i. 2 3 2
0 1
2 3
4 5
6 7
8 9
10 11
1 1 diag i. 2 3 2
0 1
8 9
0 2 1 |: i. 2 3 2
0 2 4
1 3 5
6 8 10
7 9 11
1 0 1 diag i. 2 3 2
0 2 4
7 9 11
J語言提供的排序機制基於了穩定排序算法,下面的例子代碼是快速排序的直接定義[78]:
cmp=: * @ -
quicksort=: {{
if. 1 >: #y do. y return. end.
s=. y u y {~?# y
(u quicksort (s<0)#y),((s=0)#y),(u quicksort (s>0)#y)}}
這裡定義一個動詞cmp
,它通過逐個做兩個數的差並取其符號,得到取值為_1
、0
或1
的平衡三進制值。cmp
將作為左運算元傳遞給副詞quicksort
。
在quicksort
的定義中,向局部變量s
賦值的表達式,第一步隨機選擇支點(pivot)運算,首先計算?#y
,生成在數據總個數範圍內的隨機數,接着在其上計算{~
,選擇出在隨機數指定的位置上的支點值;它的第二步運算,將運算元u
,應用到其左參數的數據列表,和右參數的支點值二者之上。
隨後是串接分治運算結果,首先將平衡三進制值列表,分別與0
做逐項的三分法比較,得到三個布爾值列表;然後以這種列表中的0
和1
作為件數,複製出數據列表的符合這個條件一個新的子列表,其中兩個作為參數傳遞給遞歸調用進行排序。
下面的快速排序實現,展示了隱式編程,即將函數複合在一起,而不顯式的引用任何變量,不提及要應用於其上的形式參數。這裡將前面代碼中向局部變量s
賦值時所求值的表達式改為隱式定義,進而以作為鈎子的第一步運算的方式,代入引用這個變量的表達式之中,並且採用鈎子的參數複製機制消隱了形式參數y
:
cmp=: * @ -
quicksort=: {{((($:@#~ <&0),(#~ =&0),($:@#~ >&0)) (u ({~ ?@#))) ^: (1<#) y}}
cmp quicksort 2 0 4 7 15 9 8 0 4 9 18 8 1 18
0 0 1 2 4 4 7 8 8 9 9 15 18 18
提供給連詞^:
的左側運算元,外層是個一元鈎子,它將提供給它的單一右數據參數,重複放置在它的左數據參數位置上。這個外層一元鈎子的第一步運算,是生成平衡三進制值列表的嵌套的二層一元鈎子(u ({~ ?@#))
;而外層一元鈎子的第二步運算,將生成的三個子列表串接起來。生成三個子列表的表達式,以數據列表是作為左參數,以平衡三進制值列表作為右參數;這裡的三個二元鈎子首先生成布爾值列表,接着進行對換了左右參數位置的二元複製運算,最後它們中有兩個通過自引用$:
進行了遞歸調用。
這個定義中的$:
是在這個副詞的私有語境內調用的動詞,所以不像前面直接定義那樣需要加上運算元u
以副詞形式來調用。這裡沒有對字符串長度小於等於1
的情況進行處理,這是因為迭代運算在條件不滿足時返回初始值,也就是返回這個字符串本身。將cmp
的表達式,代入定義中的左運算元u
,就能定義出動詞,同時也不再需要外在的採用直接定義的形式。
將一元鈎子替代為左分支為]
的叉子,形成的動詞列車更具可讀性:
quicksort=: {{(] (($:@#~ <&0),(#~ =&0),($:@#~ >&0)) ] u ] {~ [:?#) ^: (1<#) y}}
下面的例子定義基於一元/:
進行字符串比較的cmp
[79]:
cmp=: -/ @ (-.@-: * /:@;)
'alpha' cmp 'beta'
_1
'beta' cmp 'alpha'
1
'beta' cmp 'beta'
0
t=: ' the heart has its reasons that the reason does not know'
]words=: <;._1 t
┌───┬─────┬───┬───┬───────┬────┬───┬──────┬────┬───┬────┐
│the│heart│has│its│reasons│that│the│reason│does│not│know│
└───┴─────┴───┴───┴───────┴────┴───┴──────┴────┴───┴────┘
cmp&> quicksort words
┌────┬───┬─────┬───┬────┬───┬──────┬───────┬────┬───┬───┐
│does│has│heart│its│know│not│reason│reasons│that│the│the│
└────┴───┴─────┴───┴────┴───┴──────┴───────┴────┴───┴───┘
在這個cmp
定義中,/:@;
先將兩個字符串參數進行盒裝串接,然後一元/:
給出二者的升序索引,二者之間為升序或相同時為0 1
,而二者為降序時為1 0
;至此是升序還是相同仍需區分,-.@-:
判斷兩參數是否為「不相同」,不相同時為1
,而相同時為0
。這裡的副詞;._1
「自有區間」,使用字符串的第一個字符作為分隔符,對字符串進行劃分並去除分隔符,然後應用所修飾的動詞於這些子字符串之上。
下面的例子給出n
個項目的所有置換的有次序的矩陣[80]。首先定義名詞p3
,它是置換長度為3
的全排列矩陣:
]p3=: (i.@! A. i.) 3
0 1 2
0 2 1
1 0 2
1 2 0
2 0 1
2 1 0
這裡用到了動詞:A.
「易位詞」(anagram),x A. y
的左參數x
,指定了長度為#y
的所有置換中給特定一個置換的編號,其對應的置換向量在組合數學中被稱為逆序向量,據此編號置換y
的項目。這裡求全排列的數目,用到了一元動詞!
「階乘」。接着在p3
的基礎上,實現置換長度為4
的全排列矩陣:
=/~ @ i. ] 4 NB. 生成4×4单位矩阵
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
\:"1 @ (=/~) @ i. ] 4 NB. 生成第1列为0 1 2 3,每行后3个元素升序的4×4“奇妙”矩阵
0 1 2 3
1 0 2 3
2 0 1 3
3 0 1 2
0&,. @: +&1 p3 NB. 对3元素全排列的每个元素增1,并在每个排列头部添0
0 1 2 3
0 1 3 2
0 2 1 3
0 2 3 1
0 3 1 2
0 3 2 1
perm0=: (0&,.@:+&1 p3) {"(_ 1) \:"1@(=/~)@i.
<"_1 perm0 4
┌───────┬───────┬───────┬───────┐
│0 1 2 3│1 0 2 3│2 0 1 3│3 0 1 2│
│0 1 3 2│1 0 3 2│2 0 3 1│3 0 2 1│
│0 2 1 3│1 2 0 3│2 1 0 3│3 1 0 2│
│0 2 3 1│1 2 3 0│2 1 3 0│3 1 2 0│
│0 3 1 2│1 3 0 2│2 3 0 1│3 2 0 1│
│0 3 2 1│1 3 2 0│2 3 1 0│3 2 1 0│
└───────┴───────┴───────┴───────┘
$ perm0 4
4 6 4
這裡的{"(_ 1)
,其左側是從6×3全排列矩陣加工而成6×4選取矩陣,用它分別對其右側的4×4「奇妙」矩陣的每一行進行主軸索引運算,即將選取矩陣每行第1個元素保持為「奇妙」矩陣此行的第1個元素,而每行後面3個元素是對「奇妙」矩陣此行後面3個元素的排列[81]。這一步寫出的排列動詞的結果是4×6×4的三維陣列,將它重製形狀為24×4全排列矩陣:
perm1=: (,~ !) $ ,@((0&,.@:+&1 p3) {"(_ 1) \:"1@(=/~)@i.)
$ p4=: perm1 4
24 4
二元動詞$
的左參數的值為(!y) , y
,這裡的y
是給排列動詞的數據參數;而它的右參數是用一元動詞,
將三維陣列散開後形成的一個向量。
然後將其中的p3
,替代為遞歸的自引用$:@-&1
;並通過名詞秩,形成常量動詞(1 0$0)"_
,設置長度為0
時的基礎值為1 0$0
:
perm=: (1 0$0)"_ ` ((,~ !) $ ,@(0&,.@:+&1@$:@-&1 {"(_ 1) \:"1@(=/~)@i.)) @. (>&0) : [:
(perm 4) -: p4
1
$ perm 0
1 0
$ perm 1
1 1
invertVec=: I.@(, -:"1 perm@#) : ({ perm)
1 _1 invertVec 4
0 1 3 2
3 2 1 0
invertVec 3 2 1 0
23
最後將遞歸形式改為迭代形式,可採用連詞F..
「單結果正向摺疊」(fold single forward),使用它需要事先安裝插件dev/fold
[82]。這個連詞所形成的動詞,從左至右遍歷右參數列表,將其項目逐個作為動詞運算元所見到的左參數;它的左參數是迭代對象的初始值,動詞運算元所見到的右參數是迭代對象:
load 'dev/fold/foldr'
perm=: (1 0$0)&(]F..((,~ !)@[ $ ,@(0&,.@:+&1@] {"(_ 1) \:"1@(=/~)@i.@[)))@:(>:@i.) : [:
如果不採用連詞F..
,可以基於一元副詞/
「插入」,自行實現正向摺疊算子:
foldl=: {{m"_ ` (v&:>/@,&(<m)@(<"_1@|.)) @. (>&0@#)}}
perm=: (1 0$0)foldl((,~ !)@[ $ ,@(0&,.@:+&1@] {"(_ 1) \:"1@(=/~)@i.@[))@:(>:@i.) : [:
在J語言中,提供了二元副詞;.±3
「子陣列」(subarrays),它是;.
「剪切」(cut)的三種形式之一,也被稱為密鋪(tessellate)或鑲嵌(tile)。x(u;._3)y
應用動詞u
於由x
指定的y
的有相同形狀的每個正規鑲嵌之上。;.3
與之類似,但不丟棄結果中不完整的鑲嵌。
現代APL所使用的二元算子⌺
「模板」(stencil),在邊緣的處理上不同於J語言的鑲嵌,它要求鑲嵌子陣列每個軸的中心,在長度為奇數時是y
的元素,在長度為偶數時在其元素之間,並且用填充(fill)元素填滿超出的部份,它的缺省移動步長是1
。下面在;._3
的基礎上,利於二元動詞{.
「採取」(take)的填充特性,定義一個stencil
實現:
stencil=: {{
p=. 1&,:`|.@.(>&1@#@$) n
r=. <.-:<:{: p
t=. -r+s=. r+$y
p u;._3 t&{.s&{. y}}
這個定義只提供一個右名詞運算元n
,它是鑲嵌子陣列的規定矩陣,不提供同每個子陣列對應的諸軸填充數目作為左名詞運算,APL⌺
算子提供它,意圖在需要時籍此移除填充。這裡的鑲嵌規定矩陣定義,其第1行是子陣列的每軸長度,第2行是每軸的移動步長,這個行次序與;.±3
的規定相反。這裡的p
是給;._3
的鑲嵌規定矩陣,r
是每軸在頭部和尾部的填充數量,s
是正值控制尾部填充,t
是負值控制頭部填充。在下面的簡單用例中,數值陣列的填充元素是0
:
]d=: 4 4 $ >: i. 9
1 2 3 4
5 6 7 8
9 1 2 3
4 5 6 7
< stencil 2 3 d
┌─────┬─────┬─────┬─────┐
│0 1 2│1 2 3│2 3 4│3 4 0│
│0 5 6│5 6 7│6 7 8│7 8 0│
├─────┼─────┼─────┼─────┤
│0 5 6│5 6 7│6 7 8│7 8 0│
│0 9 1│9 1 2│1 2 3│2 3 0│
├─────┼─────┼─────┼─────┤
│0 9 1│9 1 2│1 2 3│2 3 0│
│0 4 5│4 5 6│5 6 7│6 7 0│
└─────┴─────┴─────┴─────┘
下面實現康威生命遊戲,它是基於Moore鄰域的一種細胞自動機[83]:
life=: {{3=s-y*.4=s=. (+/@,) stencil 3 3 ] y}}
glider=: ".;._2 noun define
0 0 1 0 0
1 0 1 0 0
0 1 1 0 0
0 0 0 0 0
0 0 0 0 0
)
life glider
0 1 0 0 0
0 0 1 1 0
0 1 1 0 0
0 0 0 0 0
0 0 0 0 0
{&('.',u:16b2596) &.> (i.8) {{life ^:x ] y}} &.> <glider
┌─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┐
│..▖..│.▖...│..▖..│.....│.....│.....│.....│.....│
│▖.▖..│..▖▖.│...▖.│.▖.▖.│...▖.│..▖..│...▖.│.....│
│.▖▖..│.▖▖..│.▖▖▖.│..▖▖.│.▖.▖.│...▖▖│....▖│..▖.▖│
│.....│.....│.....│..▖..│..▖▖.│..▖▖.│..▖▖▖│...▖▖│
│.....│.....│.....│.....│.....│.....│.....│...▖.│
└─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┘
這裡的實現算法,將生命遊戲規則合併入一個單一表達式中,它由Arthur Whitney提出[84]。算法的第一步驟用+/@,
合計每個格點及其周圍格點中1
數目,並將它局部保存在s
中。第二步驟將為前面的結果與4
做相等比較,再與當前狀態y
做邏輯與運算,只有在當前格點為1
,而且周圍格點合計為3
的情況下,當前格點得到真值1
。第三步驟用s
減去前面的結果真值,再與3
做相等比較。在這個最終結果中,當前格點得到真值1
有兩類情況:⑴它在s
中的值為4
,並減去了真值1
,這就是第二步驟運算所選定的情況;⑵它在s
中的值為3
,並減去第二步驟運算在這種情況下必然得出的假值0
,這又可細分為兩種情況:當前格點為0
,而且周圍格點合計為3
;或者當前格點為1
,而且周圍格點合計為2
。
這個算法可以寫為隱式定義形式:
life=: (=&3@] +. (*. =&4)) (+/@,) stencil 3 3 : [:
在J語言中,實現以遞推關係定義的序列,避免出現的時間複雜度,可以採用連詞F:.
「多結果正向摺疊」(fold multiple forward),使用它需要事先安裝插件dev/fold
[82]。這個連詞所形成的動詞,不輸出左參數的初始值,如果提供的右參數為空值,它的輸出為空值,否則它輸出每次迭代的結果。上例中的迭代算式可以改寫為:
load 'dev/fold/foldr'
{&('.',u:16b2588) &.> (< , <F:.(life@])&(7$0)) glider
如果不採用連詞F:.
,可以自行實現輸出中間結果的正向摺疊算子:
foldlist=: {{
if. 1 > # y do. '' return. end.
r=. '' [ a=. x
for_i. y do. r=. r , u a=. i v a end.
r }}
{&('.',u:16b2588) &.> (< , <foldlist(life@])&(7$0)) glider
在這裡的foldlist
中,將r=. '' [ a=. x
改為r=. u a=. x
,則(< , <foldlist(life@])&(7$0))
可改為<foldlist(life@])&(7$0)
。
在J語言中,提供了二元副詞/.
「鍵分組」(key),它按左參數中的唯一鍵,對右參數進行分組(group)或稱為分區(partition),並將所修飾動詞應用到這些分組之上。分組次序同於一元動詞~.
「唯一值」處理結果的次序,它除去匹配前面出現過的項目的任何項目。下面在它的基礎之上,定義對應現代APL使用的二元算子⌸
「鍵分組」(key)的一個副詞,它將所修飾動詞應用在唯一鍵和相應的分組二者之上,它還具有一元和二元兩種形式[85]:
key=: {{
(<"0 ~. y) u (y </. i.#y)
:
(<"0 ~. x) u (x </. y)}}
它的二元形式的左參數含有唯一鍵,而右參數是要分組的數據;它的一元形式的右參數含有唯一鍵,所分組的是右參數諸項目的索引值。下面是這個鍵分組副詞所適用的動詞的簡單示例:
x=: 'Mississippi'
[ key x
┌─┬─┬─┬─┐
│M│i│s│p│
└─┴─┴─┴─┘
] key x
┌─┬────────┬───────┬───┐
│0│1 4 7 10│2 3 5 6│8 9│
└─┴────────┴───────┴───┘
,. key x
┌─┬────────┐
│M│0 │
├─┼────────┤
│i│1 4 7 10│
├─┼────────┤
│s│2 3 5 6 │
├─┼────────┤
│p│8 9 │
└─┴────────┘
([ ,. #&.>@]) key x
┌─┬─┐
│M│1│
├─┼─┤
│i│4│
├─┼─┤
│s│4│
├─┼─┤
│p│2│
└─┴─┘
下面的例子通過鍵分組來找到一個單詞列表中的易位詞:
]a=: <;._1 ' pats spat teas sate taps etas past seat eats tase star east seta'
┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┐
│pats│spat│teas│sate│taps│etas│past│seat│eats│tase│star│east│seta│
└────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┘
/:~ &.> a
┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┐
│apst│apst│aest│aest│apst│aest│apst│aest│aest│aest│arst│aest│aest│
└────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┘
(]key~ /:~&.>) a
┌─────────────────────┬─────────────────────────────────────────┬──────┐
│┌────┬────┬────┬────┐│┌────┬────┬────┬────┬────┬────┬────┬────┐│┌────┐│
││pats│spat│taps│past│││teas│sate│etas│seat│eats│tase│east│seta│││star││
│└────┴────┴────┴────┘│└────┴────┴────┴────┴────┴────┴────┴────┘│└────┘│
└─────────────────────┴─────────────────────────────────────────┴──────┘
在J語言中,提供了二元動詞I.
「區間索引」,它左參數x
必須是有次序的,從而定義了1+#x
個區間,除了最後一個之外的每個區間,都含有並結束於x
的一個項目,而最後一個結束於正無窮,第一個開始於負無窮;它應用於右參數y
,給出y
所位於的區間的索引。
下面的例子產生符合指定離散概率分布的隨機數列表,這裡定義了動詞ran
,它依據左參數x
給出的正實數向量中的這些權重,從i.#x
中選取出由右參數y
指定個數的隨機數列表[86]:
ran=: [: : ((I.~ (+/\ % +/))~ ?@$&0)
wt=: 7 5 6 4 7 2 0.4
# t=: wt ran 1e6
1000000
10 {. t
0 1 1 5 0 1 3 4 4 0
] r=: wt (+/@(=/ i.@#)~ % #@]) t NB. 实测的出现比率
0.222618 0.159083 0.19152 0.127394 0.222795 0.06378 0.01281
] p=: (% +/) wt NB. 期望的出现概率
0.22293 0.159236 0.191083 0.127389 0.22293 0.0636943 0.0127389
0j6 ": r - p
_0.000312 _0.000153 0.000437 0.000005 _0.000135 0.000086 0.000071
這裡首先通過?@$&0
,生成指定數目的在區間(0,1)
中的隨機浮點數,它也可以寫為等價的?@($ 0:)
。然後在叉子+/\ % +/
中,使用一元副詞\
「前綴」修飾動詞+/
,從而計算權重向量的前綴和,再用前綴和除以總和得出累積分布函數。最後通過區間索引,在有隨機浮點數落入特定區間的時候,生成這個區間對應的隨機整數。
動詞ran
的表達式是個二層二元鈎子,外層鈎子的第一步運算應用到右參數上,它的第二步運算即內層鈎子,整體修飾了二元副詞~
「被動」而對換了兩個參數的位置。內層鈎子的第一步運算+/\ % +/
所應用的右參數實際上是外層鈎子的左參數,它的第二步運算I.
修飾了~
,從而將它所面對的內層鈎子的左右兩參數,再次對換回到外層鈎子即整體表達式原先的位置上。
下面是將區間索引和鍵分組結合起來的例子,演示了林德伯格-萊維中心極限定理[87]:
histogram =: {{
{&('.',u:16b258c) @ ((|.i.x)&(</)) @ (>.@*&x) @ (% >./) y}}
summary=: {{ l=. 0 [ r=. 1
-&1@#/.~ @ ((i.x)&,) @ ((l+(}.i.x)*%&x(r-l))&I.) y}}
sampleMean=: {{%&m @ (+/) @ (m&, $ v@*&m) y}}
24&histogram @ (80&summary) @ (10 sampleMean (?@$&0)) 1e6
......................................▌▌▌▌......................................
.....................................▌▌▌▌▌▌.....................................
....................................▌▌▌▌▌▌▌▌....................................
....................................▌▌▌▌▌▌▌▌....................................
...................................▌▌▌▌▌▌▌▌▌▌...................................
..................................▌▌▌▌▌▌▌▌▌▌▌▌..................................
..................................▌▌▌▌▌▌▌▌▌▌▌▌..................................
.................................▌▌▌▌▌▌▌▌▌▌▌▌▌▌.................................
.................................▌▌▌▌▌▌▌▌▌▌▌▌▌▌.................................
................................▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌................................
................................▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌................................
...............................▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌...............................
...............................▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌...............................
..............................▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌..............................
..............................▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌..............................
.............................▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌.............................
............................▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌............................
............................▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌............................
...........................▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌...........................
..........................▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌..........................
.........................▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌.........................
........................▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌........................
......................▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌......................
.........▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌........
lineChart=: {{
s=. (|.i.x)&(</) @ (>.@*&x) @ (% >./)
t=. >&0 @ (2&(-/\)) @ (2&(-~/\))"1 @ ,.&1 @ (1&,.)
{&('.',u:16b2588) @ (2&(-~/\)@(0&,) +. t) @ s y}}
24&lineChart @ (+/\) @ (80&summary) @ (10 sampleMean (?@$&0)) 1e6
....................................................████████████████████████████
..................................................██............................
................................................██..............................
...............................................█................................
..............................................█.................................
............................................██..................................
............................................█...................................
...........................................█....................................
..........................................█.....................................
.........................................█......................................
........................................█.......................................
.......................................█........................................
.......................................█........................................
......................................█.........................................
.....................................█..........................................
....................................█...........................................
...................................█............................................
...................................█............................................
.................................██.............................................
................................█...............................................
...............................█................................................
.............................██.................................................
...........................██...................................................
.........██████████████████.....................................................
這裡定義的summary
局部賦值了兩個局部變量l
和r
,可以將這兩個局部賦值去掉,並將這兩個局部變量的出現替代為運算元m
和n
,如此對它的調用將變成(80&(0 summary 1))
這樣的形式。接下的代碼結合前面兩個例子,採用了不同於上例連續型均勻分布的其他分布作為獨立同分布,和不同的樣本平均:
ratio=: [: : (-&1@#/.~@(,~ i.)~ % #@])
10&histogram @ ((#wt)&ratio) @ (wt&ran) 1e6
random=: [: : (#@[ %~ (?@$&0@] + ((I.~ (+/\ % +/))~ ?@$&0)))
20&lineChart @ (80&summary) @ (wt&random) 1e6
20&lineChart @ (80&summary) @ (2 sampleMean (wt&random)) 1e6
20&lineChart @ (80&summary) @ (4 sampleMean (wt&random)) 1e6
load 'pacman' NB. 加载包管理器
'install' jpkg 'data/sqlite' NB. 安装SQLite数据库插件
load 'data/sqlite' NB. 加载SQLite数据库插件
getbin_psqlite_ '' NB. 安装SQLite数据库的共享库
SQLite數據庫的簡單用例:
load 'data/sqlite' NB. 加载SQLite数据库插件
db=: sqlopen_psqlite_ '~addons/data/sqlite/db/sandp.db' NB. 打开样例数据库文件
sqltables__db '' NB. 查看所有表格名字
┌─┬─┬──┐
│p│s│sp│
└─┴─┴──┘
sqlmeta__db 's' NB. 查看表格s的结构
┌───┬──────┬────┬───────┬──────────┬──┐
│cid│name │type│notnull│dflt_value│pk│
├───┼──────┼────┼───────┼──────────┼──┤
│0 │sid │text│0 │NULL │1 │
│1 │name │text│0 │NULL │0 │
│2 │status│int │0 │NULL │0 │
│3 │city │text│0 │NULL │0 │
└───┴──────┴────┴───────┴──────────┴──┘
ds=: sqlread__db 'select * from s' NB. 读取表格s,结果表格形状扁长不适合直接展示
dict=: |: @:> NB. 以字典方式显示表格数据
] rs=: dict ds
┌──────┬──────────────────────────────────┐
│sid │┌──┬──┬──┬──┬──┐ │
│ ││s1│s2│s3│s4│s5│ │
│ │└──┴──┴──┴──┴──┘ │
├──────┼──────────────────────────────────┤
│name │┌─────┬─────┬─────┬─────┬─────┐ │
│ ││smith│jones│blake│clark│adams│ │
│ │└─────┴─────┴─────┴─────┴─────┘ │
├──────┼──────────────────────────────────┤
│status│20 10 30 20 30 │
├──────┼──────────────────────────────────┤
│city │┌──────┬─────┬─────┬──────┬──────┐│
│ ││london│paris│paris│london│athens││
│ │└──────┴─────┴─────┴──────┴──────┘│
└──────┴──────────────────────────────────┘
rs -: sqldict__db 's'
1
cols=: {: @:> NB. 表格数据的诸列列表
cs=: cols ds
cs -: sqlexec__db 's'
1
('s_'&, &.> @ {. @:> ds) =: cs NB. 将表格的诸列并行赋值给添加了表名前缀的诸列名
s_status
20 10 30 20 30
s_sid
┌──┬──┬──┬──┬──┐
│s1│s2│s3│s4│s5│
└──┴──┴──┴──┴──┘
({. @:> ds) -: sqlcols__db 's'
1
reads=: ({. , (,@> &.>)@}.) @:> NB. 格式化显示表格数据
] rs=: reads ds
┌───┬─────┬──────┬──────┐
│sid│name │status│city │
├───┼─────┼──────┼──────┤
│s1 │smith│20 │london│
│s2 │jones│10 │paris │
│s3 │blake│30 │paris │
│s4 │clark│20 │london│
│s5 │adams│30 │athens│
└───┴─────┴──────┴──────┘
$ @ (2&{:: @ {:) rs NB. 第3列数据的形状
5 1
rs -: sqlreads__db 's'
1
readm=: ({. ; <@|:@:(< @ > @ >)@{:) @:> NB. 以矩阵显示表格数据
] rs=: readm ds
┌──────────────────────┬────────────────────┐
│┌───┬────┬──────┬────┐│┌──┬─────┬──┬──────┐│
││sid│name│status│city│││s1│smith│20│london││
│└───┴────┴──────┴────┘│├──┼─────┼──┼──────┤│
│ ││s2│jones│10│paris ││
│ │├──┼─────┼──┼──────┤│
│ ││s3│blake│30│paris ││
│ │├──┼─────┼──┼──────┤│
│ ││s4│clark│20│london││
│ │├──┼─────┼──┼──────┤│
│ ││s5│adams│30│athens││
│ │└──┴─────┴──┴──────┘│
└──────────────────────┴────────────────────┘
rs -: sqlreadm__db 's'
1
cp=: '~addons/data/sqlite/db/sandp.db' ; '~/test_sandp.db'
db=: sqlcopy_psqlite_ cp NB. 复制数据库并打开复本
cls=: sqlcols__db 's' NB. 得到表格s的列名列表
dat=: ('s6';'s7') ; ('brown';'eaton') ; 40 10 ;< 'rome';'madrid'
sqlinsert__db 's' ; cls ;< dat NB. 将数据插入表格s
0
3 sqltail__db 's' NB. 返回最后3个格式化记录
┌───┬─────┬──────┬──────┐
│sid│name │status│city │
├───┼─────┼──────┼──────┤
│s5 │adams│30 │athens│
│s6 │brown│40 │rome │
│s7 │eaton│10 │madrid│
└───┴─────┴──────┴──────┘
sqlclose__db '' NB. 关闭数据库
1
J語言採用命名語境實現類,採用編號語境實現對象,下面示例建立字典類:
cocurrent 'Dict'
create=: {{o [ DEFAULT__o=: 0$0 [ o=. conew 'Dict'}}
get=: {{". 'ITEM_',y}}
set=: {{
('ITEM_',y)=: DEFAULT
:
('ITEM_',y)=: x}}
del=: {{erase 'ITEM_',y}}
pop=: {{r [ del y [ r=. get y}}
default=: {{DEFAULT=: y}}
filt=: {~ I.@:({.@('ITEM_'&E.)@>)
len=: {{# filt namelist 0}}
list=: {{5&}.&.> filt namelist 0}}
in=: {{+/@:(-:&y@>) list ''}}
clear=: {{#@,@:(erase @>) filt namelist 0}}
copy=: {{o=. conew 'Dict'
o [ ".@(,&'__o=:',(5!:5)@<)&.> 'DEFAULT';filt namelist 0}}
destroy=: codestroy
cocurrent 'base'
在家目錄中建立一個dict.ijs
文件並錄入上述代碼,接着以如下代碼建立字典對象並對其進行檢視和簡單操作:
load '~/dict.ijs'
conl 0 NB. 检视命名语境
┌────┬────┬─┬────────┬──────┬─────┬─┐
│Dict│base│j│jcompare│jregex│jtask│z│
└────┴────┴─┴────────┴──────┴─────┴─┘
namelist_Dict_ 3 NB. 检视Dict类的动词
┌─────┬────┬──────┬───────┬───┬───────┬────┬───┬──┬───┬────┬───┬───┐
│clear│copy│create│default│del│destroy│filt│get│in│len│list│pop│set│
└─────┴────┴──────┴───────┴───┴───────┴────┴───┴──┴───┴────┴───┴───┘
d=: create_Dict_ ''
d NB. 变量保存的是盒装字符串
┌─┐
│0│
└─┘
namelist__d 0 NB. 检视d对象的名词
┌─────────┬───────┐
│COCREATOR│DEFAULT│
└─────────┴───────┘
conl 1 NB. 检视编号语境
┌─┐
│0│
└─┘
copath <'0' NB. 检视编号语境的查找路径
┌────┬─┐
│Dict│z│
└────┴─┘
set__d 'i1'
(2 3) set__d 'i2'
2 3
'abc' set__d 'i3'
abc
len__d ''
3
list__d ''
┌──┬──┬──┐
│i1│i2│i3│
└──┴──┴──┘
e=: copy__d ''
get__d 'i2'
2 3
del__d 'i2'
1
in__d 'i3'
1
pop__d 'i3'
abc
clear__d ''
1
list__e ''
┌──┬──┬──┐
│i1│i2│i3│
└──┴──┴──┘
參見
引用
外部連結
Wikiwand - on
Seamless Wikipedia browsing. On steroids.
Remove ads