If statement changes contents of var

Report problems with documented functionality
pneumatic
Posts: 338
Joined: 05 Dec 2016, 01:51

If statement changes contents of var

01 Dec 2019, 00:56

Code: Select all

int1 := "12345678901234567890"  ;20 digits - 1 longer than ahk can handle for ints, but quotes should mean it's treated as a string
int2 := int1
msgbox % int1 . "`n" . int2
Image

Code: Select all

If (int1 := "12345678901234567890"){  
	int2 := int1
	msgbox % int1 . "`n" . int2
}
Image
swagfag
Posts: 6222
Joined: 11 Jan 2017, 17:59

Re: If statement changes contents of var

01 Dec 2019, 11:39

there was a thread about this not too long ago, but i totally forgot who made it or where it was posted to
maybe someone else can dig it up
SOTE
Posts: 1426
Joined: 15 Jun 2015, 06:21

Re: If statement changes contents of var

02 Dec 2019, 03:49

If (int1 := "12345678901234567890")
That is incorrect syntax. It should be "=" and not ":=".

If (int1 = "12345678901234567890")
This is the correct syntax.
guest3456
Posts: 3462
Joined: 09 Oct 2013, 10:31

Re: If statement changes contents of var

02 Dec 2019, 10:11

SOTE wrote:
02 Dec 2019, 03:49
If (int1 := "12345678901234567890")
That is incorrect syntax. It should be "=" and not ":=".

If (int1 = "12345678901234567890")
This is the correct syntax.
how do you know that he wants to test for equality rather than simply assigning a variable in the expression?
clearly its a bug report so the usage is intentional.

joefiesta
Posts: 497
Joined: 24 Jan 2016, 13:54
Location: Pa., USA

Re: If statement changes contents of var

02 Dec 2019, 10:26

@SOTE The syntax is correct, but, yes, another ridiculous case of some shortcuts in AHK totally obfuscating what is going on. In the if(...) statement (1) init1 is first ASSIGNED the value of the string "1234...". Then, as if the statement were only "If (int1)", the if is evaluated. Yes, this is rather ridiculous, since the IF will always evaluate to TRUE unless the string is "0" or "false". However, none of that changes the poster's (initial) statement that the IF statement does not assign INT2 to be identical to INT1. It certainly looks like the string is being treated as a number somewhere. AHK is not very friendly when it comes to strings and numbers, and does, indeed, some rather absurd things.

The code in question is, thus, identical to:

Code: Select all

int1 := "12345678901234567890"
If (int1){
        int3 := int1
        msgbox % int1 . "`n" . int3
SOTE
Posts: 1426
Joined: 15 Jun 2015, 06:21

Re: If statement changes contents of var

02 Dec 2019, 10:56

Maybe I'm misunderstanding something, but it appeared to me that there was confusion about an Expression versus a Function.

Inside of an Expression you would use "=", and not ":=".

Inside of a Function, when dealing with parameters, you would then use ":=", instead of "=".

Also I thought the behavior was intentional. Maybe because I also like Object Pascal/Delphi, where they use both "=" and ":=", that this difference is more clear in how it's used in AHK v1 versus where some languages use "=" versus "==".

Example difference between Expression and Function:

Code: Select all

If (int1 = "12345678901234567890") ; This is our expression
{  
	int2 := int1
	msgbox % int1 . "`n" . int2
}

Do(int1) ; This is our function
ExitApp
Return

Do(int1 := "12345678901234567890")
{  
	int2 := int1
	msgbox % int1 . "`n" . int2
}
guest3456
Posts: 3462
Joined: 09 Oct 2013, 10:31

Re: If statement changes contents of var

02 Dec 2019, 12:13

SOTE wrote:
02 Dec 2019, 10:56
Maybe I'm misunderstanding something
you are. joefiesta explained it
SOTE wrote:
02 Dec 2019, 10:56
Inside of an Expression you would use "=", and not ":=".
no. you'd use = for comparison, and you'd use := for assignment
you can assign within an expression, in fact things like this happen all the time:

Code: Select all

if (result := DllCall("asdfad"))
   msgbox, result is nonzero: %result%
else
   msgbox, result is falsey (zero or empty "") - dllcall probably failed
or real example:

Code: Select all

if (hwnd := WinExist("Untitled - Notepad"))
   WinHide, ahk_id %hwnd%
or see here and see lines 47, 51, 57 for example

SOTE wrote:
02 Dec 2019, 10:56
Inside of a Function, when dealing with parameters, you would then use ":=", instead of "=".
that's not inside a function, but rather for the function definition in order to set the default values for parameters that may be omitted. and both = and := are allowed for that purpose

pneumatic
Posts: 338
Joined: 05 Dec 2016, 01:51

Re: If statement changes contents of var

02 Dec 2019, 19:21

Thanks, I did mean to assign.

When I first encountered that type of expression I thought it was silly too, but now I can't live without it :lol:

I mean you get 2 lines for the price of 1 - less code and improved performance, what's not to like?
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: If statement changes contents of var

02 Dec 2019, 20:10

This example suggests that by using "" you can still retrieve the original string:

Code: Select all

;q:: ;test if with assignment
int1 := "12345678901234567890"
MsgBox, % int1 ;12345678901234567890

int1 := "12345678901234567890"
if int1
	(0) ;NoOp
int2 := int1
int3 := "" int1
MsgBox, % int1 "`r`n" int2 "`r`n" int3
;result: 12345678901234567890 9223372036854775807 12345678901234567890

if (int1 := "12345678901234567890")
	(0) ;NoOp
int2 := int1
int3 := "" int1
MsgBox, % int1 "`r`n" int2 "`r`n" int3
;result: 12345678901234567890 9223372036854775807 12345678901234567890
return
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
gregster
Posts: 8990
Joined: 30 Sep 2013, 06:48

Re: If statement changes contents of var

02 Dec 2019, 20:25

jeeswg wrote:
02 Dec 2019, 20:10
This example suggests that by using "" you can still retrieve the original string:
Afaik, that's a result of AHK's variable caching:
https://www.autohotkey.com/docs/Concepts.htm#caching wrote:Caching

Although a variable is typically thought of as holding a single value, and that value having a distinct type (string, number or object), AutoHotkey automatically converts between numbers and strings in cases like myString + 1 and MsgBox %myNumber%. As these conversions can happen very frequently, whenever a variable is converted, the result is cached in the variable.

In effect, a variable can contain both a string and a number simultaneously. Usually this just improves the script's performance with no down-sides, but if a variable contains both a number and a string, is it number, or is it a string? This ambiguity causes unexpected behavior in at least two cases:[...]
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: If statement changes contents of var

02 Dec 2019, 20:42

I'd appreciate if anyone could help expand the info here:
string/numeric caching in AHK v1 - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=5&t=69454

Here are two links that are partially related to this thread:
if statement influences floating point number - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=14&t=53498
Object.Push is eating initial zeros - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=5&t=64932
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
SOTE
Posts: 1426
Joined: 15 Jun 2015, 06:21

Re: If statement changes contents of var

03 Dec 2019, 00:18

guest3456 wrote:
02 Dec 2019, 12:13
no. you'd use = for comparison, and you'd use := for assignment
you can assign within an expression, in fact things like this happen all the time:

Code: Select all

if (result := DllCall("asdfad"))
   msgbox, result is nonzero: %result%

Code: Select all

if (hwnd := WinExist("Untitled - Notepad"))
I see what you are saying by these examples, but I don't see how the behavior is incorrect usage versus a bug. I always thought this was intentional behavior programmed by the developers, in AHK v1.
Doing this if (result := DllCall("asdfad")) is not the same as If (int1 := "12345678901234567890")

In the example that Pneumatic gave us, he might of wanted to do assignment, but appears to have wrote it incorrectly.
int1 := "12345678901234567890" Without the "if" or Expression.
Or

Code: Select all

int1 := "12345678901234567890"
If (int1 = "12345678901234567890")
{
        int2 := int1
        msgbox % int1 . "`n" . int2
}
...would have gave him the result desired.

In an expression, the "=" operator, is as if we are saying the variable is equal to or not equal (!=) to. Your use of ":=" in the expression is to assign the result of the function to the variable, prior to a next step. Using the if (int1 = "12345678901234567890"), is also saying "if true" then... You can also use the ":=" to test if the result of the function is true, after assignment, as well. Which seems confusing, but if we are doing just assignment, we don't need the "if" or to put it in an Expression.

Code: Select all

int1 := "12345678901234567890"
if (int1 := Do())
{
	MsgBox,,, True
}
else
{
	MsgBox,,, False
}

if (int1 = Do())
{
	MsgBox,,, True
}
else
{
	MsgBox,,, False
}

if (int1 != Do())
{
	MsgBox,,, True
}
else
{
	MsgBox,,, False
}
Return

Do()
{  
	int2 := "12345678901234567890"
	Return int2
}
To make the intention of assignment more clear, we could have removed the "if" or took it out of an Expression, and just had result := DllCall("asdfad") or int1 := Do(). Because the result of the function would have changed the contents of the variable, regardless. Putting the assignment into an Expression or with "if", is to save a step, which comes off as a good thing and not a bug. It's just that it can be confusing for those that don't know it's combining steps/code.
guest3456
Posts: 3462
Joined: 09 Oct 2013, 10:31

Re: If statement changes contents of var

03 Dec 2019, 11:27

SOTE wrote:
03 Dec 2019, 00:18
Putting the assignment into an Expression or with "if", is to save a step, which comes off as a good thing and not a bug.
thats exactly the purpose
SOTE wrote:
03 Dec 2019, 00:18
I see what you are saying by these examples, but I don't see how the behavior is incorrect usage versus a bug.
its a bug because look at the msgbox screenshot results. very simple.

lexikos
Posts: 9583
Joined: 30 Sep 2013, 04:07
Contact:

Re: If statement changes contents of var

07 Dec 2019, 20:02

Code: Select all

If (int1 := "12345678901234567890"){
This will assign the value and always execute the if statement, because the value is true. Of course, there would be more sensible cases, where the value being assigned is not a constant. But the inline assignment is immaterial anyway.

The issue is with variables containing numeric strings, and specifically evaluating such variables as numbers. Variants of this problem have come up numerous times before. Many other cases where the variable is used as a number will have the same result, supposing it has that same value: (int1 + 0), int3 := int1 + 0, if (int1), bool := !int1, etc.

Fixing these issues properly involves script-breaking changes, which were already made long ago in the v2 branch.
User avatar
rommmcek
Posts: 1473
Joined: 15 Aug 2014, 15:18

Re: If statement changes contents of var

04 Apr 2020, 18:20

jeeswg wrote:
02 Dec 2019, 20:10
This example suggests that by using "" you can still retrieve the original string …
It doesn't have to be a new variable, the old one contains as always both types.

Code: Select all

If (int1 := "12345678901234567890"){  
	int2 := int1 . ""
	msgbox % int1 . "`n" . int2
}
P.s.: Pure numeric assignements prioritize to be integers while alphanumeric ones (e.g.: 0x9) tends to be strings!

Return to “Bug Reports”

Who is online

Users browsing this forum: No registered users and 22 guests