• Re: a typeof command for debugging?

    From Christian Gollwitzer@21:1/5 to All on Sat Jun 21 15:51:31 2025
    Am 21.06.25 um 13:16 schrieb Mark Summerfield:
    I'd like a `typeof` command for debugging.
    I've had a go but only bits of it work.

    ```
    proc typeof x {
    if {![catch {[info object class $x] name}]} {
    return $name
    } else {
    if {[string is boolean -strict $x]} {
    return bool
    [...]

    I don't think you can do much better than that, since Tcl is a weakly
    typed language (usually referred to as the "EIAS" principle). The only
    other thing you can do is peek into the internal cached type, which
    shows you the last type that was used on that object (besides string):

    (chris) 50 % set a [expr {23*5}]
    115
    (chris) 51 % tcl::unsupported::representation $a
    value is a int with a refcount of 4, object pointer at 0x55d6b8f8b320,
    internal representation 0x73:(nil), string representation "115"


    Christian

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Christian Gollwitzer@21:1/5 to All on Sat Jun 21 15:58:50 2025
    shows you the last type that was used on that object (besides string):

    (chris) 50 % set a [expr {23*5}]
    115
    (chris) 51 % tcl::unsupported::representation $a
    value is a int with a refcount of 4, object pointer at 0x55d6b8f8b320, internal representation 0x73:(nil), string representation "115"


             Christian

    PS: Since you are new to Tcl, please have a look at the following:

    (chris) 52 % set a {1 2 3 4}
    1 2 3 4
    (chris) 53 % tcl::unsupported::representation $a
    value is a pure string with a refcount of 5, object pointer at
    0x55d6b8f8ac90, string representation "1 2 3 4"
    (chris) 54 % lindex $a 2
    3
    (chris) 55 % tcl::unsupported::representation $a
    value is a list with a refcount of 4, object pointer at 0x55d6b8f8ac90, internal representation 0x55d6b8c06cf0:(nil), string representation "1 2
    3 4"
    (chris) 56 %

    Also, the {} do not make the list, they are a quoting mechanism. You
    will get an identical result if you use "":
    (chris) 61 % tcl::unsupported::representation $b
    value is a pure string with a refcount of 5, object pointer at
    0x55d6b8f85860, string representation "1 2 3 4 5 6"
    (chris) 62 % lindex $b 2
    3
    (chris) 63 % tcl::unsupported::representation $b
    value is a list with a refcount of 4, object pointer at 0x55d6b8f85860, internal representation 0x55d6b8f14b40:(nil), string representation "1 2
    3 4 5 6"
    (chris) 64 %


    And, there is "constant sharing". After you ran the previous examples,
    try with another surprise:

    (chris) 64 % set c "1 2 3 4"
    1 2 3 4
    (chris) 65 % tcl::unsupported::representation $c
    value is a list with a refcount of 9, object pointer at 0x55d6b8f8ac90, internal representation 0x55d6b8c06cf0:(nil), string representation "1 2
    3 4"
    (chris) 66 %


    Christian

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Ralf Fassel@21:1/5 to All on Sun Jun 22 13:08:53 2025
    * Mark Summerfield <[email protected]>
    | I've incorporated that but I still have an actual bug. The catch always
    | returns false (failed) so objects always get returned as list_or_str. Yet,
    | if I use info object class directly it correctly returns the class name.
    | So clearly I'm doing something wrong in the catch.

    | proc typeof x {
    | # puts "\n[tcl::unsupported::representation $x]"
    | if {![catch {[info object class $x] name}]} {
    | return $name

    This looks suspicious: you are calling
    [info object class $x]
    and whatever that returns, you use as a command to call with argument 'name', and discard the result. The variable $name should not be set when you hit
    the return.

    Did you rather mean

    catch {info object class $x} name

    ?
    R'

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Christian Gollwitzer@21:1/5 to All on Sun Jun 22 21:22:37 2025
    Am 22.06.25 um 08:50 schrieb Mark Summerfield:
    I found that tcl::unsupported::representation says "pure string" for
    strings and numbers and bools and lists; it only seems to distinguish
    dicts (Tcl 9.0.1).


    No, it doesn't. You seem to have the misconception that {1 2 3} is a
    list of three values. It is actually a string, but can be treated as a list.

    In Tcl, neither the values nor the variables do have a type in the sense
    of Python. However, the runtime uses an internal cached typed
    representation, which you can query.

    See this transcript:

    (chris) 49 % set a [list 1 2 3]
    1 2 3
    (chris) 50 % tcl::unsupported::representation $a
    value is a list with a refcount of 4, object pointer at 0x5576f6d87430, internal representation 0x5576f6d57ab0:(nil), string representation "1 2 3" (chris) 51 % set b [dict a 1 b 2]
    b 2
    (chris) 52 % tcl::unsupported::representation $b
    value is a dict with a refcount of 4, object pointer at 0x5576f6d86e30, internal representation 0x5576f6da2d60:(nil), string representation "b 2" (chris) 53 % set c [expr {1.0/3}]
    0.3333333333333333
    (chris) 54 % tcl::unsupported::representation $c
    value is a double with a refcount of 4, object pointer at
    0x5576f6d86cb0, internal representation 0x3fd5555555555555:(nil), string representation "0.33333333333..."
    (chris) 55 % set d yes; if {$d} { puts yes }
    yes
    (chris) 56 % tcl::unsupported::representation $d
    value is a booleanString with a refcount of 4, object pointer at 0x5576f6d880f0, internal representation 0x1:0x5576f6d815e0, string representation "yes"
    (chris) 57 %

    Read up on EIAS if you struggle to understand this. It is alos the
    reason why this is in the "unsupported" namespace, because this command
    breaks EIAS.

    Christian

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Schelte@21:1/5 to Christian Gollwitzer on Sun Jun 22 23:50:48 2025
    On 22/06/2025 21:22, Christian Gollwitzer wrote:
    (chris) 51 % set b [dict a 1 b 2]
    b 2
    (chris) 52 % tcl::unsupported::representation $b
    value is a dict with a refcount of 4, object pointer at 0x5576f6d86e30, internal representation 0x5576f6da2d60:(nil), string representation "b 2"

    Funny. While clearing up one point, you are confusing readers again on
    another point: It may not immediately be clear how b can end up being
    the dictionary "b 2". The explanation is that the command [dict a 1 b 2]
    is interpreted as [dict append 1 b 2], because there is only one dict subcommand that starts with "a". Additionally "dict append" will create
    the dict if it doesn't yet exist. So this creates a dict in a variable
    called "1", with key "b" that has a value of "2". That dict is then also
    copied to the variable "b".

    I suppose you actually intended to use [dict create a 1 b 2].


    Schelte.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Christian Gollwitzer@21:1/5 to All on Mon Jun 23 08:06:48 2025
    Am 22.06.25 um 23:50 schrieb Schelte:
    On 22/06/2025 21:22, Christian Gollwitzer wrote:
    (chris) 51 % set b [dict a 1 b 2]
    b 2
    (chris) 52 % tcl::unsupported::representation $b
    value is a dict with a refcount of 4, object pointer at
    0x5576f6d86e30, internal representation 0x5576f6da2d60:(nil), string
    representation "b 2"

    Funny. While clearing up one point, you are confusing readers again on another point: It may not immediately be clear how b can end up being
    the dictionary "b 2". The explanation is that the command [dict a 1 b 2]
    is interpreted as [dict append 1 b 2], because there is only one dict subcommand that starts with "a". Additionally "dict append" will create
    the dict if it doesn't yet exist. So this creates a dict in a variable
    called "1", with key "b" that has a value of "2". That dict is then also copied to the variable "b".

    I suppose you actually intended to use [dict create a 1 b 2].


    Good catch! I missed that one.

    Christian

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)