Oleg Nemanov <
[email protected]> wrote:
???????, 22 ?????? 2022 ?. ? 17:55:02 UTC+3, [email protected]:
The things is even more complecated if there is nested list with dict
like this: set ctx [dict create srcs [list [dict create SOME_DATA]
[dict create SOME_DATA]]]
And we want to process each list item in a loop. In this case, Rich
and Schelte method isn't work and, it seems, the more simple way is:
set src [lindex [dict get $ctx srcs] 0]
src_proc1 src
dict set ctx srcs [lreplace [dict get $ctx srcs] 0 0 $src]
And i thinkg this is not very effectively :-).
Tcl's [time] command can be a great way to see if something seems not efficient.
In this case, for the set src and src_proc1 src lines, only an
additional pointer, to the list element, should be created. Should
src_proc1 modify (via upvar) the contents of src, then a copy of what
is in 'src' will be made.
The last line should then replace just the one list element (not copy
and GC the entire dict). So while some copying and GC will happen, it
should be limited to just the parts that got changed, not the entire
'ctx' dict.
The tcl::unsupported::representation can be very illuminating for
discovering how the runtime deals with manipulating data under the
hood.
Note:
$ rlwrap tclsh
% set ctx [dict create srcs [list [dict create a b] [dict create c d]] dst [dict create e f]]
srcs {{a b} {c d}} dst {e f}
% tcl::unsupported::representation $ctx
value is a dict with a refcount of 2, object pointer at 0x115b780,
internal representation 0x11967e0:(nil), string representation "srcs
{{a b} {..."
% tcl::unsupported::representation [lindex [dict get $ctx srcs] 0]
value is a dict with a refcount of 4, object pointer at 0x1156a70,
internal representation 0x113df80:(nil), string representation "a b"
% set src [lindex [dict get $ctx srcs] 0]
a b
% tcl::unsupported::representation $src
value is a dict with a refcount of 5, object pointer at 0x1156a70,
internal representation 0x113df80:(nil), string representation "a b"
%
src is now pointing to the same object that five other references are
also pointing towards.
Now, modify via lreplace:
% set new [dict create y z]
y z
% tcl::unsupported::representation $new
value is a dict with a refcount of 4, object pointer at 0x115b000, internal repr esentation 0x1196de0:(nil), string representation "y z"
% dict set ctx srcs [lreplace [dict get $ctx srcs] 0 0 $new]
srcs {{y z} {c d}} dst {e f}
% tcl::unsupported::representation $ctx
value is a dict with a refcount of 2, object pointer at 0x115b780, internal repr esentation 0x11967e0:(nil), string representation "srcs {{y z} {..."
% tcl::unsupported::representation $new
value is a dict with a refcount of 5, object pointer at 0x115b000,
internal representation 0x1196de0:(nil), string representation "y z"
% tcl::unsupported::representation [lindex [dict get $ctx srcs] 0]
value is a dict with a refcount of 5, object pointer at 0x115b000,
internal representation 0x1196de0:(nil), string representation "y z"
%
ctx is the same object pointer as before (0x115b780).
the new dict began life as poinnter at 0x115b000, and remained the same
after 'splicing'
The item spliced in is the same obj pointer as new when it began life (0x115b000). So the thing that was in 'new' just got 'spliced into'
the list by having the first list cell point at the same thing "new"
was pointing at.
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)