AutoHotkey: Why are assignment, InsertAt, length, and MaxIndex, not working on an array generated by RegExMatch()?

Viewed 158

In AutoHotkey, RegExMatch() in mode 3 (match object) puts the matched strings in an array. I can get the matches using array[index], and I can get the number of matches using .count(). But I have the following problems:

  • When I try to change the value of an element of the array with :=, the value does not change.
  • When I try to insert an element using .InsertAt, nothing is inserted.
  • When I try to get the size of the array using .length() or .MaxIndex(), I get nothing.

This behavior is demonstrated by the following script:

; "TestScript.ahk"

; Use a regular expression to read data from a string, then test the behavior of the resulting array.

#NoEnv
#Warn

^+z::                           ; Hotkey for this script: Ctrl-shift-Z
sDataString := "A1B2C3"
nFoundPosn := RegExMatch(sDataString, "O)A(\d)B(\d)C(\d)", asData)
asData[2] := "4"
asData.InsertAt(3, "5")
MsgBox % "I expect the following to produce:`n"
        . "{1, 4, 5, 3}`n"
        . ">4<, >4<, >4<`n"
        . "`n"
        . "but instead I get:`n"
        . "{" . asData[1] . ", " . asData[2] . ", " . asData[3] . ", " . asData[4] . "}`n"
        . ">" . asData.count() . "<, >" . asData.length() . "<, >" . asData.MaxIndex() . "<"
return

which produces the following output:

enter image description here

Obviously, there's something I don't understand about the array that's being produced and how to work with it. The fact that assignment and insertion don't work suggests to me that the array variable is a pointer, but I don't see anything about that in the documentation linked above, so if it is a pointer, I don't know how to access the object it's pointing to. What am I doing wrong, or what do I misunderstand?

1 Answers

What an interesting thing you've come across! I thought that you surely had made an error, but I was wrong. It appears that the only usable properties are those listed in the help documentation for that mode. Annoyingly, it cannot be treated as a standard object; you can't even clone it to do useful work with it. As highly-esteemed AHK forum user jeeswg found (here), the only option is to loop through the match object and build an array from it, as demonstrated below.

^+z::
asDataNew := []
sDataString := "A1B2C3"
nFoundPosn := RegExMatch(sDataString, "O)A(\d)B(\d)C(\d)", asData)

Loop , % asData.count()
    asDataNew[A_Index] := asData[A_Index]

asDataNew[2] := "4"
asDataNew.InsertAt(3, "5")
MsgBox % "I expect the following to produce:`n"
        . "{1, 4, 5, 3}`n"
        . ">4<, >4<, >4<`n"
        . "`n"
        . "but instead I get:`n"
        . "{" . asData.1 . ", " . asData[2] . ", " . asData[3] . ", " . asData[4] . "}`n"
        . ">" . asData.count() . "<, >" . asData.length() . "<, >" . asData.MaxIndex() . "<`n"
        . "`n"
        . "With hard copy I get:`n"
        . "{" . asDataNew.1 . ", " . asDataNew[2] . ", " . asDataNew[3] . ", " . asDataNew[4] . "}`n"
        . ">" . asDataNew.count() . "<, >" . asDataNew.length() . "<, >" . asDataNew.MaxIndex() . "<"
return
Related