J語言
J語言,是一種陣列編程語言,由肯尼斯·艾佛森和許國華於1990年代初發明。J語言是APL語言的一種方言[5][6],延續了APL鮮明的簡潔性,它在數學和統計學程式設計上十分高效,特別是在需要進行矩陣運算的場合。
編程範型 | 陣列、隱式、反射式、函數式 |
---|---|
語言家族 | APL |
設計者 | Kenneth E. Iverson、許國華 |
實作者 | JSoftware |
面市時間 | 1990年[1] |
當前版本 |
|
型態系統 | 動態類型 |
操作系統 | 跨平台: Windows, Linux, macOS |
許可證 | GPLv3 |
網站 | www |
主要實作產品 | |
J | |
啟發語言 | |
SHARP APL | |
影響語言 | |
Dyalog APL, NARS2000, BQN, SuperCollider[3] |
J語言最初起步於肯尼斯·艾佛森在1987年發表的《APL字典》[7],它實現了其中至關重要的秩的概念[8]。J語言提供隱式定義機制包括秩、鈎子[9]、叉子[10]和多種函數複合[11],並介入了作為頭等對象的動名詞,用以建立控制結構[12],它常被作為隱式編程的典範之一[13]。
簡介
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]。
文檔與詞類
J語言的文檔包括在官網的NuVoc中[37],在其中將主要的字羅列為「J原語」,並使用顏色標示出它們分別的詞類[38]。早期的文檔還有入門和字典。在J語言中的字,被識別為名詞[39]、動詞[40]、定語[41](副詞和連詞)、系詞、標點、控制字。一個程序或例程,如果接受數據作為輸入並產生數據作為輸出,則被稱為「動詞」,與之相對,數據參數被稱為「名詞」。
J術語 | APL術語 |
---|---|
名詞 | 陣列 |
動詞 | 函數 |
副詞,連詞 | 算子 |
字母 | 字符集 |
單詞構成 | 詞法分析(lexing) |
標點 | 控制結構,括號界定等 |
句子 | 表達式 |
字典 | 參考手冊 |
雋語(epigram) | 單行代碼(one-liner) |
動詞有兩種形式:只有右側一個參數的一元(monad)形式,和有左右兩側參數的二元(dyad)形式,例如在-1
中減號是一元動詞,而在3-2
中減號是二元動詞。J語言預定義了很豐富的動詞,它們都自動的作用於多種數據類型之上。用戶定義的程序可以自行命名,並用在任何允許使用原始動詞的地方。無論原始動詞還是派生動詞,它們的一元定義與二元定義,在很大程度上是獨立的。
起步示例
J語言可以寫出非常精簡的程序,特別是存在重度的對符號的函數重載,以至於一些編程者將它稱為難以閱讀的只寫語言。在計算機的終端上執行ijconsole
,即可進入J語言的REPL解釋器界面。
Hello, World!
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!
平均
在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),它在後面的定語章節和單獨條目中論述。
查找與排序
二元動詞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
CSV插件
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
數據類型
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詞彙 | APL 符號 |
詞類 | 秩 | 含義 | 例子 |
---|---|---|---|---|---|
= |
動詞 | 0 0 |
(二元)等於(equal) | 3 = i. 5
| |
< |
< |
動詞 | 0 0 |
(二元)小於(lesser) | 8 < 7 8 9
|
⊂ |
動詞 | _ |
(一元)盒裝(box)[注 1] | (< i. 2 3) , < i. 3 2
| |
> |
> |
動詞 | 0 0 |
(二元)大於(greater) | 8 > 7 8 9
|
↑ |
動詞 | 0 |
(一元)打開(open)[注 2] | > (i. 2 3) ; i. 3 2
| |
<: |
≤ |
動詞 | 0 0 |
(二元)小於等於(less or equal)[注 3] | 8 <: 7 8 9
|
>: |
≥ |
動詞 | 0 0 |
(二元)大於等於(larger or equal)[注 3] | 8 >: 7 8 9
|
~. |
∪ |
動詞 | _ |
(一元)唯一值(nub) | ~. 'abracadabra'
|
~: |
動詞 | _ |
(一元)唯一值篩選(nub sieve) | ~: 'abracadabra'
| |
≠ |
動詞 | 0 0 |
(二元)不等於(not-equal) | 3 ~: i. 5
| |
L. |
≡ |
動詞 | _ |
(一元)最大盒裝層數(level of) | L. (<1),(<<2),<<<3
|
-: |
動詞 | _ _ |
(二元)匹配(match)[注 3] | 'no' -: 'yes'
| |
e. |
∊ |
動詞 | _ _ |
(二元)成員關係(member/in) | 'a' e. 'alpha'
|
E. |
⍷ |
動詞 | _ _ |
(二元)尋找匹配子陣列起點(find match) | 'co' E. 'cocoa'
|
數學
J詞彙 | APL 符號 |
詞類 | 秩 | 含義 | 例子 |
---|---|---|---|---|---|
+ |
動詞 | 0 0 0 |
共軛複數(conjugate)· 加(plus) | 2 + 3 30
| |
+. |
動詞 | 0 |
(一元)實部/虛部(real/imaginary) | +. 3j5
| |
∨ |
動詞 | 0 0 |
(二元)最大公約/或(GCD/or) | 0 0 1 1 +. 0 1 0 1
| |
+: |
動詞 | 0 |
(一元)雙倍(double) | +: 7
| |
⍱ |
動詞 | 0 0 |
(二元)或非(not-or) | 0 0 1 1 +: 0 1 0 1
| |
* |
× |
動詞 | 0 0 0 |
符號函數(signum)· 乘(times) | 3 30 * 2
|
*. |
動詞 | 0 |
(一元)模長/幅角(length/angle) | *. 3j4
| |
∧ |
動詞 | 0 0 |
(二元)最小公倍/與(LCM/and) | 0 0 1 1 *. 0 1 0 1
| |
*: |
動詞 | 0 |
(一元)平方(square) | *: 7
| |
⍲ |
動詞 | 0 0 |
(二元)與非(not-and) | 0 0 1 1 *: 0 1 0 1
| |
- |
− |
動詞 | 0 0 0 |
相反數(negate)· 減(subtract) | 1 10 - 5 6
|
-. |
∼ |
動詞 | 0 _ _ |
非(not)· 差(less) | -. 0 1
|
-: |
動詞 | 0 |
(一元)一半(halve)[注 1] | -:7
| |
% |
÷ |
動詞 | 0 0 0 |
倒數(reciprocal)· 除(divide) | 2 3 5 % 3 4 6
|
%: |
動詞 | 0 0 0 |
平方根(square root)· 方根(root) | %: 49
| |
| |
動詞 | 0 0 0 |
幅值(magnitude)· 餘數(residue) | 2 | i. 7
| |
<. |
⌊ |
動詞 | 0 0 0 |
下取整(floor)· 極小(minimum) | 2 3 4 <. 9 1 2
|
>. |
⌈ |
動詞 | 0 0 0 |
上取整(ceiling)· 極大(maximum) | >. 1.1 0.5 1.9
|
<: |
動詞 | 0 |
(一元)減少(decrement)[注 1] | <: 7 8 9
| |
>: |
動詞 | 0 |
(一元)增加(increment)[注 1] | >: 7 8 9
| |
^ |
⋆ |
動詞 | 0 0 0 |
指數(exponential)· 冪(power) | 2 ^ i. 17
|
^. |
⍟ |
動詞 | 0 0 0 |
自然對數(natural log)· 對數(log) | 2 10 ^. 4 100
|
o. |
○ |
動詞 | 0 0 0 |
乘以(pi times)· 圓函數(circle function) | sin=: 1&o.
|
j. |
動詞 | 0 0 0 |
乘以(imaginary)· 形成複數(complex) | 3 j. 4
| |
! |
動詞 | 0 0 0 |
階乘(factorial)· 抽取(out of) | 2 ! 10
| |
? |
動詞 | 0 0 0 |
擲骰(roll)· 發牌(deal) | 3 ? 10
| |
#. |
⊥ |
動詞 | 1 1 1 |
基數2(base 2)· 基數(base) | _ 60 60 #. 24 0 1
|
#: |
⊤ |
動詞 | _ 1 0 |
反基數2(antibase 2)· 反基數(antibase) | 24 60 60 #: 86401
|
. |
連詞 | 2 |
(一元)行列式(determinant)[注 2] | (-/ . *) i. 3 3
| |
. |
連詞 | _ _ |
(二元)矩陣積(matrix product)[注 3] | (i. 3 2) (+/ . *) i. 2 3
| |
%. |
⌹ |
動詞 | 2 _ 2 |
逆矩陣(matrix inverse)· 矩陣除(matrix divide) | %. ? 3 3 $ 10
|
結構
J詞彙 | APL 符號 |
詞類 | 秩 | 含義 | 例子 |
---|---|---|---|---|---|
$ |
⍴ |
動詞 | _ 1 0 |
形狀(shape of)· 重製形狀(reshape) | 2 2 4 $ 1 2 11 22
|
|. |
⊖ ⌽ |
動詞 | _ _ _ |
反轉(reverse)· 旋轉(rotate) | |. 2 |. i. 6 2
|
|: |
⍉ |
動詞 | _ 1 _ |
轉置(transpose)· 重排軸(rearrange axes)[注 1] | |: 'abc' ,: 'def'
|
, |
, |
動詞 | _ |
(一元)散開(ravel) | , i. 2 3 4
|
⍪ |
動詞 | _ _ |
(二元)附加(append) | (i. 2 3) , i. 3 2
| |
,. |
動詞 | _ |
(一元)散開項目(ravel items)[注 2] | ,. i. 2 3 4
| |
, |
動詞 | _ _ |
(二元)縫合(stitch) | (i. 2 3) ,. i. 2 4
| |
,: |
動詞 | _ _ _ |
項目化擴秩(itemize)· 疊加(laminate)[注 3] | (i. 2 3) ,: i. 3 2
| |
; |
動詞 | _ _ _ |
拆除(raze)[注 4]· 鏈接(link)[注 5] | ; (i. 2 3) ; i. 3 2
| |
;.±1 ;.±2 |
副詞 | _ |
(一元)自有區間(self intervals)[注 6] | <;._1 ' a b c'
| |
⊂ |
副詞 | 1 _ |
(二元)區間(intervals)[注 7] | 1 0 1 0 0 <;.1 'abcde'
| |
;.±3 |
⌺ |
副詞 | 2 _ |
(二元)子陣列鑲嵌(subarrays) | (2 2,:2 4) <;.3 i. 5 6
|
;: |
動詞 | 1 |
(一元)劃分單字(words) | ;: 'ab cde'
| |
選取
J詞彙 | APL 符號 |
詞類 | 秩 | 含義 | 例子 |
---|---|---|---|---|---|
# |
≢ |
動詞 | _ |
(一元)計數(tally)[注 1] | # 1 2 3
|
⌿ / |
動詞 | 1 _ |
(二元)計件複製(copy)[注 2] | 1 0 2 # 1 2 3
| |
{. |
動詞 | _ |
(一元)頭部(head)[注 3] | {. 'foot'
| |
↑ |
動詞 | 1 _ |
(二元)採取(take) | 3 {. 'foot'
| |
}. |
動詞 | _ |
(一元)斷頭(behead) | }. 1 2 3 4
| |
↓ |
動詞 | 1 _ |
(二元)捨棄(drop) | 2 }. 1 2 3 4
| |
{: |
動詞 | _ |
(一元)尾部(tail) | {: 'foot'
| |
}: |
動詞 | _ |
(一元)截短(curtail) | }: 1 2 3 4
| |
索引
J詞彙 | APL 符號 |
詞類 | 秩 | 含義 | 例子 |
---|---|---|---|---|---|
i. |
⍳ |
動詞 | 1 _ _ |
整數生成(integers)[注 1]· 出現索引(index of) | i. 10
|
i: |
動詞 | 0 _ _ |
階梯序列(steps)· 最後出現索引(index of last) | 'abcd' i: 'c'
| |
I. |
⍸ |
動詞 | 1 _ _ |
真值位置索引(indices)· 區間索引(interval index) | I. 0 0 1 0 1 0
|
/: |
⍋ |
動詞 | _ |
(一元)升序索引(grade up) | ({~ /:) 10 ? 20
|
動詞 | _ _ |
(二元)上升排序(sort up) | /:~ 10 ? 20
| ||
\: |
⍒ |
動詞 | _ |
(一元)降序索引(grade down) | ({~ \:) 10 ? 20
|
動詞 | _ _ |
(二元)下降排序(sort down) | \:~ 10 ? 20
| ||
{ |
動詞 | 1 |
(一元)目錄匯編(catalogue) | { 0 1 ; 2 3 4 ; 5 6
| |
⌷ |
動詞 | 0 _ |
(二元)出自(from) | 2 4 { 'abcde'
| |
} |
@ |
副詞 | _ _ |
(二元)修改(amend) | 'gw' 0 3} 'cross'
|
{:: |
⊃ |
動詞 | 1 _ |
(二元)獲取(fetch) | 1 {:: (<1),(<<2),<<<3
|
|
算子
J詞彙 | APL 符號 |
詞類 | 秩 | 含義 | 例子 |
---|---|---|---|---|---|
/ |
∘. |
副詞 | _ _ |
(二元)形成表格(table)[注 1] | */~ >: i. 6
|
⌿ / |
副詞 | _ |
(一元)插入(insert) | ([ + 2&*@])/ 1 10 100
| |
\ |
副詞 | _ _ |
(二元)中綴(infix)[注 2] | 3 <\ 'abcdefg'
| |
⍀ \ |
副詞 | _ |
(一元)前綴(prefix) | ]\ 'banana'
| |
\. |
副詞 | _ _ _ |
後綴(suffix)· 外綴(outfix) | _1 ]\. 1 2 3 4
| |
/. |
副詞 | _ |
(一元)斜對角(oblique) | </. i. 4 4
| |
⌸ |
副詞 | _ _ |
(二元)鍵分組(key) | 1 0 0 1 0 </. 'AbcDe'
| |
~ |
⍨ |
副詞 | _ lu ru |
返身(reflex)· 被動(passive) | +~ 1 2 3
|
" |
⍤ |
連詞 | 秩(rank) | +/"1 i. 2 3 4
| |
@: |
連詞 | _ _ _ |
在於(at) | [注 3] | |
@ |
連詞 | mv lv rv |
頂上(atop) | ||
& |
連詞 | mv mv mv |
合成(compose) | ||
∘ |
連詞 | _ 0 _ |
粘上(bond) | ||
&: |
⍥ |
連詞 | _ _ _ |
並列(appose) | |
&. |
連詞 | mv mv mv |
對偶(dual) | ||
&.: |
⍢ |
連詞 | _ _ _ |
底下(under) | |
@. |
連詞 | mv lv rv |
議程(agenda) | ||
` |
連詞 | 連結動名詞(tie or gerund) | |||
`: |
連詞 | _ _ _ |
喚起動名詞 (evoke gerund) | ||
^: |
⍣ |
連詞 | _ _ _ |
動詞冪(power of verb) | +: ^:(6&<)"0 ] 5 12
|
!. |
⍠ |
連詞 | mu lu ru |
調整/定製(fit/customize) | 2 |.!._ i. 6
|
!: |
) |
連詞 | 0 0 0 |
外界(foreign)/系統函數 | 6!:0 ''
|
雜類
J詞彙 | APL 符號 |
詞類 | 秩 | 含義 | 例子 |
---|---|---|---|---|---|
=. |
← |
系詞 | 是(is),局部作用域(local) | loc=. 1 2
| |
=: |
系詞 | 是(is),全局作用域(global) | 'a b' =: 3 ; 4
| ||
NB. |
⍝ |
系詞 | 注釋(comment) | NB. for comments
| |
'字符串' |
名詞 | 字符串(character string) | 'Hello, World!'
| ||
_ |
¯ ∞ |
名詞 | 負號(negative sign)/ 無窮(infinity) | _3 = -3
| |
0$0 |
⍬ |
空數值向量(empty numeric vector) | $ 0$0
| ||
a: |
名詞 | 麼點即盒裝空值(boxed empty) | a: -: <0$0
| ||
[ |
⊣ |
動詞 | _ _ _ |
相同(same)· 左參數(left) | p=: 3 [ q=: 5
|
] |
⊢ |
動詞 | _ _ _ |
相同(same)· 右參數(right) | i."0 ] 3 4 5
|
[: |
動詞 | 遮帽(cap) | ({~ [: ? #) 3 1 4
| ||
". |
⍎ |
動詞 | 1 _ _ |
執行(do)· 數值(numbers) | 9999 ". '56 NULL'
|
": |
⍕ |
動詞 | _ 1 _ |
缺省格式(default format)· 格式(format) | 10j2 ": 6
|
{{ }} |
{ } |
控制 | 直接定義(direct definition) | dist=: {{%:+/*:x-y}}
| |
: |
∇ |
連詞 | 定義(definition) | add=: 0&$: : {{x+y}}
| |
$: |
動詞 | _ _ _ |
自引用(self-reference) | fact=: 1:`(* $:@<:)@.*
|
定語
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],二種隱形連詞和四種複合連詞,規定了如何將參數或將所飾動詞應用於參數的結果,提供給所飾動詞來進行應用的規則。下表列出它們的定義:
連詞 | APL 符號 |
一元 | 二元 | 秩 |
---|---|---|---|---|
鈎子 | (u v) y ↔ y u (v y) |
x (u v) y ↔ x u (v y) |
_ _ _
| |
叉子 | (f g h) y ↔ (f y) g (h y) |
x (f g h) y ↔ (x f y) g (x h y) |
_ _ _
| |
@: |
⍤ |
(u @: v) y ↔ u (v y) |
x (u @: v) y ↔ u (x v y) |
_ _ _
|
@ |
(u @ v) y ↔ (u @: v)"v y |
x (u @ v) y ↔ x (u @: v)"v y |
mv lv rv
| |
&: |
⍥ |
同於@: 而應棄用 |
x (u &: v) y ↔ (v x) u (v y) |
_ _ _
|
& |
同於@ 而應棄用 |
x (u & v) y ↔ x (u &: v)"mv y |
mv mv mv
|
在上面表格中,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),它通過向二元動詞固定提供其一個參數的值而產生一個動詞:
連詞 | APL 符號 |
秩 |
---|---|---|
& |
∘ |
_ 0 _
|
&
派生的動詞經常作為一元動詞使用,即m&v y
或u&n y
;如果作為二元動詞使用,即x m&v y
或x u&n y
,左參數表示應用這個派生動詞於右參數的次數。需要確保通過&
定義的一元動詞,不出現在能夠取用左右兩個的參數的上下文中;如此定義的二元動詞,也不應該出現在只能取用一個右參數的上下文中。需要注意m&v
、v/
和v\
等的左參數的作用域,有時遇到其左側的複合連詞會產生並非預期的效果,經常需要將表達式整體加以圓括號包圍。
J語言還提供連詞&.:
「底下」(under)和&.
「對偶」(dual)[56]。下面定義中的動詞冪^:_1
表示逆運算:
連詞 | APL 符號 |
定義 | 秩 |
---|---|---|---|
&.: |
⍢ |
u &.: v ↔ v^:_1 @: u &: v |
_ _ _
|
&. |
u &. v ↔ (u &.: v)"mv |
mv mv mv
|
@
、&
和&.
合稱為「緊密複合」(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]。這裡列出的是每個範疇內的代表性控制字:
範疇 | 控制結構 |
---|---|
斷言觸發 | assert.
|
返結果退出 | return.
|
跳轉到標號 | goto_lbl. label_lbl.
|
條件執行 | if. T do. B else. B1 end.
|
情況執行 | select. T case. T0 do. B0 end.
|
條件循環 | while. T do. B end.
|
逐項執行 | for_ijk. A do. B end.
|
終止循環 | break.
|
終止本次迭代 | continue.
|
嘗試執行捕獲異常 | try. B catch. B1 end.
|
拋出異常 | throw.
|
索引
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
SQLite插件
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│
└──┴──┴──┘
參見
引用
- ^ Roger K.W. Hui, Kenneth E. Iverson, E. E. McDonnell, Arthur T. Whitney. APL\?. 1990 [2022-06-12]. (原始內容存檔於2022-06-14).
This paper describes a version of APL based upon the dictionary, but significantly simplified and enhanced, and directly usable on any machine that provides ASCII characters. It also describes salient features of a C implementation that has been tested on several machines, and is available as freeware.
- ^ https://code.jsoftware.com/wiki/System/ReleaseNotes/J9.5.
- ^ SuperCollider documentation, Adverbs for Binary Operators. [2020-04-18]. (原始內容存檔於2020-12-11).
- ^ Release Notes J9.4. [2023-03-25]. (原始內容存檔於2023-05-08).
- ^ K. E. Iverson. A Personal View of APL. 1991 [2022-06-12]. (原始內容存檔於2022-06-12).
Roger and I then began a collaboration on the design and implementation of a dialect of APL (later named J by Roger), first deciding to roughly follow 「A Dictionary of APL」 and to impose no requirement of compatibility with any existing dialect. We were assisted by suggestions from many sources, particularly in the design of the spelling scheme (E.B. Iverson and A.T. Whitney) and in the treatment of cells, items, and formatting (A.T. Whitney, based on his work on SHARP/HP and on the dialect A reported at the APL89 conference in New York).
- ^ Roger K. W. Hui, Morten J. Kromberg. APL since 1978. Proceedings of the ACM on Programming Languages, Volume 4, Issue HOPL. 2020 [2022-06-20]. (原始內容存檔於2022-07-10).
In 1989, Iverson, together with Roger Hui and with input from Arthur Whitney, produced J, with a goal of providing a 「shareware」 APL implementation for use in teaching. The special APL characters were abandoned because it was felt that they require technical solutions which at that time were still prohibitively expensive in an educational environment. ……
J was clearly a 「rationalization」 of SHARP APL. ……
ACM SIGAPL, the ACM Special Interest Group on APL, reinterpreted the 「APL」 in its name in early 2009 as Array Programming Languages, so that J, k, Nial, etc. would be included in its purview. - ^ Kenneth E. Iverson. A Dictionary of APL. 1987 [2022-06-08]. (原始內容存檔於2022-06-12).
A dictionary should not be read as an introduction to a language, but should rather be consulted in conjunction with other material that uses the language in some context of interest to the reader. Even the general section on grammar, which may be intelligible even to the beginner, should perhaps be studied only after a certain amount of other exposure to the language.
On the other hand, a dictionary should not be used only to find the meanings of individual words, but should also be studied to gain an overall view of the language. In particular, the grammar may be profitably reviewed again and again in the light of increased knowledge of the language, and the study of groups of related verbs and adverbs can reveal important relationships otherwise easily overlooked. - ^ Kenneth E. Iverson. Operators and Functions. 1978 [2022-06-21]. (原始內容存檔於2022-06-24).
Nuclear Axis Operators - The nuax operator (denoted by
⍤
) applies to a function left argument and a variable right argument to specify the axes which define the nuclei to which the function is to apply. ……The coax operator⍥
is also provided; its argument specifies the axes complementary to the nuclear axes.
Kenneth E. Iverson. Rationalized APL. 1983 [2022-06-19]. (原始內容存檔於2022-07-22).In conventional APL, the scalar functions (which apply to scalar elements and produce scalar results) extend to higher rank arrays according to simple general rules; no corresponding general rules exist for the remaining so-called mixed functions. ……
Function rank is the most important notion needed to provide a simple and systematic basis for the uniform treatment of all 「mixed」 or non-scalar functions. ……
Iff
has rankr
, thenf⍵
is determined by applyingf
to each of the 「cells」 of shape(-r)↑⍴⍵
, producing a common shapes
for each, and assembling the whole into a result of shape((-r)↓⍴⍵),s
. ……
If the functiong←f⍤r
is to be applied dyadically as well as monadically (the only cases addressed in the preceding sections), then it is necessary thatr
specify three independent ranks, the monadic, the left, and the right. The general argumentr
is therefore a three-element vector that specifies the ranks in the order just indicated. Moreover,r
is extended by reshape if necessary, so thatf⍤r ←→ f⍤(⌽3⍴⌽r)
. - ^ 9.0 9.1 Kenneth E. Iverson, Eugene McDonnell. Phrasal Forms. APL 89 Conference Proceedings. August 1989 [2022-06-09]. (原始內容存檔於2022-06-12).
In combinatory logic one of the most useful primitive combinators is designated by
S
[Sch24]. Curry definesSfgx
in prefix notation to befx(gx)
[CuFeCr74]. In common mathematical infix notation this would be given by(x)f(g(x))
, which one can write in APL asxfgx
, and this is the hook form(fg)x
. The combinatory logician appreciates this form because of its great expressiveness: it can be shown thatS
, along withK
, the constancy combinator, suffice to define all other combinators of interest [Ro50]. (The constancy combinatorK
is defined in infix notation so thatcKx
has the valuec
for allx
.) Users of APL will appreciate the hook for the same reasons. - ^ 10.0 10.1 Kenneth E. Iverson, Eugene McDonnell. Phrasal Forms. APL 89 Conference Proceedings. August 1989 [2022-06-09]. (原始內容存檔於2022-06-12).
Curry [Cu31] defines a formalizing combinator,
Φ
, in prefix notation, such thatΦfghx
meansf(gx)(hx)
. In common mathematical infix notation this would be designated by(g(x))f(h(x))
. An example of this form isΦ+sin2cos2θ
, meaningsin2θ+cos2θ
. The fork(f g h)⍵
has the same meaning, namely(f⍵)g(h⍵)
. Curry named this the formalizing combinator because of its role in defining formal implication in terms of ordinary implication.
Iverson and Whitney have made several earlier suggestions of ways to achieve what the fork form provides: the scalar operators of [Iv78], [Iv79a], [Iv 79b], the til operator of [Iv82], the union and intersection conjunctions of [Iv87], and the yoke adverb of [Iv88]. Benkard [Bk87] has also suggested a way to achieve the meaning of this form, in his proposal for↑g/(f h)⍺ ⍵
, using the notion of function pair (↑
is APL2’s first function). The present proposal has significant advantages over these earlier ones. - ^ Roger K.W. Hui, Kenneth E. Iverson, Eugene E. McDonnell. Tacit Definition. 1991 [2022-06-11]. (原始內容存檔於2022-07-06).
To appreciate the more general use of tacit definition, it is necessary to understand three key notions of J: cells and rank, forks, and composition.……
The conjunction&
is called with, and applies to nouns (variables)a
andb
as well as to verbsf
andg
as follows:
a&g y
isa g y
f&b y
isx f y
f&g y
isf g y
x f&g y
is(g x) f (g y)
……
A number of other constructs in J similarly enhance the utility of tacit definitions. The more important are the under (or dual), atop (a second form of composition), the power conjunction^:
, and further forms of partitions.
Jsoftware. Changes in Version 3.2, 1991 06 02. 1991 [2022-11-07]. (原始內容存檔於2022-06-14).@.
agenda@:
at&:
appose - ^ Robert Bernecky, Roger K. W. Hui. Gerunds and representations. 1991 [2022-06-12]. (原始內容存檔於2022-06-12).
Gerunds, verbal forms that can be used as nouns, are recognized as having utility in the realm of programming languages. We show that gerunds can be viewed as arrays of atomic repmentations of verbs (functions), in a way which is consistent with the syntax and semantics of APL, and which allows verbs to be first class objects in the language. We define derivations of verbs from gerunds in the J dialect of APL, and show how these derivations provide control structures for sequencing, selection (in the sense of generalized forms of CASE or SWITCH statements and IF/THEN/ELSE), iteration (DO UNTIL), recursion, and parallel computation (MIMD, or Multiple Instruction, Multiple Data). We conclude with alternative representations of verbs which are useful in other contexts.
Jsoftware. Changes in Version 4.0, 1991 11 23. 1991 [2022-06-12]. (原始內容存檔於2022-06-14).`:1
replaced byu^:v
`:4
replaced bym~
`:5
replaced by@.
- ^ 13.0 13.1 Roger K. W. Hui, Morten J. Kromberg. APL since 1978. Proceedings of the ACM on Programming Languages, Volume 4, Issue HOPL. 2020 [2022-06-20]. (原始內容存檔於2022-07-10).
For years, Iverson struggled to achieve in APL the effect of
f+g
andf×g
as they are written in calculus. …… Finally, trains AKA forks were invented [Iverson and McDonnell 1989]. ……
Moreover,(f … h p q r) ↔ (f … h (p q r))
, and an isolated sequence of two functions is also assigned a meaning (atop, described below), so that a train of any length, even or odd, is interpreted. ……
Subsequently, it was realized that trains greatly increase the possibilities for 「tacit definition」, expressions consisting of compositions of functions which do not explicitly mention the arguments [Hui et al. 1991]. Trains are implemented in several dialects: J [Hui et al. 1991], NARS2000 [Smith 2020], NGN APL [Nickolov 2013], and Dyalog APL [Scholes 2013]. ……
The expressive completeness of trains depends on an atop composition of two functions …… Dyalog APL defines 2-trains as atop. That, together with the functions⊣
(left) and⊢
(right), allows many common compositions to be written as trains. - ^ Roger Hui earns the Iverson Award. [2022-07-30]. (原始內容存檔於2022-07-30).
- ^ Vocabulary/Words. [2020-05-18]. (原始內容存檔於2016-03-07).
- ^ 16.0 16.1
Kenneth E. Iverson. Rationalized APL. 1983.
The enclose function as defined in [Operators and Enclosed Arrays] has made it possible to produce by straightforward APL functions the 「index lists」 required in indexing expressions of the form
a[i;j]
, and therefore makes it possible to define a corresponding indexing function, which will be denoted by{
and called from:
i{a ←→ a[>i[0];>i[1]; ...]
Since the disclose function>
is permissive, the selection of any single element of a can be written without enclosures as, for example,1 2 3{a3
. Moreover, the left rank of{
is1
and its right rank is infinite, so that …… a simple left argumenti
of rank greater than1
produces an array of shape¯1↓⍴i
of elements chosen by the index vectors along its last axis, yielding what is sometimes called 「scattered」 indexing. For examp1e:
(3 2⍴⍳6){a2 ←→ a2[0;1],a2[2;3],a2[4;5]
……
In forming the left arguments of the indexing function, it will often be convenient to use the link function⊃
defined as follows:
⊃b ←→ <b
ifb
is simple
b
ifb
is non-simple
a⊃b ←→ (<a),⊃b
For example,(2 3⊃4⊃∘⊃5 6){a4 ←→ a[2 3;4;;5 6]
.
The indexing function{
as defined thus far provides all of the facilities provided by conventional indexing, and 「scattered」 and 「complementary」 indexing as well. Its power is further enhanced by allowing negative indexing …….
Roger Hui. Some Uses of { and }. 1987.Dyadic
{
encompasses all computations expressible by[;]
indexing of APL\360, as well as the new negative indexing and complementary indexing. - ^ 17.0 17.1 IBM. APL Language (PDF). June 1976 [2022-07-02]. (原始內容存檔 (PDF)於2019-09-26).
For vectors
R
andX
, the decode(or base-value) functionR⊥X
yields the value of the vector X evaluated in number system with radicesR[1],R[2],...,R[⍴R]
. ……
Scalar(or one-element vector) arguments are extended to conform, as required. ……
the decode function is extended to arrays in the manner of the inner product: each of the radix vectors along the last axis of the first argument is applied to each of the vectors along the first axis of the second argument.
J語言的#.
並未繼承IBM對APL解碼函數⊥
的擴展規定,它可以實現為:decode=: {{x #."(1 _) (0|: y)}}
- ^ 18.0 18.1
Kenneth E. Iverson. Operators and Functions. 1978 [2022-06-21]. (原始內容存檔於2022-06-24).
We also introduce a form of indexing called from denoted by
⌷
, ……. The basic definition is:
i⌷a ↔ (,a)[⍉(⍴a)⊥⍉i]
The function⌷
distributes over any scalar function; thus,i⌷a+b ↔ (i⌷a)+(i⌷b)
. …… For example:
m←3 4⍴⍳12
m
0 1 2 3
4 5 6 7
8 9 10 11
2 2 ⌷ m
10
……
(3 2⍴3|⍳6)⌷m
1 8 6
J語言在定義上述的⌷
(from)之時,解碼前後不需要專門進行一元轉置⍉
運算:from=: {{(($ y) #. x) {::"(0 _) (, y)}} ]m=: 3 4$i.12 0 1 2 3 4 5 6 7 8 9 10 11 2 2 from m 10 3 2$3|i.6 0 1 2 0 1 2 (3 2$3|i.6)from m 1 8 6
- ^ IBM. APL Language (PDF). June 1976 [2022-07-02]. (原始內容存檔 (PDF)於2019-09-26).
APL functions apply to collections of individual items called arrays. Arrays range from scalars, which are dimensionless, to multi-dimensional arrays of arbitrary rank and size.
- ^
Bob Smith. Nested arrays, operators, and functions. 1981 [2022-06-19]. (原始內容存檔於2022-06-20).
The data structures of APL are rectangular, multi-dimensional, and flat -- the latter term meaning that all items of arrays are simple scalars. ……
In general, a system with nested arrays extends the power of APL by being able to represent data of non-zero depth. Also, in keeping with the past, the system includes a set of primitive functions and operators, tailor-made for manipulating these new data structures.
Continuing the above example, the names of the months of the year are best represented in a 12-item vector whose items are each character vectors. This structure has a depth of one. Note that because the individual names are in separate items, we need no longer resort to artifices like pad characters. Moreover, explicit delimiters are not needed as the separation between items is represented through structure rather than data. This particular representation is called a vector of vectors, and can be created as follows:
MONTHS ← ('JANUARY') ('FEBRUARY') ...
The above line also illustrates strand notation, used to enter a nested vector in a simple and convenient manner. ……
Of the several new operators, the only one specific to nested arrays is the each operator(symbol¨
), which is monadic as an operator, and produces an ambivalent derived function. It is used to apply the f unction which is its argument to the items of an array to produce corresponding items in the result. For example, to determine the length of the names of the months in the above example, use
⍴¨MONTHS
(7) (8) (5) (5) (3) (4) (4) (6) (9) (7) (8) (8)
Since monadic rho returns a vector , each item of the above result is a vector (specifically in these cases a one-item vector). The parentheses in the display indicate that the item is not a simple scalar. - ^ James A. Brown. The Principles of APL2. TR 03.247. IBM Santa Teresa Laboratory, San Jose, California. 1984 [2022-06-23]. (原始內容存檔於2022-06-12).
APL2 is based on this writer' s PhD Thesis [Br1], the array theory of Trenchard More [Mo1] and most of all on APL1. ……
The arrays of APL2 are finite rectangular arrays which contain arrays as items. When the term array is used, it means this subset of all possible arrays.
The arrays of APL2 are the same as the arrays of Array Theory and in particular empty arrays have structure as defined by Array Theory [Mo1 etc.].
An array one of whose items is other than a single number or character (a simple scalar) is called a nested array. An array containing only numbers or containing only characters is called a homogeneous array. An array all of whose items are either single numbers or single characters is called a simple array. The arrays of APL1 are simple and homogeneous.
In some sense every array in APL2 is nested because it contains other arrays. The term is reserved for those which contain at least one item which is not a single number or character. Thus the universe of arrays is partitioned into two subsets: simple arrays and nested arrays. ……
A function is pervasive if pick distributes over it. ……
Since the pick function may select an item at an arbitrary depth in a nested array, it may select deep enough to access a simple scalar (because nested arrays have finite depth). Thus a pervasive function may be thought of as applying independently to each simple scalar in its argument(s). ……
In APL2 the scalar functions and only the scalar functions are pervasive. - ^ 22.0 22.1 Kenneth E. Iverson. Operators and Functions. 1978 [2022-06-21]. (原始內容存檔於2022-06-24).
The enclose function (denoted by
<
) produces a scalar representation of its argument in the sense that the result is of rank zero, and that there exists an inverse function (called disclose, and denoted by>
) such thata ↔ ><a
for alla
. Any result producible by an expression which does not employ the enclose function is called a simple array, or is said to be simple.
Selection and reshaping functions apply without change to non-simple arrays. However, non-simple arrays are outside the domain of all other functions except for enclose, disclose, and equality (together with those functions such as≠
and∊
which are defined in terms of equality).
The equality function is extended to non-simple scalar arguments as follows:
1.(<a)≠a
for alla
2. Ifa
equalsb
(in rank, shape, and all elements), then(<a)=(<b)
yields1
……
The disclose function is scalar in the sense that it applies to each element of its argument, the new axes disclosed becoming the final axes of the result. ……
The disclose function applied to a simple arraya
produces a result identical toa
. Thus(<a)=<>a
is a test for whethera
is simple. - ^
Kenneth E. Iverson. Rationalized APL. 1983.
APL2 provides two significant facilities which apply at 「depth」 in the enclosure structure of an argument, the dyadic pick function, and the pervasive functions. RS provides no primitive corresponding to pick; it could be defined recursively by:
pick←''∇('→2+0=⍴⍺'⊃'(>0{⍺){(1↓⍺)∆⍵'⊃'⍵')
……
Since pervasiveness is a property assigned to functions, it would, in the framework of RS, be provided by an operator. Such an operator could be applied to any function (defined or derived as well as primitive) and, if defined to be dyadic, could provide greater variety. ……
If each essential space in an expression is counted as a character, then the link function and strand notation used to form non-simple vectors from simple vectors require expressions of nearly identical length. ……
RS does not include the heterogeneous arrays of APL2, and the production of equivalent constructs requires greater use of enclosure. However, the structure of RS does not preclude their introduction. ……
The monadic enclose functions defined in RS (<
) and in APL2 (⊂
) differ in one respect: ifs
is a simple scalar, thens≡⊂s
, but~s≡<s
. Although<
can therefore produce some structures not producible by⊂
, the differences between them (in the contexts of the respective systems) cannot, in most cases, be discerned. - ^ Guides/AVX. [2021-12-20]. (原始內容存檔於2021-12-20).
- ^ Roger K. W. Hui, Morten J. Kromberg. APL since 1978. Proceedings of the ACM on Programming Languages, Volume 4, Issue HOPL. 2020 [2022-06-20]. (原始內容存檔於2022-07-10).
In order to provide users with access to APIs and frameworks, APL language designers searched for ways to integrate into APL, where everything is an array, selected aspects of the OO paradigm, where everything is an object. ……
Some interpreters, like APL+Win, avoided incorporating objects into the APL heap (or 「workspace」). ……
Other systems added features which allowed variables, functions and operators to be organized in dynamic objects in the workspace. The resulting containers are known as namespaces (Dyalog APL) and locales (J). k implements dictionaries, which are also containers for arrays, but are typically used to contain arrays representing the columns of a relational table. …… The same language features which supported namespaces or classes within APL were used to wrap the external objects used by object oriented APIs, or platforms like the Microsoft’s OLE and .NET frameworks.
The choice of syntax for referring to a membername
of an objectemp
was not straightforward. ……
Most APL systems did adopt the notation from other OO languages — with a few exceptions.
emp.name
in most APL systems
name__emp
in J (retaining right-to-left evaluation)
emp[`name]
in k (using a symbol within index brackets to select from a dictionary)
……
Although APL interpreters have had extensive support for object oriented programming for nearly two decades, most APL users still feel that object and array paradigms are an awkward fit. …… Many of the benefits of OO are related to taking advantage of types, while much of the strength of the APL family is that you can write code which is shape, rank, and type agnostic — achieving many of the same goals as OO through radically different mechanisms. - ^ 语境. [2022-09-29]. (原始內容存檔於2022-09-29).
- ^ 27.0 27.1 Chris Burke. J4 and OOP. 1998 [2022-11-08]. (原始內容存檔於2022-11-08).
Roger Stokes. Chapter 25: Object-Oriented Programming. 2015 [2020-05-18]. (原始內容存檔於2020-06-25). - ^ J9 base library. [2022-10-20]. (原始內容存檔於2022-12-19).
標準庫 (頁面存檔備份,存於網際網路檔案館) - ^ 包管理器. [2020-05-22]. (原始內容存檔於2021-04-06).
- ^ 插件 (頁面存檔備份,存於網際網路檔案館)
- ^ Run a sentence and produce a 2D display of results. [2022-10-30]. (原始內容存檔於2022-10-30).
Dissect (頁面存檔備份,存於網際網路檔案館) - ^ Jdatabase (Jd) is a relational database management system (RDBMS) from Jsoftware that is implemented in J. [2022-09-25]. (原始內容存檔於2022-12-06).
- ^ Bussell, Brian; Taylor, Stephen, Software Development as a Collaborative Writing Project, Extreme programming and agile processes in software engineering, Oulu, Finland: Springer: 21–31, 2006, ISBN 978-3-540-35094-1,
In practice, competence in the business and in writing software coincide only where the business requires mathematical skills. In consequence, highly abstract executable notations such as APL, A+, J, K, Q, R and S flourish primarily among actuaries, financial traders and statisticians. ……
A key technique to the success of this has been programmers and users collaborating on writing the source code. ……
Programmers have made this possible by constructing local, domain-specific executable notations. The vocabulary of these notations is drawn from the users』 talk about the work. ……
Users and programmers can now converge quickly on and verify a common understanding. The notation enables them to avoid ambiguity; it is a 「tool for thought」 in the sense of Iverson’s Turing Award lecture [11]. Because the notation is executable (and interpreted), the running system animates the described behaviour in front of them. - ^ Holt, Alan, Network Performance Analysis: Using the J Programming Language, Springer, 2007, ISBN 978-1-84628-822-7
- ^ Eric Iverson. J Source GPL. J programming mailing list. 1 March 2011 [2020-05-18]. (原始內容存檔於2016-09-23).
- ^ Jsoftware's sourcing policy. [2020-05-18]. (原始內容存檔於2021-01-26).
- ^ NuVoc (頁面存檔備份,存於網際網路檔案館)
- ^ 詞類(頁面存檔備份,存於網際網路檔案館)
- ^ 名詞(頁面存檔備份,存於網際網路檔案館)
- ^ 動詞(頁面存檔備份,存於網際網路檔案館)
- ^ 定語 (頁面存檔備份,存於網際網路檔案館)
- ^ 42.0 42.1 IBM. APL Language (PDF). June 1976 [2022-07-02]. (原始內容存檔 (PDF)於2019-09-26).
For example, the grade function
⍋
is commonly used to produce indices needed to reorder a vector into ascending order (as inX[⍋X]
), but may also be used in the treatment of permutations as the inverse function, that is,⍋P
yields the permutations as the inverse toP
. - ^ Read and write CSV files and strings. [2022-06-14]. (原始內容存檔於2022-07-07).
Addons/tables/csv (頁面存檔備份,存於網際網路檔案館) - ^ Roger K.W. Hui. Extended Integers in J. 1996 [2022-06-24]. (原始內容存檔於2022-06-28).
Some verbs
v
signal domain error on some extended arguments because the result is not integral; however,<.@v
and>.@v
are closed on extended arguments. - ^ J Memory Mapped File. [2022-10-20]. (原始內容存檔於2022-10-20).
內存映射文件 (頁面存檔備份,存於網際網路檔案館) - ^ K.E. Iverson. Determinant-Like Functions Produced by the Dot Operator. 1982.
The operator denoted by the dot has been extended to provide a monadic function (as in
-.×m
) as well as the established dyadic inner product function (as inn+.×m
). ……
The determinant of a square matrixm
is defined as the alternating sum (i.e. reduction by-
) of the!n←1↑⍴m
products overn
elements chosen (in each of the!n
possible ways) one from each row and column. Analogous calculations in which other function pairs are substituted for-
and×
lead to other useful functions; examples include the pairs⌈⌊
,∧∨
, and+×
, the last (called the permanent) being useful in combinatorics. - ^ 47.0 47.1 IBM. APL Language (PDF). June 1976 [2022-07-02]. (原始內容存檔 (PDF)於2019-09-26).
If
P
andQ
are vectors of the same shape, then the expression+/P×Q
has a variety of useful interpretations. ……
The inner product produces functions equivalent to expressions in this form; it is denoted by a dot and applies the two function surround it. ThusP+.×Q
is equivalent to+/P×Q
, andP×.⋆Q
is equivalent to×/P⋆Q
, and, in general,Pf.gQ
is equivalent tof/PgQ
, ifP
andQ
are vectors.
The inner product is extended to arrays other than vectors along certain fixed axes, namely the last axis of the first argument and the first axis of the last argument. the lengths of these axes must agree. the shape of the result is obtained by deleting these axes and chaining the remaining shape vectors together. ……
The inner productM+.×N
is commonly called the matrix product. ……
Either argument of the inner product may be a scalar or a one-element vectors; it is extended in the usual manner. - ^ 48.0 48.1 IBM. APL Language (PDF). June 1976 [2022-07-02]. (原始內容存檔 (PDF)於2019-09-26).
The outer product operator, denoted by by the symbols
∘.
preceding the function symbol, applies to any dyadic primitive scalar function, so that the function is evaluated for each member of the left argument paired with each member of the right argument. ……
Such tables may be better understood if labelled in a way widely used in elementary arithmetic texts: values of the arguments are placed beside and above the table, and the function whose outer product is being computed is shown at the corner. - ^ Kenneth E. Iverson. A Dictionary of APL. 1987.
The case
3⍤v
also has left rank2
, and⍺3⍤v⍵
appliesv
to each element produced by a tessellation of⍵
, using a size1{⍺
, and beginning points that are multiples of the 「shift」0{⍺
. - ^ Vocabulary/SpecialCombinations. [2023-05-08]. (原始內容存檔於2023-05-08).
- ^ 秩 (頁面存檔備份,存於網際網路檔案館)
- ^ Roger K. W. Hui, Morten J. Kromberg. APL since 1978. Proceedings of the ACM on Programming Languages, Volume 4, Issue HOPL. 2020 [2022-06-20]. (原始內容存檔於2022-07-10).
In the dyadic case, two frames
lf
andrf
are involved, from the left and right arguments. Several different treatments are possible:
• scalar agreement:(lf≡rf)∨(lf≡⍬)∨(rf≡⍬)
, the left and right frames match, or one is the empty vector (⍬
). If the frames match, there are an equal number of left and right cells, and the operand function applies to corresponding cells. If they do not match, one frame must be⍬
, that is, there is one cell on one side, whence that one cell is applied against every cell on the other side. Scalar agreement is implemented in Dyalog APL [Dyalog 2015].
• prefix agreement:(p↑lf)≡(p↑rf) ⊣ p←(≢lf)⌊(≢rf)
, one frame must be a prefix of the other. Letff
be the longer frame (that is,ff←lf,p↓rf
). In this case a cell of the argument with the shorter frame is applied against×⌿p↓ff
cells of the other argument. Prefix agreement is implemented in J [Hui and Iverson 2004], and is consistent with the emphasis on the leading axis (§2).
• suffix agreement: one frame must be a suffix of the other. J had suffix agreement before it switched to prefix agreement in 1992 on a suggestion by Whitney [Whitney 1992].
• strict agreement: the frames must match. No dialect has ever implemented this. - ^ 动词信息. [2022-06-04]. (原始內容存檔於2022-07-06).
- ^ 54.0 54.1 框架填充. [2022-06-07]. (原始內容存檔於2022-07-06).
- ^ 定语生成的动词的秩. [2022-06-04]. (原始內容存檔於2022-07-07).
- ^ Kenneth E. Iverson. Operators and Functions. 1978 [2022-06-21]. (原始內容存檔於2022-06-24).
The dual operator, denoted by
⍢
, is a slight extension of the notion of dual functions implicit in deMorgan’s law (∨⍢~ ↔ ^
and≠⍢~ ↔ =
), the extension being to include a monadic left argument, as in⌊⍢-x ↔ ⌈x
. ……
Composition and the dual operator applied to a divalent left argument and a monadic (or divalent) right argument yield parallel definitions of divalent derived functions as follows:
……
Dual:f⍢g y ↔ (g⍣¯1) f (g y)
x f⍢g y ↔ (g⍣¯1) (g x) f (g y)
It should be noted that the extension of the dual to include the monadic definition makes the identities⌈⍢- ↔ ⌊
and⌊⍢- ↔ ⌈
hold for both the monadic case (floor and ceiling) and for the dyadic case (minimum and maximum). Moreover, for the dyadic case the exponential function yields the identities×⍢* ↔ +
and+⍢⍟ ↔ ×
, the latter of which provides the basis for the use of natural logarithms in multiplication, just as the identity+⍢(10¨⍟) ↔ x
forms the basis for the use of base ten logarithms. - ^ Kenneth E. Iverson. Operators and Functions. 1978 [2022-06-21]. (原始內容存檔於2022-06-24).
The expression
f⍢>
produces a derived function which applies the functionf
to its argument in an 「item-wise」 fashion, by disclosing each element of the argument, applyingf
, and enclosing the result to produce the corresponding element of the overall result. - ^ Roger Hui. Remembering Ken Iverson. 2004 [2022-11-05]. (原始內容存檔於2019-12-20).
Ken and I had in mind to implement A Dictionary of APL [8] together with hooks and forks (phrasal forms) [20]. ……
The choice to implement forks was fortuitous and fortunate. We realized only later [32] that forks made tacit expressions (operator expressions) complete in the following sense: any sentence involving one or two arguments that did not use its arguments as an argument to an operator, can be written tacitly with fork and@:
(compose) and[
(left) and]
(right) and constant functions. If@:
were replaced by the equivalent special fork[: f g
, then a sentence can be written as an unbroken train (sequence of forks). ……
Meanwhile, Ken was concerned about the usefulness of forks, and worked hard at finding examples of forks beyond those in Phrasal Forms [20]. After a while, it seemed that everything was a fork. The explanation lies in the proof of completeness for tacit definition [32]: if the root (last) function in a sentence is applied dyadically, then a fork is required to write the sentence tacitly. - ^ Function composition. [2022-06-09]. (原始內容存檔於2022-07-06).
- ^ Kenneth E. Iverson. A Dictionary of APL. 1987 [2022-06-08]. (原始內容存檔於2022-06-12).
u⍥v
Rank: mv lv rv Upon; Upon
The monadu
is applied to the result ofv
, that is:
u⍥v ⍵ ←→ u v ⍵ ←→ u⍤v ⍵
⍺ u⍥v ⍵ ←→ u ⍺ v ⍵
- ^ Kenneth E. Iverson. A Dictionary of APL. 1987 [2022-06-08]. (原始內容存檔於2022-06-12).
u⍤v
Rank: mv mv mv On; On
Monad. In the simplest caseu⍤v ⍵
is equivalent tou v ⍵
. …… more generally, the rank of the derived functionu⍤v
is the rank ofv
; that is, the expressionu v
is applied to each of the cells of⍵
relative tov
. ……
Dyad. The left and right ranks ofu⍤v
are both the monadic rank ofv
. Therefore⍺ u⍤v ⍵
is equivalent to(v⍺) u v ⍵
. - ^ Kenneth E. Iverson. A Dictionary of APL. 1987 [2022-06-08]. (原始內容存檔於2022-06-12).
Withe (
u⍩v
) is similar to (u⍤v
), but appliesv
only to the right argument:⍺ u⍩v ⍵ ←→ ⍺ u v ⍵
u⍩v ⍵ ←→ ⍵ u v ⍵
- ^ Kenneth E. Iverson. A Dictionary of APL. 1987 [2022-06-08]. (原始內容存檔於2022-06-12).
u¨v
Rank: mv mv mv Under; Under
This function is equivalent to composition (u⍤v
) except that the function inverse tov
is applied to the result of each cell. …… The functionu¨v
is often called 「the dual ofu
with respect tov
」, but the phrase 「u
underv
」 is probably better, suggesting thatu
is performed after preparatory work byv
, and before the task is sewn up by reversing the effect ofv
. The expressionu¨v
is valid only ifv
possesses an inverse. - ^ Roger K. W. Hui, Morten J. Kromberg. APL since 1978. Proceedings of the ACM on Programming Languages, Volume 4, Issue HOPL. 2020 [2022-06-20]. (原始內容存檔於2022-07-10).
One of the HOPL IV badges has an APL expression on it:
÷+/÷(e≠0)/e
, the reciprocal of the sum of the reciprocals of the non-zero values ofe
. The expression computes the total resistance of components connected in parallel, whose resistance values are the vectore
.
There is an alternative phrasing in modern APL:+⌿⍢÷e~0
, sum under reciprocal (§3.5), without0
s. If arithmetic were extended to infinity (§4.6), in particular if÷0 ↔ ∞
and÷∞ ↔ 0
, then the expression would simplify to+⌿⍢÷e
, without the without0
(~0
). - ^ Kenneth E. Iverson. Operators and Functions. 1978 [2022-06-21]. (原始內容存檔於2022-06-24).
The power operator, denoted by
⍣
, applies to a monadic function left argumentf
and an integer right argumentk
to produce thek
th power off
in the following sense:f⍣k ↔ f f⍣k-1
, andf⍣1 ↔ f
. In particular,f⍣0
is the identity function andf⍣¯1
is the inverse off
. Moreover,f⍣_
denotes the limit off
, that is, the limiting functionf⍣n
forn
large. Similarly,f⍣¯
denotes the limit of the inverse off
. - ^ Vocabulary/Inverses. [2022-10-23]. (原始內容存檔於2022-12-05).
- ^
Kenneth E. Iverson, Peter K. Wooster. A Function Definition Operator. APL Quote Quad, Volume 12, Number 1, Proceedings of APL81, ACM. September 1981 [2022-06-29]. (原始內容存檔於2022-06-29).
This paper proposes two related extensions to APL: the extension of assignment to allow a name
F
to be assigned to a derived function by an expression of the formF←+.x
, and the introduction of a dyadic operator∇
to apply to character arraysD
andM
so thatD∇M
produces an ambivalent function in which the dyadic case is defined byD
and the monadic case byM
.
Kenneth E. Iverson. Rationalized APL. 1983 [2022-06-19]. (原始內容存檔於2022-07-22).The proposed replacement for
⎕fx
is a modification of the direct definition operator∇
defined in [A Function Definition Operator], ……
A function produced by the operator∇
may be assigned a name (as inf←m∇d
or ina(f←m∇d)b
), but it may also be used without assigning a name, as iny←''∇'⍺+÷⍵'/x
. - ^
John Scholes. Direct Functions in Dyalog APL (PDF). October 1996 [2022-06-30]. (原始內容存檔 (PDF)於2021-10-05).
A Direct Function (dfn) is a new function definition style, which bridges the gap between named function expressions such as
rank←⍴∘⍴
and APL’s traditional 『header』 style definition.
System/ReleaseNotes/J902. 14 May 2020 [2022-06-30]. (原始內容存檔於2022-07-03).Explicit entities can be defined using direct definition. The digraphs
{{
and}}
are reserved for delimiters, and text found between{{ }}
is taken to define a verb/adverb/conjunction. The text may be multiple lines long and may contain other embedded definitions. The part of speech of the defined entity is inferred from the words in it. - ^ DGEMM - matrix matrix multiply. [2022-10-13]. (原始內容存檔於2022-10-10).
- ^ 控制結構
- ^ A. D. Falkoff, K. E. Iverson. APL\360 User's Manual (PDF). IBM. August 1968 [2022-07-09]. (原始內容存檔 (PDF)於2021-10-27).
Table 3.9 shows the detailed definitions of transposition for a variety of cases. ……Case ⍴R Definition R←1⍉V
⍴V
R←V
R←1 2⍉M
⍴M
R←M
R←2 1⍉M
(⍴M)[2 1]
R[I;J]←M[J;I]
R←1 1⍉M
⌊/⍴M
R[I]←M[I;I]
R←1 2 3⍉T
⍴T
R←T
R←1 3 2⍉T
(⍴T)[1 3 2]
R[I;J;K]←T[I;K,J]
R←2 3 1⍉T
(⍴T)[3 1 2]
R[I;J;K]←T[J;K;I]
R←3 1 2⍉T
(⍴T)[2 3 1]
R[I;J;K]←T[K;I;J]
R←1 1 2⍉T
(⌊/(⍴T)[1 2]),(⍴T)[3]
R[I;J]←T[I;I;J]
R←1 2 1⍉T
(⌊/(⍴T)[1 3]),(⍴T)[2]
R[I;J]←T[I;J;I]
R←2 1 1⍉T
(⌊/(⍴T)[2 3]),(⍴T)[1]
R[I;J]←T[J;I;I]
R←1 1 1⍉T
⌊/⍴T
R[I]←T[I;I;I]
Table 3.9: TRANSPOSITION - ^ Roger Hui. dyadic transpose, a personal history. 22 May 2020 [2022-08-08]. (原始內容存檔於2022-08-08).
Dyadic transpose,
x⍉y
, is probably one of the last primitives to be mastered for an APLer, but is actually straightforward to describe. - ^
IBM. APL Language (PDF). June 1976 [2022-07-02]. (原始內容存檔 (PDF)於2019-09-26).
If
P
is any permutation of the indices of the axes of an arrayA
, thenP⍉A
is an array similar toA
except that the axes are permuted: theI
th axis becomes theP[I]
th axis of the result. Hence, ifR←P⍉A
, then(⍴R)[P]
is equal to⍴A
. For example:
A←2 3 5 7⍴⍳210
⍴A
2 3 5 7
P←2 3 4 1
⍴P⍉A
7 2 3 5
……
The monadic transpose⍉A
reverses the order of the axes of its argument. Formally,⍉A
is equivalent to(⌽⍳⍴⍴A)⍉A
.
上面的APL轉置⍉
運算規定中,不將多個軸映射到結果中的一個軸的簡單示例,所對應的J語言代碼:transpose=: {{(/: x) |: y}} a=: >:i. 2 3 5 7 $ a 2 3 5 7 p=: 2 3 4 1 $ p transpose a 7 2 3 5
- ^ Kenneth E. Iverson. Operators and Functions. 1978 [2022-06-21]. (原始內容存檔於2022-06-24).
The use of the indexing function will be illustrated in a proof of the useful identity
i⍉j⍉a ↔ i[j]⍉a
. We first state the definition of the transpose as follows: ifk
is any vector index ofj⍉a
then
k⌷j⍉a ↔ k[j]⌷a
Then:
k⌷i⍉j⍉a
k[i]⌷j⍉a
(k[i])[j]⌷a
k[i[j]]⌷a
k⌷i[j]⍉a
Kenneth E. Iverson的上述二元轉置定義,用J語言寫為(<k){j|:a
↔(<(/:j){k){a
,而恆等式i|:j|:a
↔(i{j)|:a
的推導過程相應如下:
(<k){i|:j|:a (<(/:i){k){j|:a (<(/:j){(/:i){k){a (<k){(/:(/:j){(/:i))|:a (<k){(i{j)|:a
- ^ Roger K. W. Hui, Morten J. Kromberg. APL since 1978. Proceedings of the ACM on Programming Languages, Volume 4, Issue HOPL. 2020 [2022-06-20]. (原始內容存檔於2022-07-10).
Well, we don’t know what Ken Iverson’s favorite APL expression was or if he even had a favorite APL expression. But we can guess. From A History of APL in 50 Functions [Hui 2016a, §8]:
⊢ x←,1
1
⊢ x←(0,x)+(x,0)
1 1
⊢ x←(0,x)+(x,0)
1 2 1
⊢ x←(0,x)+(x,0)
1 3 3 1
The expression(0,x)+(x,0)
or its commute, which generates the next set of binomial coefficients, ……. - ^ Roger K. W. Hui, Morten J. Kromberg. APL since 1978. Proceedings of the ACM on Programming Languages, Volume 4, Issue HOPL. 2020 [2022-06-20]. (原始內容存檔於2022-07-10).
What is being indexed is an array (of course) but the indices themselves (the 「subscripts」) can also be arrays. For example [Hui 2016a, §4]:
x← 3 1 4 1 5 9
'.⎕'[x∘.>⍳⌈⌿x]
……
In the example, the 2-element character vector'.⎕'
is indexed by a 6-by-9 Boolean matrix. - ^
IBM. APL Language (PDF). June 1976 [2022-07-02]. (原始內容存檔 (PDF)於2019-09-26).
More generally,
Q⍉A
is a valid expression ifQ
is any vector equal in length to the rank ofA
which is "complete" in the sense that if its items include any integerN
they also include all positive integers less thenN
. For example, if⍴⍴A
is3
, then1 1 2
and2 1 1
and1 1 1
are suitable values forQ
but1 3 1
is not. Just as for the caseP⍉A
whereP
is a permutation, theI
th axis becomes theQ[I]
th axis ofQ⍉A
. However, in this case two or more of the axes ofA
may map into a single axis of the result, thus producing a diagonal section ofA
as illustrated below:
……
B←3 5⍴⍳15
B
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
1 1⍉B
1 7 13 - ^ Roger K. W. Hui, Morten J. Kromberg. APL since 1978. Proceedings of the ACM on Programming Languages, Volume 4, Issue HOPL. 2020.
Quicksort works by choosing a 「pivot」 at random among the major cells, then catenating the sorted major cells which strictly precede the pivot, the major cells equal to the pivot, and the sorted major cells which strictly follow the pivot, as determined by a comparison function
⍺⍺
. Defined as an operatorQ
:
Q←{1≥≢⍵:⍵ ⋄ s←⍵ ⍺⍺ ⍵⌷⍨?≢⍵ ⋄ (∇ ⍵⌿⍨0>s)⍪(⍵⌿⍨0=s)⍪(∇ ⍵⌿⍨0<s)}
……
The above formulation is not new; see for example Figure 3.7 of the classic The Design and Analysis of Computer Algorithms [Aho et al. 1974]. However, unlike the pidgin ALGOL program in Figure 3.7,Q
is executable, and the partial order used in the sorting is an operand, the(×-)
andcmp¨
andcmp⍤1
in the examples above. - ^ Roger K. W. Hui, Morten J. Kromberg. APL since 1978. Proceedings of the ACM on Programming Languages, Volume 4, Issue HOPL. 2020 [2022-06-20]. (原始內容存檔於2022-07-10).
Monadic
⍋
was originally defined only on numeric vectors, and was extended [Wooster 1980] to work on numeric arrays with higher rank. With that extension it has the distinction of being the first APL primitive function defined to work on major cells, before the term was invented or the importance of the concept realized. It was later extended to work on character arrays in Dyalog APL in 1982. More recently,⍋
was extended in J to work with a TAO (total array ordering) [Hui 1996] on a suggestion by Whitney. TAO was taken up by Dyalog APL in 2018 [Brudzewsky et al. 2018]. The TAO also extends the left domain of⍸
. (The expression above for getting grade from sort requires TAO.) - ^ Roger K. W. Hui, Morten J. Kromberg. APL since 1978. Proceedings of the ACM on Programming Languages, Volume 4, Issue HOPL. 2020.
Generate the sorted matrix of all permutations of
⍳⍵
[Hui 2016a, §19; McDonnell 2003; Hui 2015b]. …… perm⍵
obtains by indexing each row of the matrix⍒⍤1 ∘.=⍨ ⍳⍵
by0,1+perm ⍵-1
. …… Putting it all together:
perm ← {0=⍵:1 0⍴0 ⋄ ((!⍵),⍵)⍴(⊂0,1+∇ ¯1+⍵)⌷⍤1 ⍒⍤1 ∘.=⍨ ⍳⍵}
- ^ A History of APL in 50 Functions - 19. Permutations. [2022-09-27]. (原始內容存檔於2022-09-27).
- ^ 82.0 82.1 J implementation of Fold primitives. [2022-11-01]. (原始內容存檔於2022-11-01).
- ^ Roger K. W. Hui, Morten J. Kromberg. APL since 1978. Proceedings of the ACM on Programming Languages, Volume 4, Issue HOPL. 2020.
An example of John Conway’s Game of Life [Gardner 1970] is obligatory with this operator. life below is due to Jay Foad, translated from an algorithm in k by Whitney [Hui 2017c]. It applies the rules of the Game of Life to the universe to create the next generation.
life ← {3=s-⍵∧4=s←{+⌿,⍵}⌺3 3⊢⍵}
⊢ glider←5 5⍴0 0 1 0 0 1 0 1 0 0 0 1 1,12⍴0
……
{'.⍟'[⍵]}¨ (⍳8) {life⍣⍺⊢⍵}¨ ⊂glider
……
In life, the derived function{+⌿,⍵}⌺3 3
computes the sum of each3
-by-3
square, moving by1
in each dimension. The function{'.⍟'[⍵]}
produces a compact display for a Boolean array. - ^ Stencil Lives.
Jay Foad offers another stencil life, translating an algorithm in k by Arthur Whitney:
life3 ← {3=s-⍵∧4=s←{+/,⍵}⌺3 3⊢⍵} ⍝ Jay Foad
……
The algorithm combines the life rules into a single expression, whereins←{+/,⍵}⌺3 3 ⊢⍵
(0) for0
-cellss
is the number of neighbors; and
(1) for1
-cellss
is the number of neighbors plus1
, and the plus1
only matters ifs
is4
. - ^ Roger K. W. Hui, Morten J. Kromberg. APL since 1978. Proceedings of the ACM on Programming Languages, Volume 4, Issue HOPL. 2020 [2022-06-20]. (原始內容存檔於2022-07-10).
Key is a monadic operator. In the dyadic case of the derived function
⍺ f⌸ ⍵
, major cells of⍺
specify keys for the corresponding major cells of⍵
, andf
is applied to each unique key in⍺
and the selection of cells in⍵
having that key. In the monadic case of the derived function,f⌸⍵ ↔ ⍵ f⌸ ⍳≢⍵
:f
is applied to each unique key in⍵
and the indices in⍵
of that key.
Key was defined and implemented in J in 1989 or 1990 [Hui 2007] and in Dyalog APL in 2015 [Dyalog 2015; Hui 2020b]. It is motivated by the 「generalized beta」 operation in The Connection Machine [Hillis 1985, §2.6], but generalizes the generalized beta by accepting arrays of any rank, not just vectors, and by permitting any function, not just reductions (folds). Key is also cognate with the GROUP BY statement in SQL. ……
The following snippet solves a 「Programming Pearls」 puzzle [Bentley 1983]: given a dictionary of English words, here represented as the character matrixa
, find all sets of anagrams. ……he algorithm works by sorting the rows individually (note the use of the rank operator⍤
(§3.1)), and these sorted rows are used as keys (「signatures」 in the Programming Pearls description) to group the rows of the matrix. As the anagram example illustrates, other APL functions can be used to create the requisite keys. - ^ Roger K. W. Hui, Morten J. Kromberg. APL since 1978. Proceedings of the ACM on Programming Languages, Volume 4, Issue HOPL. 2020.
Generate
⍵
random numbers selected from⍳≢⍺
according to the weights⍺
, a vector of positive real numbers [Hui 2017d]. For example, ifa←7 5 6 4 7 2 0.4
are the weights, then ina ran 1e6
the number0
should occur roughly as often as4
(both with a weight of7
) and3.5
times as often as5
(with a weight of2
).
ran ← {(0⍪+⍀⍺÷+⌿⍺)⍸?⍵⍴0}
……
The technique can be used to generate random numbers according to a probability distribution [Abramowitz and Stegun 1964, §26.8]. If a discrete distribution with valuesv
and probabilitiesp
, thenv[p ran ⍵]
. If a continuous distribution, convert it into a discrete one by dividing(¯∞,∞)
into an appropriate number of intervals. The interval midpoints are the values; the probabilities are the differences of the cumulative distribution function at the interval end points.
The problem was solved in 1975 [IPSA 1975]; the current solution uses to advantage the extension of?0
to generate a random number drawn uniformly from the open interval(0, 1)
(suggested by Whitney) and the interval index function⍸
(§2.3). - ^ Roger K. W. Hui, Morten J. Kromberg. APL since 1978. Proceedings of the ACM on Programming Languages, Volume 4, Issue HOPL. 2020.
The following is an example of interval index
⍸
(§2.3) and⌸
working together to illustrate the central limit theorem, that the sum of independent random variables converges to the normal distribution [Hui and Iverson 2004; Hui 2016b, §F].
t←¯1+{≢⍵}⌸(⍳51),(4×⍳50)⍸+⌿?10 1e6⍴21
……t
counts the number of occurrences for interval endpoints4×⍳50
, of1e6
samples from the sum of ten repetitions of uniform random selection of the integers from0
to20
. A barchart oft
:
.⎕'[(6e3×⊖⍳⌈(⌈/t)÷6e3)∘.≤t]
……
The derived function{≢⍵}⌸x
counts the number of occurrences of each unique cell ofx
. The Dyalog APL and J implementations recognize particular useful operands for key, for example{≢⍵}
and{f⌿⍵}
, and implement those cases with special code (§9.3) for better performance. - ^ Sqlite enhanced API for J. [2022-10-20]. (原始內容存檔於2022-10-22).
Addons/data/sqlite/Overview. [2022-09-20]. (原始內容存檔於2022-09-20).
外部連結
- JSoftware(頁面存檔備份,存於網際網路檔案館),J的官方網站
- GitHub上的Jsoftware頁面 – Repository
- Learning J (頁面存檔備份,存於網際網路檔案館) – An Introduction to the J Programming Language by Roger Stokes
- J for C Programmers (頁面存檔備份,存於網際網路檔案館) by Henry Rich
- J for the APL Programmer (頁面存檔備份,存於網際網路檔案館) by Chris Burke and Roger Hui
- An Implementation of J (頁面存檔備份,存於網際網路檔案館) by Roger K.W. Hui
- APL to J Phrasebook (頁面存檔備份,存於網際網路檔案館)
- J - APL Wiki (頁面存檔備份,存於網際網路檔案館)
- 郭平欣譯J字典 (頁面存檔備份,存於網際網路檔案館)