if both items are literal strings e.g. "1" or "a", compare alphabetically, [EDIT: I'd remove this]
else if both items are variables with type 'String', compare alphabetically, [I'd remove this]
else if either item looks non-numeric, compare alphabetically,
else compare numerically
- So, to avoid as many problems as possible, and to be as newbie-friendly as possible, I use the general principle that:
if both items look numeric, they should be compared numerically,
otherwise they should be compared alphabetically.
- However, there should be a way to force two items to be compared alphabetically.
- [EDIT:] A StrCompare function was added to AHK v2.
- A useful innovation, in addition to, but not instead of comparison operators, would be: StrCmp/NumCmp functions to force a numeric/alphabetical comparison.
- [EDIT:] A StrCompare function was added to AHK v2.
- You could also have StrOp/NumOp functions to use an operator dynamically e.g. StrOp(a, "<", b).
NumOp and StrOp: 'dynamic' operators - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=6&t=55926
- I've also proposed Num (similar to Integer/Float and '+0') and IsNum functions.
Wish List 2.0 - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=13&t=36789
- For reference, here are some examples of forcing an alphabetical comparison (under the AHK v2.0-a099 rules):
Code: Select all
;examples of forcing an alphabetical comparison:
;numeric:
MsgBox(2 < 10) ;1
MsgBox(2 < SubStr("10", 1)) ;1
MsgBox(SubStr("2", 1) < 10) ;1
MsgBox(0+SubStr("2", 1) < SubStr("10", 1)) ;1 ;note: use of '0+'
;alphabetical:
n2 := 2, n10 := 10
MsgBox("2" < "10") ;0
MsgBox("" 2 < "" 10) ;0
MsgBox("" n2 < "" n10) ;0
MsgBox(SubStr("2", 1) < SubStr("10", 1)) ;0 ;note: users would need to be warned of this [AHK v1: 1]
MsgBox(String(2) < String(10)) ;0 [AHK v1: 1]
MsgBox(Str(2) < Str(10)) ;0 ;a proposal [AHK v1: 1]
MsgBox(StrOp(2, "<", 10)) ;0 ;a proposal
'var1 + var2'
'var1 = var2'
'var1 < var2'
- I used the results to inform my views. Thanks for reading.
Code: Select all
numbers/strings in expressions: test results
tested on AHK v1.1.30.00 and AHK v2.0-a099
links:
Variables and Expressions - Definition & Usage | AutoHotkey
https://autohotkey.com/docs/Variables.htm#AddSub
Variables and Expressions - Definition & Usage | AutoHotkey v2
https://lexikos.github.io/v2/docs/Variables.htm#AddSub
Variables and Expressions - Definition & Usage | AutoHotkey
https://autohotkey.com/docs/Variables.htm#equal
Variables and Expressions - Definition & Usage | AutoHotkey v2
https://lexikos.github.io/v2/docs/Variables.htm#equal
Variables and Expressions - Definition & Usage | AutoHotkey
https://autohotkey.com/docs/Variables.htm#compare
Variables and Expressions - Definition & Usage | AutoHotkey v2
https://lexikos.github.io/v2/docs/Variables.htm#compare
summaries:
+ (AHK v1):
(if first item is a literal string, append strings)
error if either item looks non-numeric
error if either item is a literal string
else add
+ (AHK v2):
error if either item looks non-numeric
error if first item is a literal string
else add
= and < (AHK v1):
if either item is a literal string e.g. "1" or "a", compare alphabetically
else if either item looks non-numeric, compare alphabetically
else compare numerically
= and < (AHK v2):
if both items are literal strings e.g. "1" or "a", compare alphabetically
else if both items are variables with type 'String', compare alphabetically
else if either item looks non-numeric, compare alphabetically
else compare numerically
tests:
AHK number/string test 1: +
AHK number/string test 2: =
AHK number/string test 3: <
AHK number/string test 4: < (further)
note: add a leading space to the first column to paste into Excel without losing double quotes
note: any leading zeros are lost for numbers when pasting into Excel
AHK number/string test 1: +
where n1 := 1, s1 := "1", s01 := "01", sa := "a"
script AHK v1 AHK v2
n1 + n1 2 2
n1 + s1 2 2
n1 + s01 2 2
n1 + sa err
n1 + 1 2 2
n1 + "1" 2
n1 + "01" 2
n1 + "a" err
s1 + n1 2 2
s1 + s1 2 2
s1 + s01 2 2
s1 + sa err
s1 + 1 2 2
s1 + "1" 2
s1 + "01" 2
s1 + "a" err
s01 + n1 2 2
s01 + s1 2 2
s01 + s01 2 2
s01 + sa err
s01 + 1 2 2
s01 + "1" 2
s01 + "01" 2
s01 + "a" err
sa + n1 err
sa + s1 err
sa + s01 err
sa + sa err
sa + 1 err
sa + "1" err
sa + "01" err
sa + "a" err
1 + n1 2 2
1 + s1 2 2
1 + s01 2 2
1 + sa err
1 + 1 2 2
1 + "1" 2
1 + "01" 2
1 + "a" err
"1" + n1 11 err [Unexpected operator following literal string.__ Specifically: + n1)]
"1" + s1 11 err [Unexpected operator following literal string.__ Specifically: + s1)]
"1" + s01 101 err [Unexpected operator following literal string.__ Specifically: + s01)]
"1" + sa 1a err [Unexpected operator following literal string.__ Specifically: + sa)]
"1" + 1 11 err [Unexpected operator following literal string.__ Specifically: + 1)]
"1" + "1" 11 err [Unexpected operator following literal string.__ Specifically: + "1")]
"1" + "01" 101 err [Unexpected operator following literal string.__ Specifically: + "01")]
"1" + "a" 1a err [Unexpected operator following literal string.__ Specifically: + "a")]
"01" + n1 011 err [Unexpected operator following literal string.__ Specifically: + n1)]
"01" + s1 011 err [Unexpected operator following literal string.__ Specifically: + s1)]
"01" + s01 0101 err [Unexpected operator following literal string.__ Specifically: + s01)]
"01" + sa 01a err [Unexpected operator following literal string.__ Specifically: + sa)]
"01" + 1 011 err [Unexpected operator following literal string.__ Specifically: + 1)]
"01" + "1" 011 err [Unexpected operator following literal string.__ Specifically: + "1")]
"01" + "01" 0101 err [Unexpected operator following literal string.__ Specifically: + "01")]
"01" + "a" 01a err [Unexpected operator following literal string.__ Specifically: + "a")]
"a" + n1 a1 err [Unexpected operator following literal string.__ Specifically: + n1)]
"a" + s1 a1 err [Unexpected operator following literal string.__ Specifically: + s1)]
"a" + s01 a01 err [Unexpected operator following literal string.__ Specifically: + s01)]
"a" + sa aa err [Unexpected operator following literal string.__ Specifically: + sa)]
"a" + 1 a1 err [Unexpected operator following literal string.__ Specifically: + 1)]
"a" + "1" a1 err [Unexpected operator following literal string.__ Specifically: + "1")]
"a" + "01" a01 err [Unexpected operator following literal string.__ Specifically: + "01")]
"a" + "a" aa err [Unexpected operator following literal string.__ Specifically: + "a")]
AHK number/string test 2: =
where n1 := 1, s1 := "1", s01 := "01", sa := "a"
script AHK v1 AHK v2
n1 = n1 1 1
n1 = s1 1 1
n1 = s01 1 1
n1 = sa 0 0
n1 = 1 1 1
n1 = "1" 1 1
n1 = "01" 0 1
n1 = "a" 0 0
s1 = n1 1 1
s1 = s1 1 1
s1 = s01 1 0
s1 = sa 0 0
s1 = 1 1 1
s1 = "1" 1 1
s1 = "01" 0 0
s1 = "a" 0 0
s01 = n1 1 1
s01 = s1 1 0
s01 = s01 1 1
s01 = sa 0 0
s01 = 1 1 1
s01 = "1" 0 0
s01 = "01" 1 1
s01 = "a" 0 0
sa = n1 0 0
sa = s1 0 0
sa = s01 0 0
sa = sa 1 1
sa = 1 0 0
sa = "1" 0 0
sa = "01" 0 0
sa = "a" 1 1
1 = n1 1 1
1 = s1 1 1
1 = s01 1 1
1 = sa 0 0
1 = 1 1 1
1 = "1" 1 1
1 = "01" 0 1
1 = "a" 0 0
"1" = n1 1 1
"1" = s1 1 1
"1" = s01 0 0
"1" = sa 0 0
"1" = 1 1 1
"1" = "1" 1 1
"1" = "01" 0 0
"1" = "a" 0 0
"01" = n1 0 1
"01" = s1 0 0
"01" = s01 1 1
"01" = sa 0 0
"01" = 1 0 1
"01" = "1" 0 0
"01" = "01" 1 1
"01" = "a" 0 0
"a" = n1 0 0
"a" = s1 0 0
"a" = s01 0 0
"a" = sa 1 1
"a" = 1 0 0
"a" = "1" 0 0
"a" = "01" 0 0
"a" = "a" 1 1
AHK number/string test 3: <
where n1 := 1, s1 := "1", s01 := "01", sa := "a"
script AHK v1 AHK v2
n1 < n1 0 0
n1 < s1 0 0
n1 < s01 0 0
n1 < sa 1 1
n1 < 1 0 0
n1 < "1" 0 0
n1 < "01" 0 0
n1 < "a" 1 1
s1 < n1 0 0
s1 < s1 0 0
s1 < s01 0 0
s1 < sa 1 1
s1 < 1 0 0
s1 < "1" 0 0
s1 < "01" 0 0
s1 < "a" 1 1
s01 < n1 0 0
s01 < s1 0 1
s01 < s01 0 0
s01 < sa 1 1
s01 < 1 0 0
s01 < "1" 1 1
s01 < "01" 0 0
s01 < "a" 1 1
sa < n1 0 0
sa < s1 0 0
sa < s01 0 0
sa < sa 0 0
sa < 1 0 0
sa < "1" 0 0
sa < "01" 0 0
sa < "a" 0 0
1 < n1 0 0
1 < s1 0 0
1 < s01 0 0
1 < sa 1 1
1 < 1 0 0
1 < "1" 0 0
1 < "01" 0 0
1 < "a" 1 1
"1" < n1 0 0
"1" < s1 0 0
"1" < s01 0 0
"1" < sa 1 1
"1" < 1 0 0
"1" < "1" 0 0
"1" < "01" 0 0
"1" < "a" 1 1
"01" < n1 1 0
"01" < s1 1 1
"01" < s01 0 0
"01" < sa 1 1
"01" < 1 1 0
"01" < "1" 1 1
"01" < "01" 0 0
"01" < "a" 1 1
"a" < n1 0 0
"a" < s1 0 0
"a" < s01 0 0
"a" < sa 0 0
"a" < 1 0 0
"a" < "1" 0 0
"a" < "01" 0 0
"a" < "a" 0 0
AHK number/string test 4: < (further)
where n10 := 10, n2 := 2, s10 := "10", s2 := "2"
script AHK v1 AHK v2
n10 < n10 0 0
n10 < n2 0 0
n10 < s10 0 0
n10 < s2 0 0
n10 < 10 0 0
n10 < 2 0 0
n10 < "10" 0 0
n10 < "2" 1 0
n2 < n10 1 1
n2 < n2 0 0
n2 < s10 1 1
n2 < s2 0 0
n2 < 10 1 1
n2 < 2 0 0
n2 < "10" 0 1
n2 < "2" 0 0
s10 < n10 0 0
s10 < n2 0 0
s10 < s10 0 0
s10 < s2 0 1
s10 < 10 0 0
s10 < 2 0 0
s10 < "10" 0 0
s10 < "2" 1 1
s2 < n10 1 1
s2 < n2 0 0
s2 < s10 1 0
s2 < s2 0 0
s2 < 10 1 1
s2 < 2 0 0
s2 < "10" 0 0
s2 < "2" 0 0
10 < n10 0 0
10 < n2 0 0
10 < s10 0 0
10 < s2 0 0
10 < 10 0 0
10 < 2 0 0
10 < "10" 0 0
10 < "2" 1 0
2 < n10 1 1
2 < n2 0 0
2 < s10 1 1
2 < s2 0 0
2 < 10 1 1
2 < 2 0 0
2 < "10" 0 1
2 < "2" 0 0
"10" < n10 0 0
"10" < n2 1 0
"10" < s10 0 0
"10" < s2 1 1
"10" < 10 0 0
"10" < 2 1 0
"10" < "10" 0 0
"10" < "2" 1 1
"2" < n10 0 1
"2" < n2 0 0
"2" < s10 0 0
"2" < s2 0 0
"2" < 10 0 1
"2" < 2 0 0
"2" < "10" 0 0
"2" < "2" 0 0
Code: Select all
;==================================================
;numbers/strings in expressions
;test 'a + b', 'a = b', 'a < b' etc
;note: puts text onto the clipboard at the end
;note: can be a little slow
;==================================================
#SingleInstance force
ListLines, Off
#KeyHistory 0
Menu, Tray, Click, 1
#NoEnv
AutoTrim, Off
#UseHook
SplitPath, A_ScriptName,,,, vScriptNameNoExt
Menu, Tray, Tip, % vScriptNameNoExt
;==================================================
vPathTemp := A_ScriptDir "\z temp str num " A_Now ".ahk"
vPathAhk1 := A_AhkPath
vPathAhk2 := "C:\Program Files\AutoHotkey v2\AutoHotkeyU32.exe"
if FileExist(vPathTemp)
throw "error: file already exists:`r`n" vPathTemp
if !FileExist(vPathAhk1)
throw "error: file not found:`r`n" vPathAhk1
if !FileExist(vPathAhk2)
throw "error: file not found:`r`n" vPathAhk2
;==============================
if 1
{
vScriptA = ;continuation section
(LTrim Join,`s
n1 := 1
s1 := "1"
s01 := "01"
sa := "a"
)
vListVar = n1,s1,s01,sa,1,"1","01","a"
}
;==============================
if 0
{
vScriptA = ;continuation section
(LTrim Join,`s
n10 := 10
n2 := 2
s10 := "10"
s2 := "2"
)
vListVar = n10,n2,s10,s2,10,2,"10","2"
}
;==============================
vOp := "+"
vOp := "="
vOp := "<"
;==============================
vDQ := Chr(34)
vScriptC1 = FileAppend, `% var, `% "*"
vScriptC2 = FileAppend(var, "*")
oVar := StrSplit(vListVar, ",")
VarSetCapacity(vOutput, 1000*2)
vOutput := "where " vScriptA "`r`n"
vOutput .= "script`t" "AHK v1`t" "AHK v2`r`n"
Loop % oVar.Length()
{
vItem1 := oVar[A_Index]
Loop % oVar.Length()
{
vItem2 := oVar[A_Index]
vScriptB := "try var := (" vItem1 " " vOp " " vItem2 ")"
vScriptB .= "`r`n" "catch"
vScriptB .= "`r`n" "`tvar := " vDQ "err" vDQ
Loop 2
{
vScript := vScriptA "`r`n" vScriptB "`r`n" vScriptC%A_Index%
;MsgBox, % vScript
FileAppend, % vScript, % "*" vPathTemp, UTF-8
;vTarget = "%vPathAhk%" /ErrorStdOut "%vPathTemp%"
vTarget := vDQ vPathAhk%A_Index% vDQ " /ErrorStdOut " vDQ vPathTemp vDQ
vPathAhk := vPathAhk%A_Index%
vRet := JEE_RunGetStdErr(vTarget)
vRet := RTrim(vRet, "`r`n")
vRet := RegExReplace(vRet, "[`r`n]", "_")
vRet := RegExReplace(vRet, "^.*==> ")
;if !(vRet = "")
; MsgBox, % vScript
if !(vRet = "")
;vRet%A_Index% := "err(pre)"
vRet%A_Index% := "err [" vRet "]"
else
vRet%A_Index% := JEE_RunGetStdOut(vTarget)
FileOpen(vPathTemp, "w").Close() ;empty file
}
vOutput .= vItem1 " " vOp " " vItem2 "`t" vRet1 "`t" vRet2 "`r`n"
}
}
FileDelete, % vPathTemp
Clipboard := vOutput
MsgBox, % "done"
return
;==================================================
JEE_RunGetStdErr(vTarget, vSize:="")
{
DetectHiddenWindows, On
vComSpec := A_ComSpec ? A_ComSpec : ComSpec
Run, % vComSpec,, Hide, vPID
WinWait, % "ahk_pid " vPID
DllCall("kernel32\AttachConsole", "UInt",vPID)
oShell := ComObjCreate("WScript.Shell")
oExec := oShell.Exec(vTarget)
vStdErr := ""
if !(vSize = "")
VarSetCapacity(vStdErr, vSize)
while !oExec.StdErr.AtEndOfStream
vStdErr := oExec.StdErr.ReadAll()
DllCall("kernel32\FreeConsole")
Process, Close, % vPID
return vStdErr
}
;==================================================
JEE_RunGetStdOut(vTarget, vSize:="")
{
DetectHiddenWindows, On
vComSpec := A_ComSpec ? A_ComSpec : ComSpec
Run, % vComSpec,, Hide, vPID
WinWait, % "ahk_pid " vPID
DllCall("kernel32\AttachConsole", "UInt",vPID)
oShell := ComObjCreate("WScript.Shell")
oExec := oShell.Exec(vTarget)
vStdOut := ""
if !(vSize = "")
VarSetCapacity(vStdOut, vSize)
while !oExec.StdOut.AtEndOfStream
vStdOut := oExec.StdOut.ReadAll()
DllCall("kernel32\FreeConsole")
Process, Close, % vPID
return vStdOut
}
;==================================================