Luc <
[email protected]d> wrote:
On Sun, 7 Jan 2024 06:57:43 -0000 (UTC), Rich wrote:
Is there a reason why you don't use dict create above?
Yes, just code cleanliness. I declare all global variables at the
beginning of the whole thing including four or five dicts that will
be populated later on.
But, if you are going for cleanliness, then using dict create is:
1) cleaner
2) more meaningful. The code declares exactly what it is doing. This
can be esp. good if you sit this aside for a while and return in six or
nine months. Seeing
set x [dict create key1 value1 \
key2 value2]
clearly says a [dict] is being created.
While
set x "key1 value1
key2 value2"
Is just a string, that /could/ be a list, or /could/ be a dict, or
/could/ eventually be turned into an array. Less overtly meaningful
without first investigating how "x" is used later.
3) safer.
Doing "set x [dict create key1 $somevariable]" will always succeed.
Doing "set x " key1 $somevariable" will /appear/ to also always
succeed, until that fateful day, months or years in the future, where
the string inside "$somevariable" happens to contain a character that
is meaningful to Tcl's implicit list/dict conversion parser, at which
point, the use of x as a dict will blow up with a very non-meaningful
error message. And this will be made worse by the fact that you'll be
left wondering: "it has been working for X time so far, what
happened?".
Watch:
$ rlwrap tclsh
% set somevar "a string"
a string
% set dict "key1 $somevar"
key1 a string
% dict get $dict key1
missing value to go with key
%
vs:
% set dict [dict create key1 $somevar]
key1 {a string}
% dict get $dict key1
a string
%
Unless you have very good reason to be assembling dicts or lists by concatenating plain strings, and are "very careful" when doing so, it
is best to *always* use the proper constructor procs:
[dict create ...] for dicts
[list ...] for lists
Both take care of making sure the result is proper as a dict/list and
for handing those special edge cases that are easily forgotten when
doing "$a $b $c $d $e" to assemble what will be used as a dict/list.
Or if you want the 'alignment layout':
I like alignment layout for debug printing, but I've found out it all
goes away as soon as the dict is updated.
Because as soon as you update the dict, your pretty string is parsed,
converted into a proper dict data structure, and then the next time you
'puts' it, you get back the default string representation of a dict
data structure, not the original string you began with.
I had to make a proc that "beautifies" the printing of the main dict.
https://wiki.tcl-lang.org/page/pdict%3A+Pretty+print+a+dict?R=0&O=pdict
It wasn't very easy to write and it's only good for that one dict and
its own unique structure. Doing the same with namespaces would be a
lot easier and it would work with all dict-replacing namespaces.
Plus, if you wanted to eventually save your state across exits and
reload where you were, the dict method gives you that single data
structure to save/restore. The plural namespaces means you need extra
work to extract and serialize to disk the namespaces and later restore
them all upon reload.
That is a good point, but
1. I feel that coding with dicts is by itself a lot of "extra work"
because their structure is trickier.
Not if you use the proper "create" procs (i.e., [dict create]). Then
there's nothing 'tricky' at all.
The command lines are longer and look a bit too fragmented to me,
This is true, but you realize this is Tcl, you can 'adjust' that fact
if you like:
% dict get $dict key1
a string
% interp alias {} dget {} dict get
dget
% dget $dict key1
a string
%
and inserting lists and sublists is a pretty good minefield so it's
very easy to make a mistake
If you use the creation procs, and the setting procs, instead of trying
to create strings that are proper as dicts, then it is almost
impossible to "make a mistake", and usually those mistakes that are
made are immediate syntax errors just after making a code change, not
hidden mines waiting to blow up a week from now.
and I have to be printing and checking them all the time.
Use the proper creation and update procs and you won't have to be
"printing and checking them all the time".
I feel very tempted to rewrite everything with namespaces now because
it will be a lot easier to manage.
That's up to you, and you can certianly do so. But you'll likely
encounter some other issue with that path that brings back the
complexity issues you think you are avoiding, just wearing a different
hat this time.
Bzzt, please try again.
That is because you tried to do string interpolation to store the
array. Don't do that. This works just fine:
$ rlwrap tclsh
% array set aa {item1 a}
% set dd [dict create]
% dict set dd array1 [array get aa]
array1 {item1 a}
% dict get $dd array1
item1 a
Granted, what is stored is the string representation of the array, but
once stored, you can then 'dict get' against it:
% dict get $dd array1 item1
a
Thank you for the lesson, but I find that a little too convoluted. It
seems to me that you in fact did not store an array in the dict but
rather converted it into a list so it would be admitted by the dict's doorman/bouncer.
Yes, I said so in the "Granted, what is stored is the string
representation of the array," statement. You can't physically store
"an array" in a dict, for the same reason why you can't actually pass
an array to a proc as a parameter. A design decision with how array's
were handled way back in Tcl's very early days resulted in array's
being 'oddball' that way.
But you'll note I stored the array using the proper dict update proc,
not by trying to do 'set dd "$dd array1 [array get aa]"' via string interpolation. If you have lots of those throughout your code, you
have a minefield just waiting to be stepped on some day.
In any case, if you are not using traces, the subtle distinction
hardly matters.
Not yet.
The question of course is, do you plan to use traces?
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)