I just wanted to know the pros and cons of TCL. Just now I tried to
return an array from proc it is not returning. Even I had a doubt, as
we have array concept in TCL what is the need of keylist? and We can
return a keyList fron proc but we cannot return array. So, I thought I
better to know the pros and cons of TCL...
Thanks in advance!
-Anil A Kumar
Asking for pros and cons of Tcl is like asking which notes in a song
are too loud or too soft. Without knowing what you consider "loud" or
"soft" we can't give a good answer. And what is too loud for one type
of song (lullaby, for example) might be too soft for another (heavy
metal rock). Similarly with software, what you call a pro might be a
con for someone else, and what is a pro for one type of application
might be a con for another.
What you need to know about Tcl is this: it is different. Don't expect
it to work like other languages. This isn't a bad thing, it's what
gives Tcl its strength. There are things you can do in Tcl that are
virtually impossible in other languages. Of course, the opposite is
true as well, there are things you can do in other languages that you
can't easily do in Tcl.
About pros and cons, it depends on what you want to do and with what
you compare.
Lets try a comparision of the mainstream Python 2.6 with the upcoming
Tcl 8.6.
Tcl's pro points there (compared to Python)
- Nicer Unicode and encoding support
- Better Threading support (especially for Embedding in multithreaded
C/C++ code)
- Nicer event based programming (unless you add the Twisted package to
Python)
- Better Metaprogramming abilities / write your own DSL stuff
- Better Tk integration
- Better x-platform abilities (e.g. symlinks/reparse points on all big
platforms...)
- Better single file deployment options
- Safe Interpreters
- Better packaging system (but you can argue here)
Tcl's con points (compared to Python)
- More verbose syntax
- fewer 3rd party libraries available
- No good UDP or IPv6 support on all platforms
- Often slower
- No access to much platform specific stuff in the core language
( which is a consquence of better x-platform abstraction, you cannot
have both)
- Not so many books
I guess i forgot a lot of other pro/con things that might interest one
or the other.
Michael
Sorry, I was supposed to ask limitations....
Thanks,
This is something that I have generally agreed with over the years,
but as time goes on, I have found fewer things which fall into the
category of "things you can't easily do in Tcl".
What we have, IMHO, is a lack of evangelism and experimentation in
Tcl, and a general inferiority complex in certain areas: objects,
design patterns, algorithm support, data structure support.
I was forced to revise my own misconceptions when I translated two C
programs into Tcl without understanding either the datamodel or the
algorithm in either program. The first was a brute force sudoku
solver. I used an identical algorithm and data structure. The second
was an exact cover algorithm (dancing links) that used a single non-
recursive compact algorithm with goto jumps. Again, without the
slightest understanding of the algorithm, I had no problem with the
translation. Code lines for each version were similar to the
original.
No one has yet answered your first question on arrays. Yes, you can
return an array from a proc, just not by value.
proc foo {varName} {
upvar $varName local
set value 0
foreach name {a b c d} {set local($name) [incr value]}
}
array set bar {}
% foo bar
% parray bar
bar(a) = 1
bar(b) = 2
bar(c) = 3
bar(d) = 4
If you really want by value, flatten it to a list for the return call
with 'return [array get <name>]'
--
> I just wanted to know the pros and cons of TCL.
They are similar to the pros and cons of any other programming
language.
Cons:
1. you have to learn how to design and implement algorithms in general
to be able to write useful complex programs (in any language)
2. you have to learn the language well not to get bit by language
pecularities
3. you have to learn the language by writing code if you want to be
comfortable writing programs that tend to work.
4. you have to learn where the resources are to look up "how to ..."
and "why did ..." type questions
Pros:
1. you can write all sorts of programs, of all sizes, in Tcl.
2. once you are comfortable reading and writing tcl, as well as how to
design and implement an algorithm, you can expect to get the job done
3. you have access to real-time IRC chat areas, wikis, and web
discussion groups where questions are typically answered without too
much grief.
> No one has yet answered your first question on arrays. Yes, you can
> return an array from a proc, just not by value.
>
> proc foo {varName} {
> upvar $varName local
> set value 0
> foreach name {a b c d} {set local($name) [incr value]}}
>
> array set bar {}
>
> % foo bar
> % parray bar
> bar(a) = 1
> bar(b) = 2
> bar(c) = 3
> bar(d) = 4
>
> If you really want by value, flatten it to a list for the return call
> with 'return [array get <name>]'
>
Well, technically speaking, you are not returning an array. Instead,
you are directly modifying the array. And of course, another method of
doing that would be to build the array within a namespace (even if
only the global namespace) and then just modify it directly.
At least in the way you do it, the same proc can easily be used for
multiple arrays - in the case of the global array situation, to make
it "generic" you would have to pass in the array name and then use a
variable holding the name or some such thing.
Can you return an actual data structure in any language? Probably you
return a pointer to the start of the structure. In Tcl, you usually
pass in the name of the array, the procedure then uses the array name
to create/update the array, but just like in most languages, the
structures created inside a function (local variables, and the
associated storage) disappear once the function returns, so persistent
structures must be created somewhere else.
Larry,
you are correct. I just wanted to return the array from the proc
directly. And keyed lists are also similar to arrays. As we are using
hash arrays in tcl infact we can use the same facility with
keyedlists. But we can easily return keyedlists from proc. Any I have
few more doubts like we have sleep and after both do the same thing,
they wait by specified by the amount of time mentioned. But difference
is after is in msec but sleep takes seconds. Why do we have these
duplicate commands.
In C we can call procs by references but in TCL we cannot. Just wanted
to list out the things like these.
I will be happy if we can figure out the duplicate commands, or
atleast the main purpose of these kinds of similar commands.
Basically you are speculating. Do you really think we have two
identical commands?
> In C we can call procs by references but in TCL we cannot. Just wanted
> to list out the things like these.
Not sure what you mean here. You can store a procedure name in a
variable, and then place the variable where a command should go:
% set a puts
% $a hi
hi
% $a $a
puts
Tcl has a more general concept of call by reference, we have named
references which you don't even need to pass around in order to use
(assuming you agree on the name ahead of time). But it seems the same
as with C, if you ask me.
> I will be happy if we can figure out the duplicate commands, or
> atleast the main purpose of these kinds of similar commands.
The main purpose is that they are different commands. One difference
is that [after] works with the event loop and sleep just halts the
execution of the current script for the specified time.
can u give more details on event loops...
Like Tom says, they are different. These two forms do the same thing:
sleep 1
after 1000
But [after] does more when a script is placed at the end.
set count1 0
set count2 100
proc refresh1 {} {
puts [incr ::count1]
after 1000 {refresh1}
}
proc refresh2 {} {
puts [incr ::count2]
if {$::count2 == 120} {set ::done 1; return}
after 1200 {refresh2}
}
refresh1; refresh2
vwait done
puts finished
exit
Paste that into tclsh. In the above, background activity (sockets,
pipes, Tk, etc..) would be allowed due to entering the event loop. A
blocking [sleep] is not the same.
--
> can u give more details on event loops...
There is an event queue and a loop.
I can't resist having a go too :-)
The con here is that Tcl arrays are not arrays as anyone else
understands the term.
The confusion is between variables and values - an array is a special
sort of variable not a special sort of value.
There are no types in Tcl.
Every VALUE is effectively a string.
An array isn't a value (but it's elements and keys are).
All the things that seem to be types in Tcl such as list, dict,
numbers are best thought of as strings that are optimized for a
particular use and strings can be freely returned from procs.
If the string representation looks like a dictionary then it can be
used as one but that use will be more efficient if you just built it
with the dict command and not the list command.
None of this is really a deficiency of Tcl but just an area of
potential confusion.
I wouldn't bother trying to make detailed list of differences between
C and Tcl because you will get bogged down in trying to make precise
definitions of things that people think that they understand but
actually haven't thought deeply about. You wouldn't try to compare C
to Lisp and you shouldn't try to compare it to Tcl.
Before you can compare two languages, you first have to decide the
purpose of the comparison. Tcl may be unique among general purpose
programming languages in one respect: it was initially designed to
leverage the vast supply of existing operating system/shell commands
and programs (and C library code). The tcl shell, "tclsh" is a safer
and easier to comprehend shell than the typical shells available on
unix-like systems. Whereas Java and C# have been forced to recreate
all the system level and application level tools, Tcl was designed to
use what is already there. Because of that high-level reuse of
existing components, there is very little need or interest in
rewriting libraries and applications in Tcl. I'm just talking about
Tcl, someone else could probably point out the usefulness of Tk to
expose existing command line applications and libraries as GUI
applications.
So, although there may be languages which are faster at the algorithm
level, this is generally not a problem with Tcl, because the focus is
on leveraging everything that is available, not replacing it with a
Tcl only solution.
Nicely said. Tcl's specifically intended to be used with components
(err, commands) from other languages. There's no shame in doing just
that.
Donal.
This reply is to Nick.
Nick even keyed lists also have the keys, but still we can return them
from a proc. And I know TCL array are hash arrays, but the concept is
same,isn't it?
And I just raised the issue not to compare TCL with other languages.
Since from 2 years I am working on TCL, I know the beauty of TCL, and
easiness. But my main intention is to let the TCL lovers to know about
the cons, so that if they can get any solution or alternate to that.
And that will be helpful to us. One more thing is, if don't know the
limitations, some times we cannot work properly, eg.: While writing a
script one of my procs I was returning an array, I got an error
message saying "a is not a variable and it is an array". Earlier I
don't know that we cannot return an array, I had spent ;ot of time to
figure it out, so I just want to prepare document, so that we can
share that to all our TCL lovers.
-Anil A Kumar
keys are values not variables.
arrays aren't values they just happen to be implemented using some of
the same C code as for dicts which are values.
> And I just raised the issue not to compare TCL with other languages.
> Since from 2 years I am working on TCL, I know the beauty of TCL, and
> easiness. But my main intention is to let the TCL lovers to know about
> the cons, so that if they can get any solution or alternate to that.
This is what I thought. Whatever you know about Tcl my point was that
I don't think that you will be able to get it across to non-Tcl people
by trying to compare Tcl to C.
> And that will be helpful to us. One more thing is, if don't know the
> limitations, some times we cannot work properly, eg.: While writing a
> script one of my procs I was returning an array, I got an error
> message saying "a is not a variable and it is an array". Earlier I
> don't know that we cannot return an array, I had spent ;ot of time to
> figure it out, so I just want to prepare document, so that we can
> share that to all our TCL lovers.
Here's my attempt at a simple comparison to C showing why arrays are
as they are.
NB This is not the real Tcl code as that is much more complicated but
hopefully it gives an insight.
struct Tcl_Obj {....}; // All Tcl values really are Tcl_Obj*
struct Tcl_Dict : public Tcl_Obj { Tcl_Obj* keys; Tcl_Obj*
values; } // Not real Tcl but a dict really is a value
// array set aTclArray {}
Tcl_Dict aTclArray;
// proc aTclProc {} {return [dict]}
Tcl_Obj* aTclProc() // All Tcl procs really do return Tcl_Obj* (just
not like this)
{
return new Tcl_Dict();
}
// set aTclVar [aTclProc]
Tcl_Obj* aTclVar = aTclProc(); // OK
// set aTclArray [aTclProc]; # ERROR - aTclArray is not a variable
Tcl_Dict aTclArray = ATclProc(); // ERROR - type mismatch
// proc badTclProc { array set a {}; return $a }; # ERROR because not
returning Tcl_Obj*
Tcl_Dict* badTclProc() // Not valid because all procs must return
Tcl_Obj*
{
return new Tcl_Dict();
}
To be honest I doubt that this is any more helpful than any other
explanation but maybe it will make some sense to C/C++ programmers.
IMHO If there was a clear concise explanation then someone more
articulate than me would have given it by now. If you manage to
succeed where all before you have failed then you will be a hero of
the Tcl community but just saying that you can't return arrays is too
simplistic.
You might like to remind people that one of the pros of arrays
compared to dict values is that you can trace/bind individual array
elements whereas you cant trace/bind values in a dict (or "keylist").
I like to refer people who are getting confused by names/variables and
values to Lewis Carroll (It wont clear up the confusion but it made me
think when my IT Professor first told it):
The name of the song is called "Haddocks' Eyes."'
`Oh, that's the name of the song, is it?' Alice said, trying to
feel interested.
`No, you don't understand,' the Knight said, looking a little
vexed. `That's what the name is called. The name really is "The Aged
Aged Man."'
`Then I ought to have said "That's what the song is called"?'
Alice corrected herself.
`No, you oughtn't: that's quite another thing! The song is called
"Ways and Means": but that's only what it's called, you know!'
`Well, what is the song, then?' said Alice, who was by this time
completely bewildered.
`I was coming to that,' the Knight said. `The song really is "A-
sitting On A Gate": and the tune's my own invention.'
Can you please name a single language which returns an array? An array
is a type of storage, not a value.
But forget about reality for a minute. It is considered bad design for
a procedure to choose the name of an [upvar]'d variable in Tcl. The
general practice is to pass in the name of the variable to be created
in the current scope. IF you were able to return a local array (does
that phrase have meaning?), it is important to point out that the next
attempt at accessing the array would lead to a serious error since the
array no longer exists.
senario: returning array
# -----------------------------
package require Tclx
# Set an array
array set anil {a 1 b 2 c 3 d 4}
# proc which returns an array
proc arrayTest {args} {
array set procArray {1 a 2 b 3 c 4 d}
return $procArray
}
# Test the proc
arrayTest
#output:
#C:\Documents and Settings\Advay\Desktop>tclsh85 sample1.tcl
#can't read "procArray": variable is array
# while executing
#"return $procArray"
# (procedure "arrayTest" line 3)
# invoked from within
#"arrayTest"
# (file "sample1.tcl" line 15)
#----------------------------------------
Senario: calling a proc by array.
#---------------------------------------
# -----------------------------
package require Tclx
# Set an array
array set anil {a 1 b 2 c 3 d 4}
# proc which returns an array
proc arrayTest {args} {
array set procArray {1 a 2 b 3 c 4 d}
return $procArray
}
# Test the proc
arrayTest $anil
#output:
#C:\Documents and Settings\Advay\Desktop>tclsh85 sample1.tcl
#can't read "anil": variable is array
# while executing
#"arrayTest $anil"
# (file "sample1.tcl" line 15)
---- This because we can't use an array as a variable directly we can
parse it and use it.
1. I just want to let you guys know that we can't use arrays to return
any arrays from procs, that may lead to tcl crashes. Even while
calling procs we can use parsed arrays, but not entire array.
2. Tom, Nick, Donal, Ralf, David, and Larry can we prepare a document
which gives the limitations of TCL, it is not to hurt TCL lovers but
to help them in scripting, if they know all these issues they they can
use TCL effectively. What do you say. Or else at least we can post all
these thing in blog.
Please let me know your concerns, you can send me an email @---
401...@gmail.com/ you can post your comments here.
-Anil A Kumar
You may be interested in this part of the Tcl tutorial, which is part
of the official Tcl documentation: http://www.tcl.tk/man/tcl/tutorial/Tcl23.html
And this page from the Tcl wiki: http://wiki.tcl.tk/3262
You might add some comments about limitations on passing arrays to
this page: http://wiki.tcl.tk/19838
Most college programs (used to) start with Pascal. Any document that
you would feel to be helpful would only be from your own perspective,
thus would not be appropriate to cover others point-of-views as they
approach this new paradigm.
We already explained pass-by-reference, but if you can't grasp it now,
let it brew for later until it clicks.
In your script, change 'return $procArray' to be 'return [array get
procArray]'. That is a flattened list. Or return use a dict like so:
proc qwe {} {set foo [dict create one 1 two 2]; return $foo}
qwe
dicts are similar to lists in their storage, but are accessed more like
a structure. Hit the docs to read about them:
http://www.tcl.tk/man/tcl8.5/TclCmd/dict.htm
Or the proc may take a name of an array that it will be modified in the
caller's frame with [upvar] for pass-by-reference.
Arrays not returnable by procs is NOT a limitation. The only limitation
I see is your understanding of Tcl's features.
# Set an array
array set anil {a 1 b 2 c 3 d 4}
# proc which returns an array
proc arrayTest {{arrayName {}}} {
upvar $arrayName local
if {[array exist local]} {
puts "found the array, a=$local(a)"
}
set procDict [dict create 1 a 2 b 3 c 4 d]
return $procDict
}
# Test the proc
arrayTest
arrayTest anil
--
It's all in the wiki already: http://wiki.tcl.tk
--
What does Tclx have to do with anything below? Nothing.
> # Set an array
> array set anil {a 1 b 2 c 3 d 4}
This creates an array at the global level. You can do this in C in a
code file outside of a function:
static char buf[100];
A function defined in that file can refer to this variable and the
variable will continue to exist after the function returns.
If you define an array inside a function in C:
int
NsTclServerObjCmd(ClientData arg, Tcl_Interp *interp, ...)
{
Pool *poolPtr;
char mybuf[100];
...
}
There is no way to return "mybuf" from this function, and the array
will cease to exist after the function returns.
How is this different from Tcl? It isn't.
> # proc which returns an array
> proc arrayTest {args} {
> array set procArray {1 a 2 b 3 c 4 d}
> return $procArray
>
> }
If you assumption is invalid, any conclusions you reach based upon the
assumption will be invalid. procArray is created withing the
procedure. You can't return variables which exist in a procedure.
Also, $ "operator" can't be applied to procArray because procArray
isn't a variable. Tcl has several namespaces where it looks up stuff.
Unlike most languages, you can reuse names as long as the things you
are naming exist in different namespaces. One namespace is for
procedure names, another is for variables, still another is for array
names. However, array names can't be used as variable names. I don't
know the reason for this limitation, but if it was possible, debugging
code would be a little more difficult. Anyway, procArray isn't in the
list of variables which exist inside your procedure. But if procArray
was the name of a variable, $procArray would not return the variable,
it would return the value of the variable. A procedure which returned
$procArray would not be returning the storage location, but a value.
The variable procArray, the place in memory where it exists would not
be accessible after your proc returned. No different than any other
language which can define and use local variables.
> # Test the proc
>
> arrayTest
>
> #output:
> #C:\Documents and Settings\Advay\Desktop>tclsh85 sample1.tcl
> #can't read "procArray": variable is array
> 1. I just want to let you guys know that we can't use arrays to return
> any arrays from procs, that may lead to tcl crashes. Even while
> calling procs we can use parsed arrays, but not entire array.
Seriously? No language can "return" an array, since an array is
storage, memory.
If you open a file on disk, can you return the file? No. The file
remains on disk. A file on disk is exactly the same as a char array in
memory. You can't "return" such a thing. And if you create this
storage inside a proc or function, even references to it become
invalid once the proc or function returns.
Doesn't this exclusion effectively put them in the same namespace?
Or are there really different lookup-tables for variables and arrays
inside each scope or tcl-namespace?
My guess is that the names are stored in the same hash array. If the
named variable was an array, the associated value would be a pointer
to another hash array which stored the name-value pairs.
The main point is that an array is not a "value", and neither is a
variable. Neither a variable nor an array can be "returned" by a proc.
But this is no different than any other programming language. At most
you can return a reference or a pointer to an array, which in Tcl is
just the name of the array.
Keyed list and the sleep command are not part of Tcl but rather TclX (an
extension).
Tcl 8.5+ does have dictionaries, which are like keyed list.
>
> Basically you are speculating. Do you really think we have two
> identical commands?
>
>> In C we can call procs by references but in TCL we cannot. Just wanted
>> to list out the things like these.
>
> Not sure what you mean here. You can store a procedure name in a
> variable, and then place the variable where a command should go:
>
> % set a puts
> % $a hi
> hi
> % $a $a
> puts
I *think* he meant pass variables to a procedure by reference -- yes we have
that, as in:
proc AddOne {varName} {
upvar $varName localVar
incr localVar
}
set x 1
AddOne
puts "x = $x"
We also have pass by name via uplevel.
--
+------------------------------------------------------------------------+
| Gerald W. Lester |
|"The man who fights for his ideals is the man who is alive." - Cervantes|
+------------------------------------------------------------------------+
Hrm. Without any desire to re-re-launch the boring terminology debate
about "by name vs. by reference", [upvar] is the only name/reference
manipulation primitive. Uplevel is a completely different beast,
actually a variant of [eval] climbing the ladder of call frames.
(Andreas, I know you know this, I just wanted to eliminate what I felt
was a risk of extra, unneeded confusion in our collective response to
Anil)
-Alex
And I added confusion myself since I'm pretty sure Andreas and Gerald
are two different people ;-)
Sorry guys.
-Alex
Note that I didn't author the above statement. Gerald, you are now
almost as sloppy as I am ;-)
> Keyed list and the sleep command are not part of Tcl but rather TclX (an
> extension).
I guess that explains the [package require in the examples]. [sleep]
must be from AOLserver's [ns_sleep], and the keyed lists are probably
from AOLserver's [ns_set].
> Tcl 8.5+ does have dictionaries, which are like keyed list.
AOLserver's [ns_set] has some features not found in [dict]. The most
important is that it maintains the order in which key-value pairs are
added, and keys can appear more than once, with other keys between
identical keys. You can also search for keys in a case-insensitive
way. An example use-case for this is to handle HTTP headers, which can
repeat and contain multiple headers with the same name.
>
> > Basically you are speculating. Do you really think we have two
> > identical commands?
>
> >> In C we can call procs by references but in TCL we cannot. Just wanted
> >> to list out the things like these.
>
> > Not sure what you mean here. You can store a procedure name in a
> > variable, and then place the variable where a command should go:
>
> > % set a puts
> > % $a hi
> > hi
> > % $a $a
> > puts
>
> I *think* he meant pass variables to a procedure by reference -- yes we have
> that, as in:
He talks about variables in other places, I assumed he meant procs
here. Tcl and C can handle both.
Oops, TclX's keyed list is much closer to a dict than to ns_set. Seems
like the feature set for [dict] makes it a better choice than the
keyed list.
I think that positively answers my side-question.
> The main point is that an array is not a "value", and neither is a
> variable. Neither a variable nor an array can be "returned" by a proc.
I think this subthread still lacks the statement, that
while it is principially and never possible to actually return
any type of *storage*(variables,arrays), it is easily possible
to return the *content(s)* of those as one value:
return $myLocalVariable
return [array get myLocalArray]
set retVar [myVariableContentReturningProc]
array set retArr [myArrayContentReturningProc]
(In case of reuse of "retArr", do an "array unset retArr", first.)
PS: how about an "array init <arrayName> <list>" that would first
do the clearing of the array, and then go on to "set"?
No big deal, but convenient. Is it worth a TIP?
It's ok. I was the one who started that debate some time ago.
I'm glad to read, that with respect to upvar/uplevel and pass-by-*
I've now got a follower of my views :-) (you)
The OP has been arguing that some other language (maybe C or C++)
actually allows you to return an array (or even just a pointer to an
array) that was defined inside a proc/function, and that Tcl was
uniquely unable to do this. I'm not sure how else to interpret the
statements. Here is the example proc:
# proc which returns an array
proc arrayTest {args} {
array set procArray {1 a 2 b 3 c 4 d}
return $procArray
}
Can anyone think of a language in which something like this would
work? The OP hasn't been very clear about exactly what is intended.
Part of the unclearness is that in C you can't even return a
representation of an array (something equivalent to [array get
myArray]), you could only return a pointer. But if the array was
defined inside the function, the pointer would be invalid once the
function returns...if the code even compiled.
In C++ you can really (syntactically) return e.g. a vector: The compiler
allocates storage in the outer stackframe, and upon return from the inner
function the returned vector is copied byte-for-byte into the outer one's.
vector<int> myFunc() { vector<int> myArr; return myArr; }
...
vector<int> outer=myFunc();
Apart from that, some array could have been *allocated* (e.g. with malloc(),
or the "new"-operator) from inside a procedure/function/method. That doesn't
mean that the array's storage would necessarily be part of the function's
stackframe. I wouldn't bet that people always distinguish between "define"
and "allocate" when talking of objects thusly brought to existence.
You appear to imply here that dicts don't maintain the order of
their keys. Fortunately that is not true, they do.
Schelte
They didn't do that from their beginning. Iow., this feature
was added later than the dicts themselves (iirc).
Anyway, "multiple same keys" is not among the features of dicts
(and most likely this won't change). To get it, one can use
lists of values associated to each key, but then, the insertion
order of keys is no longer maintained (only the order of values
within each key) - or just use lists directly like dicts, but
without the uniqueness and without dict's efficiency of element
access.
Correct. I realized that by maintaining key ordering in the correct
sense, values would behave like classical string values in a suitable
sense and there would be far fewer weirdnesses involved. (And I
figured out a fairly cheap way to implement it.)
> Anyway, "multiple same keys" is not among the features of dicts
> (and most likely this won't change).
Correct. The fundamental model of dictionaries is that of a value-
>value map, not a multimap.
Donal.
"The most important is that it maintains the order in which key-value
pairs are
added, and keys can appear more than once, with other keys between
identical keys."
That is one feature, of which I then gave an example:
"An example use-case for this is to handle HTTP headers, which can
repeat and contain multiple headers with the same name."
Actually an HTTP header could contain multiple headers with the same
case-insensitive name, which is why ns_set has case insensitive
versions of a number of its subcommands: iunique, ifind, iget, icput.
It also has an isnull subcommand which can actually distinguish NULL
from an empty string.
The con (since this is a pro/con thread) is that ns_sets, like arrays,
are structures, not values. You can pass them around by name, but not
by value. Another minor inconvenience: you have to use AOLserver or
nstclsh, although I have written a tcl only replacement for ns_set
based upon [lsearch] and a simple package API.
There are a good few (e.g. Haskell, Ocaml, ...) and they'd typically
implement it using references and/or copying under the hood. Many
languages don't expose how they manage memory on the program's behalf.
I suppose the key difference is whether the programming language
considers such things to be variables or values. Variables are (by
their very nature) mutable in some way and so have an identity that is
distinct from their current value (and are awkward to move around
unless there's some sort of reference remapping mechanism), whereas
values are (almost[*]) always theoretically constant - 42 is always 42
- and so can be copied around without language-theoretical problems.
Donal.
[* Old versions of Fortran got this wrong, which was a source of
horrible bugs. ]
Uh, no offense intended, but we're just both stating the obvious
truth ;-)
-Alex
I remember arguing about the need for [dict] to maintain a fixed order
and was happy to see this feature added.
> Anyway, "multiple same keys" is not among the features of dicts
> (and most likely this won't change). To get it, one can use
> lists of values associated to each key, but then, the insertion
> order of keys is no longer maintained (only the order of values
> within each key) - or just use lists directly like dicts, but
> without the uniqueness and without dict's efficiency of element
> access.
Personally I recommend that developers create their own specialized
data structures, maintained and accessed via an API to get the feature
set that they need. The base structures: lists, arrays, dicts don't
need to include every possible feature.
Schelte.
I've never found a compact way to describe this feature of an ns_set.
It does not map to any other internal data structure that I've seen.
Where is shows up is in external representations: HTTP headers, XML
child elements. And if the keys are thought of as column names in an
SQL query, an ns_set also matches the ordered and possibly duplicate
column names.
I guess the main difference is that in Tcl you can't specify what you
expect a procedure to return. You just know it will be a value. The
caller decides what the value means (if anything). The result is that
Tcl doesn't offer any syntactical support that would hint at any
behind the scenes manipulation. (One exception is the new {*} expand
syntax, but I'm not sure if you can apply that to a procedure call.)
Everyone can decide for themselves if this is a deficiency in Tcl, to
me it is just the way Tcl works. The interesting fact is that only
local variables: those created inside and local to a procedure (or
[namespace eval] block) are not available to other code. Every other
"thing" is discoverable and persists. Examples of such things are:
open file handles, global variables (any variable with a value in
the :: namespace), procedure definitions, namespaces and their
contents. Some people complain about this level of introspection. And
in addition to these persistent objects or "things", you can use
[upvar] to access local variables.
The best way to deal with complex structures which are created in one
place and used in another is to provide an interface which creates and
manages the structure.
Ah, yesofcourse! I was just still irritated how others could still
be *blind* about that truth. Or are they just part of a conspi
<transmission interrupted>
Two clarifications on that:
1.) yes, {*} also works with command substitution
2.) {*} before any subst does not "hint" any more than
usage as an argument of e.g. llength would.
Apart from that, the only language I know of, that really infers
usage-information into the called function is perl. (they talk
about singular and plural contexts, iirc)
But we can return keyedList.... even it is king of storage..!