representation

Command for inspecting the representation of a Tcl_Obj for debugging purposes. This command is not officially supported and the format of its output is deliberately chosen to be suitable for human use and not mechanical use. Do not base the behavior of any command on the results of this one; it does not conform to Tcl's value semantics!

tcl::unsupported::representation value

Examples

DKF: Here are some examples of output. Note that the refcounts can be sometimes confusing; be aware that references to literals can be retained in the history.

% tcl::unsupported::representation 1
value is a int with a refcount of 8, object pointer at 0x32eb0, internal representation 0x1:0x0, string representation "1".
% tcl::unsupported::representation 123
value is a pure string with a refcount of 3, object pointer at 0x34230, string representation "123".
% tcl::unsupported::representation abc
value is a pure string with a refcount of 3, object pointer at 0x32f40, string representation "abc".
% set s abcdef
abcdef
% string length $s
6
% tcl::unsupported::representation $s
value is a string with a refcount of 4, object pointer at 0x34338, internal representation 0x93c50:0x0, string representation "abcdef".
% tcl::unsupported::representation [list 1 2 3]
value is a list with a refcount of 1, object pointer at 0x34500, internal representation 0x8a050:0x0, no string representation.
% tcl::unsupported::representation [dict create 1 2 3 4]
value is a dict with a refcount of 1, object pointer at 0x97428, internal representation 0x92210:0x33960, no string representation.

AMG: I'm curious about why "1" has a large refcount. Does Tcl maintain a cache of common Tcl_Objs?

DGP Tcl keeps tables of literal values so they may be shared.

AMG: Also, what about this?

% # Test with "1"
% set data 1
% tcl::unsupported::representation $data
value is a int with a refcount of 20, object pointer at 00E138D0, internal representation 00000001:00000000, string representation "1".
% llength $data
% tcl::unsupported::representation $data
value is a int with a refcount of 19, object pointer at 00E138D0, internal representation 00000001:00000000, string representation "1".
% # Test with "12345" rigged to have an "int" intrep
% set data [expr {12345}]
% tcl::unsupported::representation $data
value is a int with a refcount of 3, object pointer at 00DB61C8, internal representation 00003039:00000000, string representation "12345".
% llength $data
% tcl::unsupported::representation $data
value is a list with a refcount of 2, object pointer at 00DB61C8, internal representation 00DD8988:00000000, string representation "12345".
% info patchlevel
8.6b1.2

[llength] causes 12345 to shimmer from int to list, but it does not cause 1 to shimmer from int to list. Why?

DGP That is probably an effect of shared literals, but honestly I cannot reproduce it.

MHN It actually shimmers - also in the case of [list 1]. However, it had already shimmered back to the return value of [llength] that is implicitly stored by the interactive session. Compare these:

% set data 1
1
% ::tcl::unsupported::representation $data
value is a int with a refcount of 26, object pointer at 0x82f9f0, internal representation 0x1:0x1, string representation "1"
% llength $data; ::tcl::unsupported::representation $data
value is a list with a refcount of 26, object pointer at 0x82f9f0, internal representation 0x8b0f00:(nil), string representation "1"
% llength $data
1
% ::tcl::unsupported::representation $data
value is a int with a refcount of 26, object pointer at 0x82f9f0, internal representation 0x1:(nil), string representation "1"

APN Could someone explain the ref counts from the following sequence ? Why does the refcount for literal "a" go up on the second assignment to x? And after unsetting of x, should the refcount not be back to the original 3 ? Does it possibly have to do with tkcon keeping a command history?

(tcl) 49 % ::tcl::unsupported::representation a
value is a pure string with a refcount of 3, object pointer at 00F2A030, string representation "a".
(tcl) 49 % set x a
a
(tcl) 50 % ::tcl::unsupported::representation a
value is a pure string with a refcount of 6, object pointer at 00F29A00, string representation "a".
(tcl) 51 % set x a
a
(tcl) 52 % ::tcl::unsupported::representation a
value is a pure string with a refcount of 8, object pointer at 00F29A00, string representation "a".
(tcl) 53 % unset x
(tcl) 54 % ::tcl::unsupported::representation a
value is a pure string with a refcount of 7, object pointer at 00F29A00, string representation "a".

MS Two "problems": history, and misunderstanding of which objs are shared. Maybe this will help clarify.

% proc history args {}
% ::tcl::unsupported::representation a
value is a pure string with a refcount of 3, object pointer at 0x878b178, string representation "a".
% set x0 a
a
% ::tcl::unsupported::representation a
value is a pure string with a refcount of 3, object pointer at 0x878b208, string representation "a".
% ::tcl::unsupported::representation $x0
value is a pure string with a refcount of 2, object pointer at 0x878b178, string representation "a".
% set x $x0
a
% ::tcl::unsupported::representation a
value is a pure string with a refcount of 3, object pointer at 0x878b898, string representation "a".
% ::tcl::unsupported::representation $x0
value is a pure string with a refcount of 3, object pointer at 0x878b178, string representation "a".

JMN 2023-06 - tested in Tcl 8.6 & 8.7a5 on windows This occurs both in a standard tclsh shell or when sourced from a file.

(the trailing colon & list in the command is only needed to replicate the issue when in tclsh so that an immediate string rep isn't generated)

I came across this in a repl framework I use where I was trying to understand when shimmering was occurring.

This seems like a bug to me.. can anyone shed some light on why the variable's representation is affected by the script changing or going out of scope?

I guess it's not actually shimmering in this case(?), but I wonder why a string rep is generated at that point?

#string rep generated for variable when script is changed or unset

set script {set j [list a] ; list}
append script "\n"
uplevel #0 $script
puts stdout [tcl::unsupported::representation $j]
puts stdout [tcl::unsupported::representation $j] 
puts stdout [tcl::unsupported::representation $j] 
set script ""
puts stdout [tcl::unsupported::representation $j] 
puts stdout [tcl::unsupported::representation $j] 

#value is a list with a refcount of 3, object pointer at 0x833d30, internal representation 0x878810:0x0, no string representation
#value is a list with a refcount of 3, object pointer at 0x833d30, internal representation 0x878810:0x0, no string representation
#value is a list with a refcount of 3, object pointer at 0x833d30, internal representation 0x878810:0x0, no string representation
#value is a list with a refcount of 2, object pointer at 0x833d30, internal representation 0x878810:0x0, string representation "a"
#value is a list with a refcount of 2, object pointer at 0x833d30, internal representation 0x878810:0x0, string representation "a"