2012年10月30日星期二

2 列表(Lists)和表格(Tables)

2 列表(Lists)和表格(Tables)

这是对<Learning J>(by Roger Stokes)的尝试翻译。

Roger Stokes的版权声明如下:
Copyright © Roger Stokes 2012. This material may be freely reproduced, provided that this copyright notice is also reproduced.
感谢作者的无私奉献,请您转载时也注明以上版权,也请同时注明转载地址http://corwindong.blogspot.com,我将不胜感激。

----------------------------------------------------------------------------------

计算需要数据,目前为止我们只看到单个数字或者一列数字。我们也可以把其他东西作为数据,例如表格。列表和表格统称为“阵列”。

2.1 表格

一个2行3列的表格可以通过 $ 函数构建:
   table =: 2 3   $   5 6 7  8 9 10
   table
5 6  7
8 9 10
表达式(x $ y)构造了一个表格。表格的维数通过列表x给出,x中第一个元素是表格的行数,
第二个元素是表格的列数。表格的元素由列表y给出。
 
y中的元素按顺序填充表格的第一行、第二行等等。列表y必须至少包含一个元素。如果y中
的元素数目不够填充整个表格,那么将从头开始重新使用y。
2 4 $ 5 6 7 8 92 2 $ 1
5 6 7 8
9 5 6 7
1 1
1 1

函数 $ 提供了一种构建表格的方法,还有很多其他的方式,参看第5章。

如同之前我们看到的列表一样,函数也可以应用于整个表格:
table10 * tabletable + table
5 6  7
8 9 10
50 60  70
80 90 100
10 12 14
16 18 20


也可以一个参数是表格,另一个是列表:
table0 1 * table
5 6  7
8 9 10
0 0  0
8 9 10
在这个例子中,列表0 1的元素和表格的行进行匹配,0匹配第一行,1匹配第二行。参数之间也存在其他的匹配方式,参见第7章。

2.2 阵列

表格有两个维度:行和列。类似的,列表可以看作只有一个维度。
我们还可以构造类似表格但维数大于2的数据。$ 函数的左参数可以是一个包含任意维数的列表。拥有维数的数据对象统称为“阵列”。下面示范一维、二维、三维阵列:
3 $ 12 3 $ 5 6 72 2 3 $ 5 6 7 8
1 1 15 6 7
5 6 7
5 6 7
8 5 6

7 8 5
6 7 8
上例中的三维阵列有2个平面,每个平面2行,3列,两个平面上下挨着显示。

回忆一下,一元函数 # 给出一个列表的长度:
# 6 7# 6 7 8
23
一元模式的 $ 给出阵列的维度表:
L =: 5 6 7$ LT =: 2 3 $ 1$ T
5 6 731 1 1
1 1 1
2 3
因此,如果x是一个阵列,表达式(# $ x)将得到x维度表的长度,也就是x的维数。列表的维数是1,表格的维数是2,等等。
L$ L# $ LT$T# $ T
5 6 7311 1 1
1 1 1
2 32


如果x只是一个数字,那么表达式(# $ x)的值为0:
   # $ 17
0
这意味着:尽管表格的维数是2,列表的是1,但单个数字没有维数,因为它的维度计数是0。一个维数为0的数据对象被称为标量。我们说“阵列”是有维数的数据对象,标量也是阵列,是维数为0的特殊阵列。

表达式(# $ 17)值为0。由此我们得出:既然标量的维数为0,那么它的维度表($ 17)必然长度为0(空列表)。既然一个长度为2的列表可以通过表达式2 $ 99来构造,那么长度为0的列表就可以通过 0 $ 99(或者 0 $ 任意数字)来构造。
空列表的值显示时没有输出:
2 $ 990 $ 99$ 17
99 99


需要注意的是,标量(例如17)和只有一个元素的列表(例如 $ 17),或者一个1行1列的表格(比如 1 1 $ 17)是不同的。标量维度为0,列表维度为1,表格维度为2。但是这三个显示时看起来一样:
   S =: 17
   L =: 1 $ 17
   T =: 1 1 $ 17
SLT# $ S# $ L# $ T
171717012


一个表格可能只有一列,但维数依然为2。例如:t有3行1列:
t =: 3 1 $ 5 6 7$ t# $ t
5
6
7
3 12


2.3 术语:秩(Rank)和形状(Shape)

我们之前所说的“维数”在J中叫做“秩”,因此单个数字称为0秩阵列,一列数字称为1秩阵列,等等。一个阵列的维度列表称为阵列的“形状”。

我们使用的“列表”和“表格”(元素为数字)在数学中称为“向量”和“矩阵”。有着3个或者更多维度的阵列(也可以说,秩为3或者更高的阵列)称为“报表”。

下面的表格总结了和阵列相关的术语与函数:
+--------+--------+-----------+------+
|        | Example| Shape     | Rank |
+--------+--------+-----------+------+
|        | x      | $ x       | # $ x|
+--------+--------+-----------+------+
| Scalar | 6      | empty list| 0    |
+--------+--------+-----------+------+
| List   | 4 5 6  | 3         | 1    |
+--------+--------+-----------+------+
| Table  |0 1 2   | 2 3       | 2    |
|        |3 4 5   |           |      |
+--------+--------+-----------+------+
| Report |0  1  2 | 2 2 3     | 3    |
|        |3  4  5 |           |      |
|        |        |           |      |
|        |6  7  8 |           |      |
|        |9 10 11 |           |      |
+--------+--------+-----------+------+ 
这张表格实际上是用一小段J代码生成的是一个真实的“表格”,也就是我们之前讨论的那
种表格。它的形状是6 4。然而,它不仅仅是数字表格,它还包含词语,数字列表等等。下来
我们讨论非数字阵列。  
 

2.4 字符阵列

字符包括字母、标点符号、数字字符等等。我们可以构造字符阵列,如同构造数字阵列一样。一列字符输入时使用单引号引起来,但是显示时没有单引号,例如:
   title =: 'My Ten Years in a Quandary'
   title
My Ten Years in a Quandary
一列字符称为字符串。字符串中的单引号需要输入两个连续的单引号来表示:
   'What''s new?'
What's new?


一个空的(长度为0)的字符串通过两个连续的单引号表示,显示时什么也没有:
''# ''
0


2.5 一些阵列函数

现在是时候探究一下操纵阵列的函数了。J有着非常丰富的阵列函数:这里我们仅仅展示一小部分。

2.5.1 连接(Joining)

内置函数 ,(逗号)称为“追加”。它将事物连接起来构成列表。
a =: 'rear'b =: 'ranged'a,b
rearrangedrearranged


“追加”函数连接列表或者单个元素。
x =: 1 2 30 , xx , 00 , 0x , x
1 2 30 1 2 31 2 3 00 01 2 3 1 2 3


“追加”函数也可以将两个表格首尾相连构成更长的表格:
T1=: 2 3 $ 'catdog'T2=: 2 3 $ 'ratpig'T1,T2
cat
dog
rat
pig
cat
dog
rat
pig

关于“追加”函数更多的信息请参考第5章。


2.5.2 元素

数字列表的元素是这些数字,表格的元素是表格的行。3维阵列的元素是它的平面。更一般地,我们说一个阵列的元素就是该阵列第一个维度上顺序出现的东西。阵列也就是阵列元素的列表。

回忆一下内置函数 #(“总数”)用来求列表的长度。
x# x
1 2 33


一般来说,# 计算阵列的元素数目,也就是说,它给出的是阵列的第一维度:
T1$ T1# T1
cat
dog
2 32


# T1也是T1维度表的第一个元素。标量,维度为0,被当作单独一个元素:
   # 6
1


再回到之前给出的“追加”例子:
T1T2T1 , T2
cat
dog
rat
pig
cat
dog
rat
pig
现在我们可以看出(x, y)实质上就是一个顺序包含了x和y元素的列表。

再来看一个展示“元素”这个概念用途的例子,回忆一下函数 +/+ 插入列表的元素之间。
+/ 1 2 31 + 2 + 3
66

现在我们可以说 +/ 其实+ 插入阵列的元素之间。下面这个例子中的元素是阵列的行:
T =: 3 2 $ 1 2 3 4 5 6+/ T1 2 + 3 4 + 5 6
1 2
3 4
5 6
9 129 12


2.5.3 选择

现在我们看看如何从列表中选取元素。列表的位置从0开始:0,1,2等等 。通过位置选择元素的函数是 { (左大括号,叫做“来自”)。
Y =: 'abcd'0 { Y1 { Y3 { Y
abcdabd


位置号也称为索引。{ 函数的左参数可以是单个索引,也可以是索引列表:
Y0 { Y0 1 { Y3 0 1 { Y
abcdaabdab


看看内置函数 i.(i点号)。表达式(i. n)从0开始生成n个连续数字:
i. 4i. 61 + i. 3
0 1 2 30 1 2 3 4 51 2 3


如果x是个列表,那么表达式(i. # x)生成列表x的所有索引:
x =: 'park'# xi. # x
park40 1 2 3


如果 i. 参数是列表,那么将生成相应的阵列:
   i. 2 3
0 1 2
3 4 5


i. 还有二元模式,叫做“求索引”。表达式(x i. y)找到y在x中的索引位置:
   'park' i. 'k'
3
如果y不在x中,那么将返回x的最大索引加1:
   'park' i. 'j'
4
 
更多的索引方法请参考第6章。
 

2.5.4 相等和匹配

如果我们要检查两个阵列是否相等,可以使用内置函数 -:(减号 冒号,叫做“匹配”)。“匹配”函数测试它的两个参数是否有相同的形状,以及相应的元素是否相同。
X =: 'abc'X -: XY =: 1 2 3 4X -: Y
abc11 2 3 40


不管“匹配”函数的参数是什么,它的结果一定是单个0或者1。

注意一下,空列表和空列表是匹配的。比如空的字符串和空的数字列表:
   '' -: 0 $ 0
1
因为两个列表有相同的形状,而且相应的元素也相同(两个都没有元素)。 

还有另一个函数 =(叫做“相等”)用来测试它的两个参数是否相等。= 逐个比较两个参数的元素,生成一个和参数的形状相同,只包含比较结果的阵列:
YY = YY = 2
1 2 3 41 1 1 10 1 0 0
因此,= 的两个参数形状必须相同(或者至少要兼容,比如 Y=2)。否则就会报错:
YY = 1 5 6 4Y = 1 5 6
1 2 3 41 0 0 1error



2.6 盒子(Boxes)阵列

2.6.1 拼接(Linking)

有一个内建函数 ;(分号,称为“拼接”)。它将两个参数拼接成一个列表,两个参数可以是不同的种类(这一点和“追加”函数不同)。 例如我们将字符串和数字拼接起来:
   A =: 'The answer is'  ;  42
   A
+-------------+--+
|The answer is|42|
+-------------+--+
A是一个长度为2的列表,是一个“盒子”的列表。A的第一个盒子中是字符串'The answer is',第二个盒子中是数字42。盒子在屏幕上显示为一个矩形,盒中的值显示在矩形中。
A0 { A
+-------------+--+
|The answer is|42|
+-------------+--+
+-------------+
|The answer is|
+-------------+


一个盒子是一个标量,不管里面装的是什么;因此盒子可以像数字一样装入阵列中。所以,A是一个标量列表。
A$ As =: 1 { A# $ s
+-------------+--+
|The answer is|42|
+-------------+--+
2+--+
|42|
+--+
0

盒子阵列的主要目的是为了能够将多种不同的值装入单个变量中。例如,一个保存购物单(日期,数量,描述)的变量就可以是一个盒子列表:
   P =: 18 12 1998  ;  1.99  ;  'baked beans'
   P
+----------+----+-----------+
|18 12 1998|1.99|baked beans|
+----------+----+-----------+


注意“拼接”和“追加”的不同。“拼接”可以连接不同种类的值,“追加”只能连接同一种类的值。也就是说,“追加”的两个参数要么都是数字阵列,要么都是字符阵列,要么都是盒子阵列,等等。否则就会报错:
'answer is'; 42'answer is' , 42
+---------+--+
|answer is|42|
+---------+--+
error


有时我们想要将字符串和数字结合在一起,比如要表达计算结果和一些描述。我们可以“拼接”描述和数字,就像上面看到的。但是更自然的方式是将数字转换成字符串,然后将两个字符串“连接”起来。
可以使用内置函数“格式化” ":(双引号 冒号)来将数字转换为字符串。下例中的n是一个数字,s是n的格式化结果—— 一个长度为2的字符串:
n =: 42s =: ": n# s'answer is ' , s
42422answer is 42


关于“格式化”的更多信息,请参考第19章。现在让我们回到盒子主题。因为盒子显示时有矩形轮廓,因此它们在屏幕上显示时可以达到表格的效果。
   p =: 4 1 $ 1 2 3 4
   q =: 4 1 $ 3 0 1 1
   
   2 3 $ ' p ' ; ' q ' ; ' p+q ' ;  p ; q ; p+q
+---+---+-----+
| p | q | p+q |
+---+---+-----+
|1  |3  |4    |
|2  |0  |2    |
|3  |1  |4    |
|4  |1  |5    |
+---+---+-----+

2.6.2 装盒和拆盒

内建函数 <(左尖括号,叫做“装盒”),可以用来构造盒子。将 < 应用于待装入的值将得到一个盒子。
   < 'baked beans'
+-----------+
|baked beans|
+-----------+


尽管盒子可以装数字,但是盒子本身并不是数字。想要对盒子中的值进行计算,就需要“拆开”盒子取出值。函数 >(右尖括号)就是“拆盒”。
b =: < 1 2 3> b
+-----+
|1 2 3|
+-----+
1 2 3


可以把 < 看作一个漏斗。流向宽的那头我们得到数据,流向窄的那头我们得到盒子,盒子是标量,没有维数,也可以看作一个点。同样的类比也适用于 >(方向相反)。既然盒子是标量,那么可以通过“追加”函数将盒子串起来形成列表。但是“拼接”函数更方便一些,因为它将“装盒”和串接一起完成。
(< 1 1) , (< 2 2) , (< 3 3)1 1 ; 2 2 ; 3 3
+---+---+---+
|1 1|2 2|3 3|
+---+---+---+
+---+---+---+
|1 1|2 2|3 3|
+---+---+---+

 

 

2.7 总结

总之,每一个数据对象在J中多是一个阵列,有0个,1个或者更多维度。一个阵列可以是数字阵列,字符阵列,或者盒子阵列(还有其他高级阵列)。

这里就到了第二章结尾了。


说明:
  1. join和link这两个词都有连接,连合之意,但是在J中指的是两种不同的操作,因此我将join翻译为连接,将link翻译为拼接,貌似比较合适。




2012年10月28日星期日

1 基础

这是对<Learning J>(by Roger Stokes)的尝试翻译。

Roger Stokes的版权声明如下:
Copyright © Roger Stokes 2012. This material may be freely reproduced, provided that this copyright notice is also reproduced.
感谢作者的无私奉献,请您转载时也注明以上版权,也请同时注明转载地址http://corwindong.blogspot.com,我将不胜感激。

----------------------------------------------------------------------------------

1 基础

1.1 交互式使用

用户在键盘上敲击一行,输入的可以是表达式,例如:2+2。当该行内容被输入(按了“输入”或者“回车”键),表达式的值将被计算同时显示在下一行上。
   2+2
4 
然后解释器将提示等待输入新的行你可以在距离左边界几个空格的地方看到提示光标。
因此在本书中由几个空格缩进的行代表用户的输入,接下来的那一行(没有缩进),
代表相应的输出。
 

1.2 算术

乘法符号是 *(星号)
    2*3
6
如果我们再试一次,这次输入:2 space * space 3
    2 * 3
6
结果和之前一样,表示这里的空格是可选的。空格可以使表达式可读性好一些。

除法符号是 %(百分号)
    3 % 4
0.75

减法符号依然是我们熟悉的 -
    3 - 2
1
下面这个例子展示负数是如何表示的。负号是在负数开头来一个 _(下划线),下划线和数字之间没有空格。负号不是一个数值函数:它就是一种数字记法,和十进制小数点一样,只是一种记法。
    2 - 3
_1  

求负数的符号也是 - ,和减法符号一样:
    - 3
_3 

幂函数符号是 ^(插入符)。2的立方是8:
    2 ^ 3
8 

平方函数的符号是 *:(星号+冒号)。
    *: 4
16

1.3 一些术语:函数(Function)、参数(Argument)、应用(Application)和值(Value)

以表达式2 * 3为例。我们说乘法函数 * 被应用于它的参数。左参数是2,右参数是3。同时,2和3也被称为参数的值。

1.4 列表(List)型值

有时我们想要把同一个运算应用在一些不同的参数上。例如,一列数字可以表示为 1 2 3 4,数字之间用空格分隔。想要求每个数字的平方,我们可以:
    *: 1 2 3 4
1 4 9 16
我们可以看到“平方”函数(*:)应用到列表中的每个值上。如果把两个列表作为一个函数(例如 +)的参数,那么该函数将应用到每对相应的元素上:   
    1 2 3 + 10 20 30
11 22 33
如果一个参数是列表,另一个是单元素,那么单元素将按照需要被复制:
   1 + 10 20 30
11 21 31
      
   1 2 3 + 10
11 12 13  
 
这个特性有时很有用,比如我们遇到一个新函数,想要看看一列参数的模式能在结果中引
起什么样的模式。
例如,7除以2,商3余1。J内置求余数的函数是 |(竖线),叫做“剩余”函数。参数和
结果的模式如下:
   2 | 0 1 2 3 4 5 6 7
0 1 0 1 0 1 0 1
      
   3 | 0 1 2 3 4 5 6 7
0 1 2 0 1 2 0 1
“剩余”函数和“求模”函数类似,只不过我们写的是(2 | 7)而非(7 mod 2) 
 

1.5 圆括号

表达式可以包含括号,括号的含义和通常一样;括号中实际上就是一个分隔出来的小运算,如:
    (2+1)*(2+2)
12
括号并非必须的。然而,考虑J表达式:3*2+1。它意味着(3*2)+1,等于7吗?还是意味着3*(2+1)等于9呢?
   3 * 2 + 1
9
学校的数学课中我们学到的规则是:乘法优先级比加法高。该规则使得我们可以减少括号
的数量。
但是在J中,没有乘法优先级比加法高这样的规则。如果需要,我们得加上括号。在J中,
有一条括号省略规则,一如3*2+1展示的。该规则是:在没有括号的情况下,算术函数的
右参数是所有它右边的。因此在3*2+1中,*的右参数是2+1。再例如: 
   1 + 3 % 4 
1.75
可以看到 % 先于 +,也就是说,最右边的函数先应用。
 
“最右边优先”的规则和通常的“乘法先于加法”不同,但是扮演的角色是相同的。它只
是一种便利性约定:你可以忽略它转而使用括号。它的便利性在于:在J中,有很多(大概
100个)函数用于数值计算,试图记住哪个函数比哪个函数优先级高是不可能的事。
 
在本书中,我有时会展示一些含有括号的表达式,这些括号在“最右边优先”规则下是不
需要的。这么做的目的在于强调表达式的结构,通过括号分开表达式的各个部分,使之更
具可读性。

1.6 变量和赋值

汉语语句——让x为100——在J中可以表达为:
    x =: 100
该表达式称为赋值,使得值100被赋予一个名字x。我们创建了变量x并使之具有值100。如果一行输入只包含了一个赋值,当把该行输入解释器时,响应中不会有任何显示。

被赋值的名字在接下来的计算中随时可用。
    x - 1
99
 
赋值式中的值本身也可以通过表达式计算:
    y =: x - 1  
此时y被用来记录x-1的计算结果。要看一个变量被赋予了什么值,直接输入该变量的名字
即可。变量名也是一个表达式,只不过形式特别简单:
    y
99 
 
一个变量可以被多次赋值,新值将覆盖旧值:
   z =: 6
   z =: 8
   z
8
变量的值也可以用来计算该变量的新值:
   z =: z + 1
   z
9
之前说过只包含赋值式的行输入时,响应中没有任何值。然而,赋值本身是表达式:它有
一个值,可以用在更大的表达式中。
   1 + (u =: 99)
100
   u
99
 
下面是一些赋值式例子,用来我们展示如何挑选变量名:
   x                       =: 0
   X                       =: 1
   K9                      =: 2
   finaltotal              =: 3
   FinalTotal              =: 4
   average_annual_rainfall =: 5   
每个名字都必须以字符开头。名字只可以包含字符(大小写均可),数字和下划线(_)。
注意大小写是区分的,x和X代表的变量不同。
   x
0
   X
1    

1.7 术语:一元和二元

只接受右边一个参数的函数称为一元函数,或者简称monad。例如“平方”,(*:)。接
受两个参数(一左一右)的函数称为二元函数或者dyad。例如 + 。

减法和求负展示了同一个符号(-)代表了两个不同的函数。换句话说,我们可以说 - 有
一个一元模式(求负)和一个二元模式(减法)。基本上所有的J语言内置函数都有一元
和二元两种模式。再举个例子:除法函数 %,二元模式是除法,一元模式求导数。
   % 4
0.25 
 

1.8 更多内置函数

本节的目的是通过观察一些内置的J函数来展示J语言编程的感觉。
看看汉语表达式:将数字2,3,4一起加起来,或者简洁地说:
加 一起 2 3 4
我们期望得到的结果9. 这个表达式在J中为:
   + / 2 3 4
9
对比汉语和J,“加”表示为 +,“一起”表示为 /。类似的,表达式: 
乘 一起 2 3 4
的结果为24。该表达式用J表示为:
   * / 2 3 4
24
我们发现+/2 3 4意味着2+3+4;*/2 3 4意味着2*3*4。符号 / 称为“插入”,因为它将左
侧的任何函数插入右侧列表的各个元素之间。通用规则为:如果F是一个二元函数,L是数字a,
b,c,... y,z组成的列表,那么:
    F / L     表示    a F b F ... F y F z 
 
让我们继续前行,看看新的函数。考虑如下三个命题:
    2比1大  (毋庸置疑)
    2和1相等(假的)
    2比1小  (假的) 
在J中,数字1表示“真”,数字0表示假。上面的三个命题在J中表示为:
    2 > 1
1
   
    2 = 1
0
    
    2 < 1
0
 
如果x是一列数字,比如:
    x =: 5 4 1 9    
我们想知道:x中哪些数字比2大?
    x > 2
1 1 0 1
第一个,第二个和最后一个结果为真。是不是x中的所有数字都大于2呢?
    * / x > 2
0  
不是,因为我们看到x>2结果为1 1 0 1。任一个0(假)都使得乘法(1*1*0*1)结果不可能
为1。
 
x中有多少元素大于2?我们将x>2中的1加起来:
   + / x > 2
3
 
x中有多少数字呢?我们可以将x=x中的1加起来:
   x
5 4 1 9
   
   x = x
1 1 1 1
   
   +/ x = x
4
其实不需这么麻烦,有一个内建函数 #(总数)可以给出一个列表的长度:
   # x
4 
 

1.9 并排显示

当我们输入J表达式时,表达式和结果在屏幕上挨着向下显示。我再展示一下之前的那几行:
   x
5 4 1 9
   x = x
1 1 1 1
   +/ x = x
4
   # x
4
在本书中,我有时会并排显示一些行而不是竖着向下显示,比如:
xx = x+/ x = x# x
5 4 1 91 1 1 144
这表示:在处理过程中,你输入x看到响应5 4 1 9.你输入x = x看到1 1 1 1,等等。并排
显示不是J系统的一项特性,只是本书中使用的图表。它们在第一行显示表达式,在第二行
显示相应的响应。

当你输入一个赋值式(x =:something)时,J系统并不显示值。然而,赋值式也是一个表
达式,也有值。有时能够看到赋值式的值是很便利的,因此我会在并排显示中列出赋值式
的值。例如:
x =: 1 + 2 3 4x = x+/ x = x# x
3 4 51 1 133


现在回到内置函数。假设我们有一个列表,我们可以通过说例如“yes, yes, no, yes,
no”从列表中轮流选取元素。选取序列为1 1 0 1 0。这样的0/1列表也被称为位串(或者
位表,位向量)。有一个函数,二元 #,接受一个位串(选取序列)作为它的左参数去
选取右参数中相应的元素。
y =: 6 7 8 9 101 1 0 1 0 # y
6 7 8 9 106 7 9
我们可以从y中选取满足某种条件的元素,例如:那些大于7的项:
yy > 7(y > 7) # y
6 7 8 9 100 0 1 1 18 9 10

1.10 注释

在一行J代码中,符号NB.(大写的N和B,以及点号)引入注释,注释直到行尾,不会
被求值。例如:
   NB.   this is a whole line of annotation
   
   6 + 6   NB. ought to produce 12
12 
 

1.11 内置函数的命名规则

每个内置的J函数都有一个非正式名字和一个正式名字。例如:正式名为 + 的函数有个非正式名“加法”。而且,函数还有一元模式和二元模式,因此正式名为 - 的函数有两个非正式名“求负”和“减法”。

非正式名实际上是函数的简短描述,通常一个词。J系统并不认识非正式名,也就是说,J中的表达式一定使用函数的正式名。在本书中,非正式名将被引号引起来,比如:“减法”。

基本上所有的内置函数都有一个字符或两个字符的正式名。例如 * 和 *: 函数。第二个字符往往是 :(冒号)或者 .(点号)。

两字符的名字往往意味着和单字符的基础函数有些关系。比如“平方”(*:)和“倍数”(*)。

因此内置的J函数往往意味着一组函数(6个相关函数)。有一元和二元模式,每个模式又分基础函数,冒号函数和点号函数。这里展示一下 > 函数组。

二元 > 表示“大于”,我们已经见过。

一元 > 后面再说。

一元 >. 将它的参数向上取整。注意是向上取整,不是取最接近的整数。因此非正式名为“上限”
   >. _1.7 1 1.7
_1 1 2
 
二元 >. 选择两个参数中较大的值
   3 >. 1 3 5 
3 3 5
我们通过在数据项之间插入“较大”函数(用 /)来找最大值。例如:1 6 5中的最大值可
以用(>. / 1 6 5)找到。下面的几行将解释结果为何是6,其中注释解释了每行的结果为什
么相同:
   >. / 1 6 5
6
   1 >. 6 >. 5      NB. by the meaning of /
6
   1 >. (6 >. 5)    NB. by rightmost-first rule
6
   1 >. (6)         NB. by the meaning of >.
6
   1 >. 6           NB. by the meaning of ()
6
   6                NB. by the meaning of >.
6 

一元 >: 非正式名为“递增”。它对其参数进行加一操作:
   >: _2 3 5 6.3
_1 4 6 7.3
 
二元 >: 表示“大于等于”
   3 >: 1 3 5 
1 1 0
 
第一章到此结束。