秩 (J程式語言)

秩（Rank），是對非面向陣列的標量程式語言中循環的廣泛化。它還是Lisp語言中的mapcar，及現代函數式程式語言中的map高階函數的廣泛化，以及對APL\360中標量擴展、矩陣的內積和外積的廣泛化。秩的正規實現，是在J語言中，但也可獲得於APL語言實現如Dyalog APL、ISO標準ISO/IEC 13751:2001的擴展APL和NARS2000。

## 簡介

秩有一些不同的含義。一般的說，秩的概念用於依據它們的子陣列來處理正交陣列。例如，二維陣列可以在秩為2之下，按一個完整的矩陣進行處理；或者在秩為1之下，對它所包含的諸個一維列向量或行向量進行處理；或者在秩為0之下，對它所包含的諸個單獨元素進行處理。J語言中有三種秩：

- 名詞秩，名詞的秩是非負整數。
- 動詞秩，動詞的秩是三個整數的列表。
- 秩連詞，秩連詞`"`用來導出具有指定秩的一個動詞。

## 名詞秩

在J語言中，名詞是陣列數據類型。名詞的秩是這個陣列的維數。儘管有時存在爭論，人們通常用如下名字稱謂低維陣列：

名字｜秩

原子｜標量｜0

列表｜向量｜1

表格｜矩陣｜2

立體｜張量｜3

一個N維整數陣列可以通過`i.`建立，它接受一個整數向量作為參數。其中整數的數目定義了維數，而每個整數的絕對值定義對應維的長度。可以使用派生動詞`#@$`來確定一個名詞的秩。

```J
   i. 3
0 1 2
   >:i. 3
1 2 3
   i. 2 3
0 1 2
3 4 5
   i. 2 3 4
 0  1  2  3
 4  5  6  7
 8  9 10 11

12 13 14 15
16 17 18 19
20 21 22 23
   #@$ i. 2 3 4
3
```

## 動詞秩

在J語言中，動詞是接受名詞參數產生名詞結果的函數。動詞的秩，控制著如何將動詞應用到秩大於`0`的名詞。採用副詞`u b. 0`來確定動詞`u`的秩。例如：

```J
   * b. 0
0 0 0
   +/ b. 0
_ _ _
```

這裡的`_`「無窮」，指示將參數作為整體處理。動詞的秩被表達為三個數：

- 一元情況的秩
- 二元情況用於左參數的秩
- 二元情況用於右參數的秩

例如，`&minus;y`使用`&minus;`作為單子（monad），是一元情況；`x&minus;y`使用`&minus;`作為雙子（dyad），是二元情況。在所有情況下，有一些底層動詞被應用於「單元」（cell），它是有指示秩的子陣列。如果參數沒有動詞指示的那麼多維，在這種退化的情況下，動詞的秩會有效的縮減為參數實際的秩。

在動詞中，負數秩被解釋為，將提供為參數的名詞的秩，減少指示正值，但永不會變得小於零。例如，一個動詞具有一元秩負1，在給它一個秩為3的參數的時候，將參數分解成秩為2的陣列的一個列表。將動詞的主體，應用到這些二維子陣每個之上一次。

在特定動詞和特定名詞的上下文下，將名詞的諸維，劃分成前綴諸維的序列，稱為框架（frame）；和後綴諸維的序列，稱為單元（cell）。正數動詞秩，指示單元諸維的數目，負數動詞秩，指示框架諸維的數目。

## 秩連詞

秩連詞`"`，接受一個動詞左參數和一個名詞右參數來建立一個新動詞。

名詞右參數構成自三個數，分別指定一元秩、二元左秩和二元右秩。如果右參數只有兩個數，第一個數是二元左秩，而第二個數是一元秩和二元右秩。如果右參數只有一個數，它被接受為所有三種情況下的秩。如果右參數是個動詞，就複製使用它的秩。例如：

```J
   (*"1 1 1) b. 0
1 1 1
   (*"0 _) b. 0
_ 0 _
   (*"1) b. 0
1 1 1
   (*"<) b. 0
_ 0 0
```

如果給秩連詞的左參數是個名詞，建立一個常量動詞。這個動詞的主體忽略任何參數的值，並總是生成這個名詞的結果。

## 框架一致

在二元運算的情況下，左右兩個參數，都有自己的框架，二者必須達成一致（agreement）。左右兩框架經常是共同的。如果左右兩框架不是同一的，有三種可以運算的情況：

兩參數中一個的形狀序列，是另一個的形狀序列的前綴，例如：

```J
   (i. 2 3) * i. 2 3 4
  0   0   0   0
  4   5   6   7
 16  18  20  22

 36  39  42  45
 64  68  72  76
100 105 110 115
```

這裡左側參數的短框架`2 3`，是右側參數的長框架`2 3 4`的前綴。求值這個動詞的結果，跟隨著前綴諸維序列`2 3`，是二元動詞應用到兩個有關單元的結果，即將左參數的每個0維標量，乘以右參數的每個1維陣列。

兩參數中一個的形狀序列，是另一個的形狀序列的後綴，可以通過秩連詞，指定動詞秩為維數少參數的秩，從而對它按整體處理，例如：

```J
   (i. 3 4) *"2 i. 2 3 4
  0   1   4   9
 16  25  36  49
 64  81 100 121

  0  13  28  45
 64  85 108 133
160 189 220 253
```

這裡左側參數的短框架`3 4`，是右側參數的長框架`2 3 4`的後綴。求值這個動詞的結果，跟隨著前綴諸維序列`2`，是二元動詞應用到兩個有關單元的結果，即將左參數的作為整體的1個2維陣列，乘以右參數相同形狀的每個2維陣列。

指定動詞左右秩中的一個為`_`，即按整體處理，例如：

```J
   $ (i.2 3) (*"0 _) i.3 4
2 3 3 4
   $ (i.2 3) (*"_ 0) i.3 4
3 4 2 3
   $ (i.2 3) (*"1 _) i.3 4
2 3 4
   $ (i.2 3) (*"_) i.2 3 4
2 3 4
```

這裡第一個運算的左秩為`0`，而右秩為按整體處理；求值的結果中跟隨著左參數的諸維序列`2 3`的，是將左參數的每個`0`維標量，乘以右參數的作為整體的`2`維陣列的結果。第二個運算的左右秩與第一個運算相反，其結果中來自二者的諸軸的前後次序也與之相反。第三個運算的左秩為`1`，而右秩為按整體處理；跟隨著左參數的諸維序列`2`的，是將左參數的每個`1`維向量，乘以右參數的作為整體的`2`維陣列的結果。第四個運算的左右秩都按整體處理，則同於前綴情況。

## 秩作為循環的泛化

理解秩要求知道一些非常基礎的面向陣列編程概念。在大多數基於陣列的語言中，歸約（reduction）用前向斜槓`/`來指示。在J語言中，斜槓接受一個函數左參數，和要被這個函數歸約的陣列作為右參數。將加法歸約應用到一個1維陣列：

```J
   +/ 1 2 3
6
```

預期的結果是`1 + 2 + 3`。

將加法歸約應用到一個2維陣列：

```J
   +/ i. 2 3
3 5 7
```

預期結果是`0 1 2 + 3 4 5`。`+/`的秩為`_`「無窮」，即將參數作為整體來運算，`+`算符被映射到這個陣列的最高秩之上。對2個向量進行歸約，參數名詞的形狀從`2 3`變為`1 3`即`3`，結果是合計了每行元素的長度為3的1維陣列。這個代碼對應如下APL2及其派生者的代碼：

```apl
      +⌿ 2 3⍴⍳6
3 5 7
```

還對應於如下C語言代碼片段：

```c
for(j = 0; j < 3; ++j) {
    sum[j] = 0;
}
for(i = 0; i < 2; ++i) {
    for(j = 0; j < 3; ++j) {
        sum[j] += array[i][j];
    }
}
```

假定需要合計每列元素，而得到長度為2的1維陣列，在C語言代碼中如下這樣寫：

```c
for(i = 0; i < 2; ++i) {
    sum[i] = 0;
    for(j = 0; j < 3; ++j) {
        sum[i] += array[i][j];
    }
}
```

在APL中不需要用到循環構造，這個代碼寫為：

```apl
      +/ 2 3⍴⍳6
3 12
```

在J語言中使用秩連詞可以寫為：

```J
   +/"1 i. 2 3
3 12
   +/"_1 i. 2 3
3 12
```

為了進一步展示在J語言中秩是如何工作的，以3維陣列上的加法歸約為例子：

```J
   a=: i. 2 3 4
   +/ a
12 14 16 18
20 22 24 26
28 30 32 34
   +/"_1 a
12 15 18 21
48 51 54 57
   (+/"_1 a) -: +/"2 a
1
   +/"1 a
 6 22 38
54 70 86
   (+/"1 a) -: +/"_2 a
1
```

## 延伸閱讀

- Backus, J.W., Can Programming be Liberated from the von Neumann Style? A Functional Style and Its Algebra of Programs (https://www.thocp.net/biographies/papers/backus_turingaward_lecture.pdf ), Communications of the ACM, Volume 21, Number 8, 1978-08.; §11.3.3.
- Bernecky, R., An Introduction to Function Rank (https://dl.acm.org/citation.cfm?id=55632), APL88 Conference Proceedings, APL Quote Quad, Volume 18, Number 2, 1987-12.
- Brown, J.A., The Principles of APL2 (http://www.softwarepreservation.org/projects/apl/Papers/PRINCIPLESOFAPL2 ), TR 03.247, IBM Santa Teresa Laboratory, San Jose, California, 1984-03; §20.0.
- Dyalog, Dyalog APL Version 14.0 Release Notes (http://www.dyalog.com/dyalog-version-140.htm ), Dyalog Limited, 2015.
- Hui, R.K.W., Rank and Uniformity (http://www.jsoftware.com/papers/rank.htm ), APL95 Conference Proceedings, APL Quote Quad, Volume 25, Number 4, 1995-06.
- Hui, R.K.W., Remembering Ken Iverson (https://web.archive.org/web/20191220153001/http://keiapl.org/rhui/remember.htm), 2004-11.
- Hui, R.K.W., Inner Product—An Old/New Problem (http://www.jsoftware.com/papers/innerproduct/ip.htm ), British APL Association Conference 2009, 2009-06-08.
- Iverson, K.E., Operators and Functions (http://www.jsoftware.com/papers/opfns.htm ), Research Report #RC7091, IBM, 1978-04-26.
- Iverson, K.E., A Dictionary of APL (http://www.jsoftware.com/papers/APLDictionary.htm ), APL Quote Quad, Volume 18, Number 1, 1987-09.
- Iverson, K.E., A Personal View of APL (http://www.jsoftware.com/papers/APLPersonalView1.htm ), IBM Systems Journal, Volume 30, Number 4, 1991-12.
- Slepak,Justin; Shivers, Olin; Manolios, Panagiotis, An array-oriented language with static rank polymorphism (http://www.ccs.neu.edu/home/jrslepak/typed-j.pdf ).

## 外部連結

- J Dictionary entry for "rank"
- Rank in "Learning J"