• Array get element with default (no error if not exist)

    From RodionGork@21:1/5 to All on Fri Aug 16 07:10:30 2024
    Hi Friends!

    Still making my first feeble steps in TCL so please excuse me if this is
    naive or was asked multiple times.

    Attempt to fetch by non-existing key in "associative array" results in
    error, e.g.

    set a(1) 5
    puts $a(2) ;# yields error

    the workaround seems to be [info exists ::a(2)] which feels a bit remote
    from other "array" commands.

    Is there some motivation why some command for get-with-default is not implemented, e.g.

    puts [array peek $a 2 "default value"]

    Popular use-case for this would be creating map where elements are
    updated (like counter of words etc) - though I found this is cleverly
    covered by "incr" and "append" commands properly behaving
    when element to be incremented or appended does not exist yet.

    But I suspect there are other situations when such a command may be
    handy.

    Also why [array exists ...] command does not exist (while [dict exists
    ..] does)? Perhaps there is something about no good syntax for it due
    to how arrays are implemented?

    --
    to email me substitute github with gmail please

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Ralf Fassel@21:1/5 to All on Fri Aug 16 11:11:29 2024
    * RodionGork <rodiongork@github.com>
    | Is there some motivation why some command for get-with-default is not
    | implemented, e.g.

    | puts [array peek $a 2 "default value"]

    Most probably because up to now nobody required it so badly that s/he implemented it, since the [info exists] approach is not too bad IMHO.

    proc array_peek {arr key default} {
    upvar $arr a
    if {![array exists a] || ![info exists a($key)]} {
    return $default
    }
    return $a($key)
    }
    array set a {1 one}
    array_peek a 1 "default value"
    => one
    array_peek a 2 "default value"
    => default value

    Or you could set up a read-trace on the array to provide non-existing values:

    array set a {}
    trace add variable a read set_array_default
    proc set_array_default {name1 name2 op} {
    upvar a $name1
    # puts stderr "set_array {$name1} {$name2} {$op}"
    if {![info exists a($name2)]} {
    set a($name2) "default"
    }
    }
    set a(2)
    => default

    Though that would alter the array and make the key exists which might
    not be what you want.

    HTH
    R'

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Emiliano@21:1/5 to RodionGork on Fri Aug 16 11:16:04 2024
    On Fri, 16 Aug 2024 07:10:30 +0000
    RodionGork <rodiongork@github.com> wrote:

    Hi Friends!

    Still making my first feeble steps in TCL so please excuse me if this is naive or was asked multiple times.

    Attempt to fetch by non-existing key in "associative array" results in
    error, e.g.

    set a(1) 5
    puts $a(2) ;# yields error

    the workaround seems to be [info exists ::a(2)] which feels a bit remote
    from other "array" commands.

    Is there some motivation why some command for get-with-default is not implemented, e.g.

    puts [array peek $a 2 "default value"]

    Popular use-case for this would be creating map where elements are
    updated (like counter of words etc) - though I found this is cleverly
    covered by "incr" and "append" commands properly behaving
    when element to be incremented or appended does not exist yet.

    But I suspect there are other situations when such a command may be
    handy.

    Already there in 8.7/9.0

    % array default set foo NOSUCHVALUE
    % set foo(1)
    NOSUCHVALUE
    % info exists foo(1)
    0

    8.7/9.0 also adds [dict getwithdefault] (aka [dict getdef]) for dict
    values.


    Also why [array exists ...] command does not exist (while [dict exists
    ..] does)? Perhaps there is something about no good syntax for it due
    to how arrays are implemented?

    The [array exists] command is there since ... forever

    % array exists foo
    1
    % array exists nosucharray
    0

    Well, at least since 8.4 . See https://www.tcl-lang.org/man/tcl8.4/TclCmd/array.htm

    --
    Emiliano

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Ralf Fassel@21:1/5 to All on Fri Aug 16 16:54:01 2024
    * Emiliano <emil.g@example.invalid>
    | On Fri, 16 Aug 2024 07:10:30 +0000
    | RodionGork <rodiongork@github.com> wrote:
    | > Also why [array exists ...] command does not exist (while [dict exists
    | > ..] does)? Perhaps there is something about no good syntax for it due
    | > to how arrays are implemented?

    | The [array exists] command is there since ... forever

    | % array exists foo
    | 1
    | % array exists nosucharray
    | 0

    Obviouosly in this context the OP meant "array exists" with respect to a specific key, i.e.

    array exists arrayname key
    => return true if arrayname is an array and the key exists in that array.

    R'

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From RodionGork@21:1/5 to All on Sat Aug 17 06:13:34 2024
    Friends, thanks for all the replies!

    And for suggestions providing insight on techniques of which I wasn't
    aware of, especially that "read trace".

    Yep, I definitely meant something like [array element_exists ...] rather
    than [array exists ...] which seems a bit inconsistent with [dict exists
    ..] but of course it is not a big issue.

    My curiosity was mostly satisfied, thanks! The only small thing I still
    haven't grasped well is why it happened that checking for element in
    array found its way into [info exists...] rather than some [array ...] subcommands. I suspected there was something hindering implementing it
    there, but probably it just, well, so happened historically :)

    --
    to email me substitute github with gmail please

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