• =?UTF-8?Q?missing_feature_in_TCL_=e2=86=92_advanced_array?=

    From aotto1968@21:1/5 to All on Sat Mar 25 20:45:54 2023
    Hi,

    one of my TCL projects using an ARRAY to match a source-key to a target, example:

    array set map_M2S_local {
    ME_NB1_MK_BOL Byte

    ME_NI1_MK_BYT SByte
    ME_NI2_MK_SRT Int16
    ME_NI4_MK_INT Int32
    ME_NI8_MK_WID Int64
    ME_NF4_MK_FLT Single
    ME_NF8_MK_DBL Double

    ME_NI4_MK_DBG Int32
    ME_NI4_MQ_HDL Int32
    ME_NI4_MK_NUM Int32
    ME_NI4_MQ_SLAVE_ID Int32
    ME_NI4_MQ_SOCK_HDL Int32
    ME_NI4_MQ_LTR Int32
    ME_NI4_MQ_ROU Int32

    ME_PVO_MK_PTR IntPtr
    ME_PBI_MK_BIN IntPtr
    ME_PBN_MK_BINN IntPtr
    ME_PSN_MQ_TOKEN IntPtr
    ME_PSS_MK_STR IntPtr
    ME_PSN_MK_STRN IntPtr
    ME_PFS_MK_FST IntPtr
    ME_PLI_MK_LST IntPtr
    ME_PVO_IDNT IntPtr

    ME_REF_MkBinaryR IntPtr
    ...
    }

    as you see there are many items which hast *multiple* keys BUT a *unique* target.

    example ME_NI4_* is always mapping to *Int32*

    Problem: for a *new* key this array have *always* been updated even if the *new* follow
    the already known ME_NI4_* → Int32 syntax.

    NEW

    It would be nice to have an ARRAY which is able to use a key with pattern or regexp matching

    array set ?-glob? map_M2S_local {
    ME_NB1_MK_BOL Byte

    ME_NI1_MK_BYT SByte
    ME_NI2_MK_SRT Int16
    ME_NI4_MK_INT Int32
    ME_NI8_MK_WID Int64
    ME_NF4_MK_FLT Single
    ME_NF8_MK_DBL Double

    ME_NI4_* Int32

    ME_P* IntPtr

    ME_REF_MkBinaryR IntPtr
    ...
    }

    and '$map_M2S_local(ME_NI4_something)' would return *Int32*

    I know that it is possible to implement this as *switch* with a lot of "writing" in a 'proc' as wrapper


    mfg AO

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From et99@21:1/5 to All on Sat Mar 25 13:39:50 2023
    On 3/25/2023 12:45 PM, aotto1968 wrote:

    Hi,

     one of my TCL projects using an ARRAY to match a source-key to a target, example:

    array set map_M2S_local {
        ME_NB1_MK_BOL             Byte

        ME_NI1_MK_BYT             SByte
        ME_NI2_MK_SRT             Int16
        ME_NI4_MK_INT             Int32
        ME_NI8_MK_WID             Int64
        ME_NF4_MK_FLT             Single
        ME_NF8_MK_DBL             Double

        ME_NI4_MK_DBG             Int32
        ME_NI4_MQ_HDL             Int32
        ME_NI4_MK_NUM             Int32
        ME_NI4_MQ_SLAVE_ID        Int32
        ME_NI4_MQ_SOCK_HDL        Int32
        ME_NI4_MQ_LTR             Int32
        ME_NI4_MQ_ROU             Int32

        ME_PVO_MK_PTR             IntPtr
        ME_PBI_MK_BIN             IntPtr
        ME_PBN_MK_BINN            IntPtr
        ME_PSN_MQ_TOKEN           IntPtr
        ME_PSS_MK_STR             IntPtr
        ME_PSN_MK_STRN            IntPtr
        ME_PFS_MK_FST             IntPtr
        ME_PLI_MK_LST             IntPtr
        ME_PVO_IDNT               IntPtr

        ME_REF_MkBinaryR          IntPtr
    ...
    }

    as you see there are many items which hast *multiple* keys BUT a *unique* target.

    example ME_NI4_* is always mapping to *Int32*

    Problem: for a *new* key this array have *always* been updated even if the *new* follow
    the already known ME_NI4_* → Int32 syntax.

    NEW

    It would be nice to have an ARRAY which is able to use a key with pattern or regexp matching

    array set ?-glob? map_M2S_local {
        ME_NB1_MK_BOL             Byte

        ME_NI1_MK_BYT             SByte
        ME_NI2_MK_SRT             Int16
        ME_NI4_MK_INT             Int32
        ME_NI8_MK_WID             Int64
        ME_NF4_MK_FLT             Single
        ME_NF8_MK_DBL             Double

        ME_NI4_*                  Int32

        ME_P*                     IntPtr

        ME_REF_MkBinaryR          IntPtr
    ...
    }

    and '$map_M2S_local(ME_NI4_something)' would return *Int32*

    I know that it is possible to implement this as *switch* with a lot of "writing" in a 'proc' as wrapper


    mfg AO


    I think you can accomplish this with a foreach loop and [array names]

    # (untested code)
    # lookup is the key you are interested in
    set result "" ;# if not found
    foreach key [array names map_M2S_local] {
    if { [string match $key $lookup] } {
    set result $map_M2S_local($key)
    break
    }
    }

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Gerald Lester@21:1/5 to All on Sat Mar 25 21:00:32 2023
    On 3/25/23 14:45, aotto1968 wrote:

    Hi,

     one of my TCL projects using an ARRAY to match a source-key to a
    target, example:

    array set map_M2S_local {
        ME_NB1_MK_BOL             Byte

        ME_NI1_MK_BYT             SByte
        ME_NI2_MK_SRT             Int16
        ME_NI4_MK_INT             Int32
        ME_NI8_MK_WID             Int64
        ME_NF4_MK_FLT             Single
        ME_NF8_MK_DBL             Double

        ME_NI4_MK_DBG             Int32
        ME_NI4_MQ_HDL             Int32
        ME_NI4_MK_NUM             Int32
        ME_NI4_MQ_SLAVE_ID        Int32
        ME_NI4_MQ_SOCK_HDL        Int32
        ME_NI4_MQ_LTR             Int32
        ME_NI4_MQ_ROU             Int32

        ME_PVO_MK_PTR             IntPtr
        ME_PBI_MK_BIN             IntPtr
        ME_PBN_MK_BINN            IntPtr
        ME_PSN_MQ_TOKEN           IntPtr
        ME_PSS_MK_STR             IntPtr
        ME_PSN_MK_STRN            IntPtr
        ME_PFS_MK_FST             IntPtr
        ME_PLI_MK_LST             IntPtr
        ME_PVO_IDNT               IntPtr

        ME_REF_MkBinaryR          IntPtr
    ...
    }

    as you see there are many items which hast *multiple* keys BUT a
    *unique* target.

    example ME_NI4_* is always mapping to *Int32*

    Problem: for a *new* key this array have *always* been updated even if
    the *new* follow
    the already known ME_NI4_* → Int32 syntax.

    NEW

    It would be nice to have an ARRAY which is able to use a key with
    pattern or regexp matching

    array set ?-glob? map_M2S_local {
        ME_NB1_MK_BOL             Byte

        ME_NI1_MK_BYT             SByte
        ME_NI2_MK_SRT             Int16
        ME_NI4_MK_INT             Int32
        ME_NI8_MK_WID             Int64
        ME_NF4_MK_FLT             Single
        ME_NF8_MK_DBL             Double

        ME_NI4_*                  Int32

        ME_P*                     IntPtr

        ME_REF_MkBinaryR          IntPtr
    ...
    }

    and '$map_M2S_local(ME_NI4_something)' would return *Int32*

    I know that it is possible to implement this as *switch* with a lot of "writing" in a 'proc' as wrapper


    Read the man/doc page for the array command, pay particular attention to
    the name subcommand.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From aotto1968@21:1/5 to Gerald Lester on Sun Mar 26 08:49:21 2023
    On 26.03.23 04:00, Gerald Lester wrote:
    On 3/25/23 14:45, aotto1968 wrote:

    Hi,




    Read the man/doc page for the array command, pay particular attention to the name subcommand.



    It is clear that the pattern is the KEY and not the LOOKUP.

    array set test {
    key??next* myValueToSearchFor
    }

    set test(key12nextSomething) -> myValueToSearchFor

    I already know that it is possible to transform an array into a list (array names ..., array get ...) and process
    each entry (one by one) BUT you loose all speed advantages of an array. just assume that the array has 1 million entries
    and you will understand that loop over oneBYone is not the best choice.

    I know it is NOT trivial to use a PATTERN as key in an array

    -ao

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From aotto1968@21:1/5 to Christian Gollwitzer on Sun Mar 26 10:36:07 2023
    On 26.03.23 10:17, Christian Gollwitzer wrote:
    Am 26.03.23 um 08:49 schrieb aotto1968:
    On 26.03.23 04:00, Gerald Lester wrote:

    It is clear that the pattern is the KEY and not the LOOKUP.

    array set test {
       key??next*    myValueToSearchFor
    }

    set test(key12nextSomething) -> myValueToSearchFor

    I already know that it is possible to transform an array into a list (array names ..., array get ...) and process
    each entry (one by one) BUT you loose all speed advantages of an array. just assume that the array has 1 million entries
    and you will understand that loop over oneBYone is not the best choice. >
    I know it is NOT trivial to use a PATTERN as key in an array

    And how would you think it is possible to implement such a feature, if not by looping over the entries one by one? It would help
    of course when the lookup goes to the C level instead of a Tcl level loop, but you would still spend most of the time matching
    the patterns one by one.

    There is one (half-theoretical) other way to get faster lookups, that is by transforming the patterns into a giant state machine
    where the end points correspond to the patterns. Basically this is what "lex" does. As you can imagine, transforming 1 million
    patterns into a single state machine is going to take a very long time and consume lots of memory. It can be done once for a
    static array and then applied multiple times, but it is not suitable for a dynamic construct like an array.

        Christian



    read the key from LEFT to RIGHT

    start: myValueToSearchFor
    loop until ONE or NOTHING {
    -> step one: get all keys match m*
    -> -> from solution of step one: get all keys match my* ... etc
    }

    The GOAL is to intelligent select the KEYS to just a SINGLE one using a B-TREE like key.

    -ao

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Christian Gollwitzer@21:1/5 to All on Sun Mar 26 10:17:15 2023
    Am 26.03.23 um 08:49 schrieb aotto1968:
    On 26.03.23 04:00, Gerald Lester wrote:

    It is clear that the pattern is the KEY and not the LOOKUP.

    array set test {
      key??next*    myValueToSearchFor
    }

    set test(key12nextSomething) -> myValueToSearchFor

    I already know that it is possible to transform an array into a list
    (array names ..., array get ...) and process
    each entry (one by one) BUT you loose all speed advantages of an array.
    just assume that the array has 1 million entries
    and you will understand that loop over oneBYone is not the best choice. >
    I know it is NOT trivial to use a PATTERN as key in an array

    And how would you think it is possible to implement such a feature, if
    not by looping over the entries one by one? It would help of course when
    the lookup goes to the C level instead of a Tcl level loop, but you
    would still spend most of the time matching the patterns one by one.

    There is one (half-theoretical) other way to get faster lookups, that is
    by transforming the patterns into a giant state machine where the end
    points correspond to the patterns. Basically this is what "lex" does. As
    you can imagine, transforming 1 million patterns into a single state
    machine is going to take a very long time and consume lots of memory. It
    can be done once for a static array and then applied multiple times, but
    it is not suitable for a dynamic construct like an array.

    Christian

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Rich@21:1/5 to [email protected] on Sun Mar 26 15:31:53 2023
    aotto1968 <[email protected]> wrote:
    On 26.03.23 04:00, Gerald Lester wrote:
    Read the man/doc page for the array command, pay particular
    attention to the name subcommand.

    It is clear that the pattern is the KEY and not the LOOKUP.

    array set test {
    key??next* myValueToSearchFor
    }

    set test(key12nextSomething) -> myValueToSearchFor

    I already know that it is possible to transform an array into a list
    (array names ..., array get ...) and process each entry (one by one)
    BUT you loose all speed advantages of an array. just assume that the
    array has 1 million entries and you will understand that loop over
    oneBYone is not the best choice.

    I know it is NOT trivial to use a PATTERN as key in an array

    With 'pre-processing' of the array contents, you can somewhat
    simulate a "pattern" as a key.

    Preprocess your groups of strings belonging to the same output to find
    the shortest common prefix of each set (note, be careful of overlapping prefixes for different sets). Then for each 'shortest common prefix"
    append your own 'custom' pattern suffix, and store that as the key:

    array set map {PLE_1% something
    XYX_P23_% something}

    Then, for a string PLE_145, you look for:
    PLE_145
    PLE_145%
    PLE_14%
    PLE_1%

    until you find a match.

    You will have, at most, a number of lookups equal to the character
    length of the removed suffix string. Which will be shorter than the
    fully duplicative array. But the compacted array will be much smaller, reducing memory usage. You will have to decide which you want to trade
    off, speed of lookup or consumption of memory.

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