Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does array get return a reference or a value?

Tags:

tcl

What does array get return, a reference or a value? I have an array which has lists as values, and the lists have to be modified frequently. What is the efficient way to do that?

like image 285
Dronacharya Avatar asked Dec 27 '22 02:12

Dronacharya


1 Answers

First some basics. Tcl has no references. None whatsoever. So all commands in tcl always return values.

So the simple answer to your first question is it returns a value.

To delve into the details of how tcl's value semantics work, there are two ways of looking at things.

First, there's the language seen strictly from the language specification. In other words, the user's/programmer's perspective. From this perspective tcl can only do one thing: process strings. Everything in tcl is a string. More technically you can say that tcl has extremely strong value semantics and almost no reference semantics whatsoever (kind of like C except that C prefer numbers (even strings are just arrays of numbers in C)).

If so, what are lists? Well, from this perspective, lists are nothing more than specially formatted strings. If a string looks like a list then it's a list. If not it's an invalid list. In either case they're both strings. The same can be said about numbers.

So, what are arrays then? Well, arrays are a bit special. In the same way files are special and url's are special. To get the value (content) of a file you use commands like open and read and gets. To get the value of an array you use commands like array get and the special $array_name(key) syntax. You can think of arrays as a sort of built-in simple key-value pair database. They don't behave like regular variables in tcl because $array_name yields a syntax error instead of the string representation of the value (content) of the array. But array get allows arrays to be serialized back into a string representation so all is well again with the everyting-is-a-string point of view.

The second point of view is how the language is implemented. At the C level, everything in tcl is an object and variables/values are always passed as pointers. Tcl goes to great lengths to store data in a form that is as fast to access and modify as possible. So a list, while from the high level view is nothing more than a string format convention, at the low level is actually implemented differently from a string. This allows tcl to process lists and arrays and numbers quickly. But if you explicitly ask tcl to treat a list or array or number as a string then tcl has no choice but to parse the object into a string and later reparse that string back into the native object type. This is known as shimmering and it consumes a lot of CPU cycles.

Tcl also implements modify-on-write under the hood. So returning a complete copy of a list or string does not actually cause another copy of the object to be made in memory. Copies are only created if you try to modify the returned value.

So the answer to your second question is to avoid processing the array of lists with string commands if you care about speed (regexp, string first etc). Use list commands to process lists and string commands to process strings. There are cases where you can't avoid it and there are cases where string commands may be easier and speed is not important but in general try to avoid shimmering. It's a good habit to acquire.

In light of all the above, the most efficient way to modify the lists is to use the list commands (lset, lrange etc.) on the array. For example, to modify the second element in the list "bar" in the array "foo" we'd do this:

lset foo(bar) 1 "new value"
like image 187
slebetman Avatar answered Feb 04 '23 21:02

slebetman