4

什么array get返回,一个引用或一个值?我有一个将列表作为值的数组,并且必须经常修改列表。这样做的有效方法是什么?

4

1 回答 1

10

首先是一些基础知识。Tcl 没有引用。没有任何。所以 tcl 中的所有命令总是返回值。

所以你的第一个问题的简单答案是它返回一个值。

为了深入研究 tcl 的值语义如何工作的细节,有两种看待事物的方式。

首先,严格从语言规范中看到的语言。换句话说,用户/程序员的观点。从这个角度来看,tcl 只能做一件事:处理字符串。tcl 中的所有内容都是字符串。从技术上讲,您可以说 tcl 具有极强的值语义并且几乎没有任何引用语义(有点像 C,除了 C 更喜欢数字(甚至字符串只是 C 中的数字数组))。

如果是,什么是列表?好吧,从这个角度来看,列表只不过是特殊格式化的字符串。如果一个字符串看起来像一个列表,那么它就是一个列表。如果不是,则为无效列表。在任何一种情况下,它们都是字符串。关于数字也可以这样说。

那么,什么是数组呢?好吧,数组有点特别。同样,文件是特殊的,url 也是特殊的。要获取文件的值(内容),请使用openand read和等命令gets。要获取数组的值,您可以使用类似array get的命令和特殊$array_name(key)语法。您可以将数组视为一种内置的简单键值对数据库。它们的行为不像 tcl 中的常规变量,因为会$array_name产生语法错误,而不是数组值(内容)的字符串表示形式。但是array get允许将数组序列化回字符串表示形式,因此从everyting-is-a-string 的角度来看,一切都很好。

第二个观点是语言是如何实现的。在 C 级别,tcl 中的所有内容都是一个对象,变量/值总是作为指针传递。Tcl 竭尽全力以一种访问和修改尽可能快的形式存储数据。所以一个列表,虽然从高级视图来看只不过是一个字符串格式约定,但在低级别实际上与字符串不同。这允许 tcl 快速处理列表、数组和数字。但是,如果您明确要求 tcl 将列表、数组或数字视为字符串,那么 tcl 就别无选择,只能将对象解析为字符串,然后再将该字符串重新解析回本机对象类型。这被称为闪烁,它会消耗大量 CPU 周期。

Tcl 还在底层实现了 modify-on-write。因此,返回列表或字符串的完整副本实际上不会导致在内存中创建对象的另一个副本。仅当您尝试修改返回值时才会创建副本。

因此,如果您关心速度(正则表达式、字符串优先等),则第二个问题的答案是避免使用字符串命令处理列表数组。使用列表命令处理列表,使用字符串命令处理字符串。在某些情况下您无法避免它,并且在某些情况下字符串命令可能更容易并且速度并不重要,但通常尽量避免闪烁。养成一个好习惯。

综上所述,修改列表最有效的方法是在数组上使用列表命令(lsetlrange)。例如,要修改数组“foo”中列表“bar”中的第二个元素,我们可以这样做:

lset foo(bar) 1 "new value"
于 2013-06-12T15:47:09.173 回答