passing parameters as strings v. numeric Topic is solved

Discuss the future of the AutoHotkey language
User avatar
derz00
Posts: 497
Joined: 02 Feb 2016, 17:54
Location: Middle of the round cube
Contact:

Re: passing parameters as strings v. numeric

26 Mar 2018, 12:46

Hello again, sorry about any misunderstandings I might have caused.
jeeswg wrote: It's very common for people to pass numbers (as strings) to SendMessage, people have been able to do this with no problem since AutoHotkey began. The InputBox scenario is an example of this.
To that I would say, quoting you:
I'm not aware of anyone using it this way.
Can you provide examples? Even if it has been done, is it a good practice? String type is string type,int type is int type, and depending on a program to automatically switch back and forth is not guaranteed to prevent bugs.
- You're using the word 'consistent' to mean 'normal' (perhaps based on your own programming prejudices, something we all have). AutoHotkey is consistent. There were good reasons that AutoHotkey chose this route, maybe AutoHotkey was right.
- As was pointed out, "str"+0 causes an error in AHK v2. Anyhow, both AHK v1 and AHK v2 have some type specification and differentiation functionality, and I'm glad they do, but for most functions it's better to ignore types.
I suppose it is more a feature than an inconsistency. But my point was that such a feature cannot be used to perform, as you say,
introducing greater consistency...an aim and strength of AutoHotkey v2
Also, at this point I don't see any argument for a programmer or program (not sure which you were referring to) to ever ignore types; AutoHotkey doesn't. It switches types, if it can, in some functions and expressions at least, probably to make it easier for beginners or in-a-hurry programmers. It is never necessary to make use of that feature. With one exception--concatenation. string := "my age is " intAge. That's handy, I'll admit. but changing it to str(intAge) isn't much loss.

Wishing all a good day.
try it and see
...
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: passing parameters as strings v. numeric

26 Mar 2018, 13:17

With one exception--concatenation
It has no dangerous implications, it is convenient and should probably be kept. However, str + 0 is blank or number, when blank, the error propagates undetected through the script, making it, potentially, very difficult to locate the source of the error. The fact that it is sometimes is a number, makes the error rarer and even more difficult to locate.

Cheers.
User avatar
derz00
Posts: 497
Joined: 02 Feb 2016, 17:54
Location: Middle of the round cube
Contact:

Re: passing parameters as strings v. numeric

26 Mar 2018, 13:29

str + 0 is blank or number
My apologies, but can you explain further? I cannot see the point you make--possibly you are disagreeing with something I said?
try it and see
...
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: passing parameters as strings v. numeric

26 Mar 2018, 13:45

The following might offtopic, I cannot recall what the purpose of this thread was.
I mean that because this produces a number

Code: Select all

str := "1"
msgbox str + 0 ; 1
and this

Code: Select all

str := "abc"
msgbox str + 0 ; blank
produces blank, your code will work until you make the mistake of a using a non numeric string, if both where errors, errors would be easier to detect. And, for performance, you should never use numeric strings in math operations, although I think (helgef memory :? ) the numbers are cached for speed, but the memory is wasted.

I cannot see any reason to allow nonNumTypeVar + numTypeVar, but ofc, we then need built in functions for converting string to number.

Sorry if I am still unclear, as far as I could tell, I agree with you derz00.

Cheers.
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: passing parameters as strings v. numeric

26 Mar 2018, 14:11

So essentially for that to happen we need a type system.
Recommends AHK Studio
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: passing parameters as strings v. numeric

29 Mar 2018, 02:06

- @derz00: Virtually all AutoHotkey functions allow you to pass a number, with either a numeric or string type interchangeably.
- The only functions I can think of that break the rule are NumXXX and XXXMessage, and in both cases (IMO) the behaviour is undesirable and contrary to the stated aims of AHK v2. (Sometimes you need to force type when interacting with COM objects.) (If NumGet/NumPut remain as they are, I don't mind too much.) (Interestingly, object key names were redeveloped to make numeric and string keys such as '1' interchangeable.)
- Re.
probably to make it easier for beginners or in-a-hurry programmers
You were right here, these are good arguments for interchangeability.
- The XXXMessage commands were more standard in AHK v1 re. interchangeability. And I believe that the behaviour has been changed in AHK v2 to support this AHK v1 feature that I didn't know existed and that so far it seems, no-one uses:
PostMessage / SendMessage
https://autohotkey.com/docs/commands/Po ... essage.htm
A quoted/literal string may also be sent
- So the question is, which is 'the lesser of two evils', remove a feature that no-one uses, or, a lot of people being twitchy to ensure they have used the correct type, checking through scripts adding +0 where necessary, and both casual and expert users getting mysterious bugs.
- Any time a number is obtained via SubStr/StrSplit/RegExMatch (objects)/RegExReplace/InputBox/IniRead for example, it will have to be forced to become a numeric type at some point.
- I came across this problem when parsing a space-separated list when working on recreating AHK dialog commands e.g. MsgBox/InputBox/Progress/SplashImage.
- The ideal type system, and conversion between types, are interesting topics, and I don't mind them being discussed here, but they are not what concerns me. I have no complaints about how AHK handles those issues.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
User avatar
derz00
Posts: 497
Joined: 02 Feb 2016, 17:54
Location: Middle of the round cube
Contact:

Re: passing parameters as strings v. numeric

31 Mar 2018, 12:06

jeeswg wrote: adding +0 where necessary
Except that "1" + 0 wouldn't work either, if types were enforced.
expert users getting mysterious bugs
Either the expert part is wrong, or the program isn't throwing proper errors. Types are easy to debug, not mysterious.
it will have to be forced to become a numeric type at some point
That's quite easy: In python, to get an integer input, it looks like: input_int = int(input("enter an integer"))
parsing a space-separated list
Check the AHK source code, or some place where a parameter is space separated options.. I'm sure there'd be a way to do it right.

As to why these functions under discussion behave differently than others in relation to switching strings to ints, that is above my head. Perhaps they have a reason for being developed that way.
try it and see
...
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: passing parameters as strings v. numeric

31 Mar 2018, 17:08

@derz00: Quick recap.

Code: Select all

;warning: be careful with WM_SETTEXT, you could overwrite the Edit control text

;AHK v1
;q::
;all of these are fine:
SendMessage, 0xB1, 5, 10, Edit1, A ;EM_SETSEL := 0xB1
var1 := 5, var2 := 10
SendMessage, 0xB1, % var1, % var2, Edit1, A ;EM_SETSEL := 0xB1
var1 := "5", var2 := "10"
SendMessage, 0xB1, % var1, % var2, Edit1, A ;EM_SETSEL := 0xB1
ControlGetText, vText2, Edit1, A
vText := "hello world"
if (vText2 = "")
	SendMessage, 0xC, 0, % &vText, Edit1, A ;WM_SETTEXT := 0xC
;this is not useful:
;I have never seen this used, and I'm happy to use one more line as in the &vText example above
ControlGetText, vText2, Edit1, A
if (vText2 = "")
	SendMessage, 0xC, 0, "hello world", Edit1, A ;WM_SETTEXT := 0xC
return

;AHK v2
;q::
;all of these are fine (apart from the one example indicated):
SendMessage(0xB1, 5, 10, "Edit1", "A") ;EM_SETSEL := 0xB1
var1 := 5, var2 := 10
SendMessage(0xB1, var1, var2, "Edit1", "A") ;EM_SETSEL := 0xB1
var1 := "5", var2 := "10" ;[THIS DOES NOT WORK IN AHK V2]
SendMessage(0xB1, var1, var2, "Edit1", "A") ;EM_SETSEL := 0xB1
vText2 := ControlGetText("Edit1", "A")
vText := "hello world"
if (vText2 = "")
	SendMessage(0xC, 0, &vText, "Edit1", "A") ;WM_SETTEXT := 0xC
;this is not useful:
;I have never seen this used, and I'm happy to use one more line as in the &vText example above
if (vText2 = "")
	SendMessage(0xC, 0, "hello world", "Edit1", "A") ;WM_SETTEXT := 0xC
return
- So the point is that in AHK v1, strings that started and ended with double quotes were treated as strings, everything else was treated as numeric.
- I appreciate why the change was made in AHK v2, it was to make behaviour consistent for all strings. However, the problem is that virtually no-one ever used literal strings in this way with PostMessage/SendMessage. And also, the vast majority of the times that strings were used, it was a string that contained a number.
- The new behaviour would break a lot of scripts, those scripts would need to use +0 regularly to force numeric parameters (inconvenient/ugly/a new source of bugs/not good for quick coding/introduces a new paradigm of sweating over getting your types right: not newbie-friendly). Also, it would make XXXMessage very unusual in being one of the only functions to treat numeric and string parameters differently.
- Another disadvantage of the new behaviour is that var by itself is inconsistent, if var contains a numeric type, that's a value, if it contains a string type, it uses the address of var. I would that rather addresses always be clear and obvious e.g. addr or &var, this is more readable and so easier to debug.
- For me, the clear argument is just to remove special string handling altogether. If you want to pass a string, just use &vText. Which is what I'm using at the moment in AHK v1 anyway.
- Very few people will be aware of what's happened, and why it's happening. After looking at AHK v2 for a long time, I only just realised this myself.
- Capisce?
re. other points
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
lexikos
Posts: 9552
Joined: 30 Sep 2013, 04:07
Contact:

Re: passing parameters as strings v. numeric

05 Apr 2018, 17:13

It is no more correct to say that SendMessage expects numeric parameters than to say that all of DllCall's parameters are numeric, or the same for every other function. The address of the string is passed because that's how strings are passed. If you say that SendMessage expects numeric parameters because even when you're passing a string, you're passing a number, the argument loses all value, because it must hold true for the inverse: if the function passes the string by address, it is passing a numeric value. (The function expects a numeric value, and it receives one; an address.) You're doing the same when you pass a string to any built-in function, or even user-defined function (but in that case the string is copied from its original address before the function's body executes).

SendMessage and DllCall both deal with functions outside of AutoHotkey's type system. The difference between them is that DllCall deals with a far greater range of types (putting aside structs). The same approach could be used for DllCall - all parameters being numbers - and it would lose no flexibility, just a little convenience and clarity.

However, it is true that it isn't common to pass a string in a window message. There are also many messages that take other structures, sometimes including strings inside a structure, and some that need the string to be converted. In those cases it is already necessary to deal with pointers (and string addresses), so it's not a big deal to require them to be passed by address explicitly.

Given that SendMessage can't know the meaning of the parameters nor the caller's intention, it would be reasonable to require parameters intended to be numeric to have the correct type (integer). If an exception is thrown for any incorrect type, there will be no insidious bugs. As it is, passing a numeric string and expecting it to be converted will cause a bug. If it would be converted, passing a numeric string and expecting it to be passed as-is (as a numeric string) would cause a bug. However, requiring strings to be passed by address would make it unlikely that the latter bug would go unnoticed (assuming that the strings are sometimes non-numeric and such strings would cause an exception).
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: passing parameters as strings v. numeric

05 Apr 2018, 19:14

- @lexikos: Thanks for your comments.
- Yes, your paragraph 1 essentially matches my viewpoint. I've tried to clarify my earlier post:
passing parameters as strings v. numeric - AutoHotkey Community
https://autohotkey.com/boards/viewtopic ... 53#p207653

- My rationale is:
- simplicity (it just accepts numbers: num, "num" or &var) (and perhaps &var handling could be optimised, as a safety check, although I don't personally need it)
- perfect conversion (in AHK v1 only parameters of the form "Text", used strings, these can easily be identified by a parser)
- more readable (var is ambiguous under the current behaviour, it could be a ByRef string reference, or a numeric variable, v. &var/addr/num)
- less is more (very occasionally, less is more, less is better)
- less fiddly (no need to sweat over whether the type was numeric/string when it was defined, and no need to use '+0' (ugly), just to be safe)
- fewer problems (my proposal will cause fewer problems in the short-term and long-term, e.g. with script bugs, and is cleaner)
- not quirky (the original AHK v1 behaviour re. strings was quirky, instead of killing it, we are mutating it into something in some ways more consistent, but if we're honest, something just as quirky)
- no pain (why go through all this pain to maintain some little-used functionality, that saved one line of code occasionally)
- bonus point (an input parameter should not work in a fundamentally different way if passed ByRef versus ByVal, think NumGet/NumPut/XXXMessage/oFile.RawXXX, var should mean var+0 in these cases, not &var, StrGet/StrPut has this right!)
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
lexikos
Posts: 9552
Joined: 30 Sep 2013, 04:07
Contact:

Re: passing parameters as strings v. numeric

06 Apr 2018, 02:28

jeeswg wrote:Yes, your paragraph 1 essentially matches my viewpoint.
As far as I can tell from your previous posts and this last one, no, it does not.
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: passing parameters as strings v. numeric  Topic is solved

07 Apr 2018, 04:40

- @lexikos: Thanks so much for this update, and your workaround for strings.
AutoHotkey v2 alpha (UPDATES) - Page 3 - AutoHotkey Community
https://autohotkey.com/boards/viewtopic ... 67#p211067
Changed &address-of to work with literal and temporary strings.
...
Changed SendMessage/PostMessage to accept only integers.
- Some test code:

Code: Select all

;note: all 5 of the tests below worked
q:: ;test SendMessage (v2.0-a093-f7548e0)
;SendMessage(0xC, 0, &"hello world", "Edit1", "A") ;WM_SETTEXT := 0xC
;SendMessage(0xC, 0, &("hello" A_Space "world"), "Edit1", "A") ;WM_SETTEXT := 0xC
SendMessage(0xC, 0, &SubStr("hello world", 1), "Edit1", "A") ;WM_SETTEXT := 0xC
;SendMessage(0xB1, "5", "10", "Edit1", "A") ;EM_SETSEL := 0xB1
var1 := "5", var2 := "10"
;SendMessage(0xB1, var1, var2, "Edit1", "A") ;EM_SETSEL := 0xB1
return
- I had thought that extending the & address-of operator to handle temporary strings could provide a neat 'best of both worlds' fix (numbers as strings accepted, literal strings easily passed), but I didn't know how feasible it would be. ... After checking, it seemed that the documentation hadn't been updated yet, so I had a guess at the syntax and it worked, and fortunately the syntax was(/is) just what I had hoped for. Thanks again for this.
- [EDIT:] I suppose that you will have noticed that some of this syntax could have significance for DllCall alternatives. Instead of specifying Str,"Text" you could specify Ptr,&"Text". When I'd wanted to wrap DllCall lines for specific Winapi functions as custom functions, to hide away the parameter types, there had been a dilemma over whether to use Str or Ptr, now I can just always use Ptr.
- I wonder where else this functionality could have significance.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: passing parameters as strings v. numeric

07 Apr 2018, 05:52

It looks like can be an expression changed to sometimes must be an expression, I do not see how this* is useful in any way. It just introduces an unecessary exception to normal use of built in functions. Passing a variable (or string) shouldn't require prefixing an &, makes no sense. If XXXmessage , "num" or XXXmessage , varContainingNumericStr had thrown an exception, it would make more sense.

*not refering to the & operator.

Cheers :wave: .
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: passing parameters as strings v. numeric

07 Apr 2018, 10:39

- @Helgef: In this example, we see the normal behaviour for parameters that expect 'numbers' (numeric content) whether the type is Integer or String. The XXXMessage functions are just returning to normality.

Code: Select all

MsgBox, % SubStr("abcde", 3) ;cde ;AHK v1
MsgBox, % SubStr("abcde", "3") ;cde ;AHK v1
MsgBox(SubStr("abcde", 3)) ;cde ;AHK v2
MsgBox(SubStr("abcde", "3")) ;cde ;AHK v2
- AFAIK AHK's built-in functions generally ignore the *type*, but consider the *content* (numeric or string). I welcome any exceptions being pointed out.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: passing parameters as strings v. numeric

07 Apr 2018, 11:47

Yeah any function which expects a string more than it does expect a number.
Recommends AHK Studio
lexikos
Posts: 9552
Joined: 30 Sep 2013, 04:07
Contact:

Re: passing parameters as strings v. numeric

07 Apr 2018, 17:40

Helgef wrote:It looks like can be an expression changed to sometimes must be an expression,
What do you mean? SendMessage's entire parameter list is an expression (or sub-expression).
It just introduces an unecessary exception to normal use of built in functions.
Regardless of what we do, SendMessage is necessarily an exception, because (like DllCall) it interfaces with an external system which does not allow type information to be carried across. In other words, unlike every other built-in function, we have no control over how the callee interprets the parameters. If we pass a string "123" by address to a message which expects a number, it will see not the value "123", but some arbitrary address. This is not how a normal built-in function acts.

No one should be surprised that you can't pass a literal string to SendMessage (as a string) if they read the documentation for the message, and it says "A pointer to a null-terminated string [...]." Parameters of official messages are always documented this way, because they are documented for C. In C, one has to perform a typecast to pass a pointer as WPARAM/LPARAM (a numeric type).

SendMessage's parameters are variable type, but unlike native AutoHotkey functions, we don't know what type the parameters should be. So the options are:
  • assume the type of the value shows the author's intent (not necessarily true, even for me)
  • require the type to be specified (if you want to do that, you can use DllCall)
  • let the parameter always be integer
Message parameters are nearly always numbers. The third option improves reliability/ease of use for the most common scripts, at the expense of a minor convenience in some very small percent of cases. Although I don't agree with half of what jeeswg says, I agree that treating numeric strings and pure numbers differently can cause issues. I personally ran into such issues with objects repeatedly, until I changed objects to treat key "1" as 1, etc. It's not a matter of the problem being easy or hard to debug, but of having too little reason to allow it to be a problem in the first place. Stricter languages which differentiate between types generally do so more consistently and/or have better tools to prevent these issues.

(For NumPut/NumGet, it seems far less likely that an address will come from a string, or that one would want to put into/get from the numeric component of a variable when one can simply perform an assignment. Likewise for RawRead/RawWrite; if you want to read into or write a variable which holds a pure integer, there's no good reason to use the Raw methods over ReadInt/WriteInt.)

In v1, scripts were already required to use the address operator for variables' content, but SendMessage cheated a bit and "introspected" the code to find the variable to update (even though the variable itself wasn't passed to the command).
If XXXmessage , "num" or XXXmessage , varContainingNumericStr had thrown an exception, it would make more sense.
Why? Wouldn't that be "an unecessary [sic] exception to normal use of built in functions"?
jeeswg wrote:In this example, we see the normal behaviour for parameters that expect 'numbers' (numeric content)
I'll point out, again, that SendMessage (in Win32, decoupled from the artificial restrictions of C) does not "expect numbers". It expects values of varying type, depending on the message.
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: passing parameters as strings v. numeric

07 Apr 2018, 18:22

- @nnnik: I was asking for *examples* of any parameters that work differently based on the type (or string/numeric nature of the contents) of whatever was passed to it.

- @lexikos: This is a summary of my views.
- With DllCall, if not using Str or *, that's passing numbers. If you pass &var, that's passing a number (perhaps people could quibble that). Clearly if you pass &var+0, that's passing a number. There's Char, Short, Int, Int64 etc, but they're all numbers.
- If you use Str with DllCall, that's passing a string. (Numbers are involved, and everything is 0s and 1s ultimately, but it's still passing a string.)
- I'm yet to look at types in C++ systematically, however, cf. AutoHotkey, the situation appears to be far more complex, e.g. pointers to pointers being distinct from pointers.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: passing parameters as strings v. numeric

08 Apr 2018, 16:14

This is not how a normal built-in function acts.
My point is that a built-in function accepts variable references, we do not call functions like, substr(&str, x) (x being a numeric string or pure number is besides the point here). Demanding &str rather than str is on par with the quirk of numxxx in v1. I believe the quirk existed due to limitations which doesn't exist any more, and it had useful implications. The new quirk doesn't exist due to some limitation, and it has no useful implications.
No one should be surprised that you can't pass a literal string to SendMessage (as a string) if they read the documentation for the message, and it says "A pointer to a null-terminated string [...]."
No one should read the documentation for the message and try to deduce how to use the built-in function, we pass the string to the built-in function, and as you said, if we want to specify the type, we can use dllcall. The documentation was dead clear on that passing a string would ultimately pass the address to target window.
I agree that treating numeric strings and pure numbers differently can cause issues
Treating strings as a pure numbers do cause issues, never treating a string as a pure number do not cause any issues. Parts of this thread didn't really relate to xxxmessage, my comments regarding "num", varContainingNumericStr and exceptions was in regards to my opinion that strings shouldn't be interpreted as numbers, for any function or math operator, hence that would not be an exception to the normal usage of built-in functions. I'm not passionate about sendmessage, my issue is that it seem like we are taking a step backwards, in favouring the use of numeric strings as pure numbers.

The problems described in the OP was not due to numeric strings not being interpreted as numbers, it was due the usual failure to read the documentation.

Cheers.
off topic
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: passing parameters as strings v. numeric

09 Apr 2018, 00:19

I guess I'll just never use SendMessage again.
Recommends AHK Studio
just me
Posts: 9423
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: passing parameters as strings v. numeric

09 Apr 2018, 05:20

v2.0-a093-f7548e0:

Code: Select all

StrVar := "1234"
NumVar := 1234

MyGui := GuiCreate("", "Test")
MyEdit := MyGui.AddEdit("w400 h400")
MyGui.Show()
MsgBox("Passing StrVar")
SendMessage(0xC, 0, StrVar, , "ahk_id " . MyEdit.Hwnd) ; WM_SETTEXT := 0xC
MsgBox("Passing &StrVar")
SendMessage(0xC, 0, &StrVar, , "ahk_id " . MyEdit.Hwnd) ; WM_SETTEXT := 0xC
MsgBox("Passing NumVar")
SendMessage(0xC, 0, &"", , "ahk_id " . MyEdit.Hwnd) ; WM_SETTEXT := 0xC
SendMessage(0xC, 0, NumVar, , "ahk_id " . MyEdit.Hwnd) ; WM_SETTEXT := 0xC
MsgBox("Passing &NumVar")
SendMessage(0xC, 0, &NumVar, , "ahk_id " . MyEdit.Hwnd) ; WM_SETTEXT := 0xC
MsgBox("Exit")
ExitApp

Return to “AutoHotkey Development”

Who is online

Users browsing this forum: lexikos and 44 guests