秩 (J编程语言)

秩（Rank），是对非面向阵列的标量编程语言中循环的广泛化。它还是Lisp语言中的mapcar，及现代函数式编程语言中的map高阶函数的广泛化，以及对APL\360中标量扩展、矩阵的内积和外积的广泛化。秩的正规实现，是在J语言中，但也可获得于APL语言实现如Dyalog APL、ISO标准ISO/IEC 13751:2001的扩展APL和NARS2000。
简介.
秩有一些不同的含义。一般的说，秩的概念用于依据它们的子阵列来处理。例如，二维阵列可以在秩为2之下，按一个完整的矩阵进行处理；或者在秩为1之下，对它所包含的诸个一维列向量或行向量进行处理；或者在秩为0之下，对它所包含的诸个单独元素进行处理。J语言中有三种秩：
名词秩.
在J语言中，名词是。名词的秩是这个阵列的维数。尽管有时存在争论，人们通常用如下名字称谓低维阵列：
一个N维整数阵列可以通过codice_2建立，它接受一个整数向量作为参数。其中整数的数目定义了维数，而每个整数的绝对值定义对应维的长度。可以使用派生动词codice_3来确定一个名词的秩。
<syntaxhighlight lang="J" highlight="2,4,6,7,9-15,17">
0 1 2
1 2 3
0 1 2
3 4 5
12 13 14 15
16 17 18 19
20 21 22 23
3
</syntaxhighlight>
动词秩.
在J语言中，动词是接受名词参数产生名词结果的函数。动词的秩，控制着如何将动词应用到秩大于codice_4的名词。采用副词codice_5来确定动词codice_6的秩。例如：
<syntaxhighlight lang="J" highlight="2,4">
0 0 0
_ _ _
</syntaxhighlight>
这里的codice_7“无穷”，指示将参数作为整体处理。动词的秩被表达为三个数：
例如，codice_8使用codice_9作为单子（monad），是一元情况；codice_10使用codice_9作为双子（dyad），是二元情况。在所有情况下，有一些底层动词被应用于“单元”（cell），它是有指示秩的子阵列。如果参数没有动词指示的那么多维，在这种退化的情况下，动词的秩会有效的缩减为参数实际的秩。
在动词中，负数秩被解释为，将提供为参数的名词的秩，减少指示正值，但永不会变得小于零。例如，一个动词具有一元秩负1，在给它一个秩为3的参数的时候，将参数分解成秩为2的阵列的一个列表。将动词的主体，应用到这些二维子阵每个之上一次。
在特定动词和特定名词的上下文下，将名词的诸维，划分成前缀诸维的序列，称为框架（frame）；和后缀诸维的序列，称为单元（cell）。正数动词秩，指示单元诸维的数目，负数动词秩，指示框架诸维的数目。
秩连词.
秩连词codice_1，接受一个动词左参数和一个名词右参数来建立一个新动词。
名词右参数构成自三个数，分别指定一元秩、二元左秩和二元右秩。如果右参数只有两个数，第一个数是二元左秩，而第二个数是一元秩和二元右秩。如果右参数只有一个数，它被接受为所有三种情况下的秩。如果右参数是个动词，就复制使用它的秩。例如：
<syntaxhighlight lang="J" highlight="2,4,6,8">
1 1 1
_ 0 _
1 1 1
_ 0 0
</syntaxhighlight>
如果给秩连词的左参数是个名词，建立一个常量动词。这个动词的主体忽略任何参数的值，并总是生成这个名词的结果。
框架一致.
在二元运算的情况下，左右两个参数，都有自己的框架，二者必须达成一致（agreement）。左右两框架经常是共同的。如果左右两框架不是同一的，有三种可以运算的情况：
两参数中一个的形状序列，是另一个的形状序列的前缀，例如：
<syntaxhighlight lang="J" highlight="2-8">
100 105 110 115
</syntaxhighlight>
这里左侧参数的短框架codice_13，是右侧参数的长框架codice_14的前缀。求值这个动词的结果，跟随着前缀诸维序列codice_13，是二元动词应用到两个有关单元的结果，即将左参数的每个0维标量，乘以右参数的每个1维阵列。
两参数中一个的形状序列，是另一个的形状序列的后缀，可以通过秩连词，指定动词秩为维数少参数的秩，从而对它按整体处理，例如：
<syntaxhighlight lang="J" highlight="2-8">
160 189 220 253
</syntaxhighlight>
这里左侧参数的短框架codice_16，是右侧参数的长框架codice_14的后缀。求值这个动词的结果，跟随着前缀诸维序列codice_18，是二元动词应用到两个有关单元的结果，即将左参数的作为整体的1个2维阵列，乘以右参数相同形状的每个2维阵列。
指定动词左右秩中的一个为codice_7，即按整体处理，例如：
<syntaxhighlight lang="J" highlight="2,4,6,8">
2 3 3 4
3 4 2 3
2 3 4
2 3 4
</syntaxhighlight>
这里第一个运算的左秩为codice_4，而右秩为按整体处理；求值的结果中跟随着左参数的诸维序列codice_13的，是将左参数的每个codice_4维标量，乘以右参数的作为整体的codice_18维阵列的结果。第二个运算的左右秩与第一个运算相反，其结果中来自二者的诸轴的前后次序也与之相反。第三个运算的左秩为codice_24，而右秩为按整体处理；跟随着左参数的诸维序列codice_18的，是将左参数的每个codice_24维向量，乘以右参数的作为整体的codice_18维阵列的结果。第四个运算的左右秩都按整体处理，则同于前缀情况。
秩作为循环的泛化.
理解秩要求知道一些非常基础的面向阵列编程概念。在大多数基于阵列的语言中，归约（reduction）用前向斜杠codice_28来指示。在J语言中，斜杠接受一个函数左参数，和要被这个函数归约的阵列作为右参数。将加法归约应用到一个1维阵列：
<syntaxhighlight lang="J" highlight="2">
6
</syntaxhighlight>
预期的结果是codice_29。
将加法归约应用到一个2维阵列：
<syntaxhighlight lang="J" highlight="2">
3 5 7
</syntaxhighlight>
预期结果是codice_30。codice_31的秩为codice_7“无穷”，即将参数作为整体来运算，codice_33算符被映射到这个阵列的最高秩之上。对2个向量进行归约，参数名词的形状从codice_13变为codice_35即codice_36，结果是合计了每行元素的长度为3的1维阵列。这个代码对应如下APL2及其派生者的代码：
<syntaxhighlight lang="apl" highlight="2">
3 5 7
</syntaxhighlight>
还对应于如下C语言代码片段：
<syntaxhighlight lang="c">
for(j = 0; j < 3; ++j) {
for(i = 0; i < 2; ++i) {
</syntaxhighlight>
假定需要合计每列元素，而得到长度为2的1维阵列，在C语言代码中如下这样写：
<syntaxhighlight lang="c">
for(i = 0; i < 2; ++i) {
</syntaxhighlight>
在APL中不需要用到循环构造，这个代码写为：
<syntaxhighlight lang="apl" highlight="2">
3 12
</syntaxhighlight>
在J语言中使用秩连词可以写为：
<syntaxhighlight lang="J" highlight="2,4">
3 12
3 12
</syntaxhighlight>
为了进一步展示在J语言中秩是如何工作的，以3维阵列上的加法归约为例子：
<syntaxhighlight lang="J" highlight="3-5,7,8,10,12,13,15">
12 14 16 18
20 22 24 26
28 30 32 34
12 15 18 21
48 51 54 57
1
54 70 86
1
</syntaxhighlight>