         MudOS 的 mapping 数据类型帮助文档
                 Truilkan@TMI / 文
                    jjgod / 译
                    1992/09/28
                         
MudOS 0.9 提供了一种叫做 mapping 的数据类型，mapping
是和其他语言(例如Perl)中的联合数组等价的。联合数组与
标准的数组的分别在于，联合数组可以用任意的数据类型来
建立索引(如 string、object、int、array 等等)而不是仅
仅用整数。另外，联合数组是一种“稀疏”的数组，因为一
个 mapping 可以给第 1,000,000 个元素赋值而不给其他所
有的元素赋值。mapping 有两个独特的好用处：

1、数据库
2、代替“struct”类型

一个 mapping 是这样声明的：

mapping x;

一个 mapping 可以这样来初始化：

   x = ([key0 : value0, key1 : value1, ...]);

   (注意：“x = ([]);”可用于创建一个空的 mapping)

注意，一个 mapping必须在你给它分配任何元素之前初始化，
这个限制是因为 MudOS将所有的变量(无论什么类型)都初始
化为 0，如果你不预先初始化一个 mapping，当你尝试给这
个 mapping 分配元素时，你将看到“Indexing on illegal
type”这样的出错信息。

新的 (key, value) 对照可以这样加入 mapping 中：

x[key] = value;

上面这种方式使得 driver 为了指定的键，去寻找一个叫做
“x”的 mapping，如果这个 mapping 里面已经有了这个键，
那么 mapping 中这个键对应的值就被替换为等号右边的值。
如果 mapping 中还没有这个值， 一块额外的空间将被自动
(动态的)分配出来，然后这个 (key, value) 的对照将被插
入这个 mapping 中。

一个映射中的元素可以像下面这样来引用：

        write(x[key] + "\n");

一个映射中的元素可以像下面这样来删除：

        map_delete(x, key);

这种删除的方式将会导致下面的表达式返回真(1)：

        undefinedp(x[key])

因此你可以像这样写段程序：

if (undefinedp(value = x["MudOS"]))
{
        write("“MudOS”并未在映射“x”中用作一个"
              "键。\n");
} else
{
        write("“MudOS”键的值是：" + value + "。"
              "\n");
}

映射中键(索引)的列表可以用 keys() efun 来获得， 比如
说：

        mixed *idx;
        mapping x;

        x = ([ "x" : 3, "y" : 4]);
        idx = keys(x);

idx == ({ "x", "y" }) 或 ({ "y", "x" })。

注意，key() 返回的索引列表是明显用一个随机的顺序排列
的(这个顺序是储存 mapping 的一个副作用)。

映射中值(value)的列表可以用 values() efun 来获得，比
如说：

        idx = values(x);

这样 idx 将会等于 ({ 3, 4 }) 或 ({ 4, 3 })。
注意，values() 返回的值的顺序是与 keys()返回的键的顺
序一致的。

映射中(key, value)的对照可以用 each() efun一次次的传
回， 当到达了映射的结尾时，each() 会返回一个空的向量
(0, 0)。each() 返回的顺序是和 key()、values() 的顺序
一致的。例如：

        mixed *pair;

        while ((pair = each(x)) != ({ }))
        {
                write("key   = " + pair[0] + "\n");
                write("value = " + pair[1] + "\n");
        }

(注：MudOS v22 中 each() 函数已经被去掉)。

映射可以是二维的(如果有必要，也可以是多维的)，就和数
组一样。

        mapping x, y;

        x = ([ ]);
        y = ([ ]);

        y["a"] = "c";
        x["b"] = y;

结果 x["b"]["a"]  == "c"

映射也可以使用“*”运算符：

        mapping r1, r2, a;

        r1 = ([ ]);
        r2 = ([ ]);

        r1["driver"] = "mudlib";
        r2["mudlib"] = "castle";

因此：

        a = r1 * r2 

使 a 变成这样一个映射：a["driver"] == "castle";

你也可以把两个映射加起来，两个映射的和就是把它们联合
起来。

        a = r1 + r2

这样 a 变成了：
a["driver"] == "mudlib" 而且 a["mudlib"] == "castle"

+= 运算符也是支持的，因此你可以这样用：

        a += ([ key : value ]);

可以替代：

        a[key] = value;

可是，后面的方法会有效率得多，因为前面的要先创建一个
新的映射，再把它们俩加起来，而后面的不必。

映射中减运算符应该并没有定义，你可以用 map_delete()。

sizeof() 这个 efun 可以用于测定这个 mapping 中一共有
多少对(key, value)对照。

        write("映射“x”包括" + sizeof(x) + "个元素"
              "。\n");

执行方式：

MudOS 的 mapping是使用一个可扩展的哈希表来实现的，这
个哈希表的容量通常是两倍的，就是说当此哈希表的使用率
趋近于满的时候，哈希表的容量将被扩展为原先的两倍，以
保证它存取的效率。

制作者：

MudOS 的 mapping类型最初由 Whiplash@TMI 完成，一部分
的内容在后来由 Truilkan@TMI重写过(为了使用一个可扩展
哈希表就好像一个2杈树)。

实现 mapping 的一部分数据结构是基于 Larry Wall的Perl
语言中的 hash.c 模块。Perl 程序包是由 GNU Copyleft的
GPL(General Public License)保护的。

翻译使用的词汇：

associative     ：联合
key             ：键
dynamically     ：动态
mapping         ：映射
implementation  ：执行