Math syntax parsing issue Topic is solved
Re: Math syntax parsing issue
This is not an inconsistency. The only inconsistency I found elsewhere in our other examples relates to how the first two operands are processed in other examples where those operands are incrementing a value.
Re: Math syntax parsing issue
a POINTER issue maybe:
Run this... and pay attention to the elements that contain (i)
Run this... and pay attention to the elements that contain (i)
Code: Select all
arr := [i:=1000, -2000, i:=3, i=4, i:=5, i:="element6", 7]
MsgBox(arr[1])
MsgBox(arr[2])
MsgBox(arr[3])
MsgBox(arr[4])
MsgBox(arr[5])
MsgBox(arr[6])
MsgBox(arr[7])
Re: Math syntax parsing issue
I see no problem with internal consistency here, as the value of all i is simply updated as the math or evaluation proceeds from left to right.
I noticed earlier that a non-incrementing operand would "stop" the incrementing to its left, but I did find an inconsistency with the first two operands as compared to subsequent ones.
I noticed earlier that a non-incrementing operand would "stop" the incrementing to its left, but I did find an inconsistency with the first two operands as compared to subsequent ones.
Re: Math syntax parsing issue
After further testing, I think the result you got for each element is simply the final value of i after each element was calculated from the array expression. (i) then holds the final value, and this value (via pointer?) is displayed as the value for the elements that contain the (i) variable.
So even tho you produced a similar result to the ++d issue, it may of may not be related.
See my previous example to see if you agree.
Re: Math syntax parsing issue
Thanks Mike, I agree that this is a non-issue after you pointed this out. Do you think this variable update might be causing the "strange" ++d result as well (in the original discussion)?
- Noitalommi_2
- Posts: 393
- Joined: 16 Aug 2023, 10:58
Re: Math syntax parsing issue
I predicted 5 and it's wrong.teadrinker wrote: ↑07 Sep 2023, 22:56Another one example:Try to predict, without executing the code, what this expression will equal.Code: Select all
d := 1 MsgBox ++d + ++d
Re: Math syntax parsing issue
According to what we have learned, the value must be 6, because the final d value is 3.
The next one is 7, because d becomes 2, 2 + 2 is 4, and 3 is then added to that.
The next one is 7, because d becomes 2, 2 + 2 is 4, and 3 is then added to that.
Code: Select all
#Requires AutoHotkey v2.0
d := 1
MsgBox ++d + d + ++d
Re: Math syntax parsing issue
So, are you suggesting that the values produced in the beginning of the thread are normal and expected (not a bug) based on what we have learned and we can move on?
This still makes me uneasy based on the comparisons with other languages. But so be it if that's the case.
Andy
Re: Math syntax parsing issue
This example would seem to be explained not by the final d value, because that would result in 9, but by what thqby described regarding what gets pushed on the stack and when. To me, that may explain the result, but it still doesn’t square it with how it’s documented. It doesn’t make sense for AHK users to have to understand what’s happening under the hood. They should be able to look at the code and documentation and take it at face value.mikeyww wrote: ↑ According to what we have learned, the value must be 6, because the final d value is 3.
The next one is 7, because d becomes 2, 2 + 2 is 4, and 3 is then added to that.
Code: Select all
#Requires AutoHotkey v2.0 d := 1 MsgBox ++d + d + ++d
Re: Math syntax parsing issue
So this is my understanding at this point.
Essentially you can envision the expression operation as follows?
1. All ++d found in the expression are calculated prior to any math operators being applied from left to right.
2. Then the individual math operations are performed from left to right using the final value of d that was obtained using step 1.
Because... the expression is a separate operation to the display operation of msgbox. The Msgbox retrieves its values AFTER the entire expression has been performed, and new values have been stored in memory for d.
Does that sound accurate?
I am unable to do any tests with this in mind, but can later.
If this is accurate then I agree with @boiler about it being a bit of a pain to keep track of for many AHK coders.
Essentially you can envision the expression operation as follows?
1. All ++d found in the expression are calculated prior to any math operators being applied from left to right.
2. Then the individual math operations are performed from left to right using the final value of d that was obtained using step 1.
Because... the expression is a separate operation to the display operation of msgbox. The Msgbox retrieves its values AFTER the entire expression has been performed, and new values have been stored in memory for d.
Does that sound accurate?
I am unable to do any tests with this in mind, but can later.
If this is accurate then I agree with @boiler about it being a bit of a pain to keep track of for many AHK coders.
Re: Math syntax parsing issue
And that's my traditional understanding:
What happens:
Code: Select all
d := 1
MsgBox ((d) * (++d) * (++d))
- (d) * (++d)
- (++d) -> d = 2
- (d) * (d) -> r1 = 4 (interim result)
- (r1) * (++d)
- (++d) -> d = 3
- (r1) * (d) -> 12
- (d) * (++d)
- (d) -> l = 1 (left operand)
- (++d) -> r = 2 (right operand)
- (l) * (r) -> i = 2 (interim result)
- (i) * (++d)
- (++d) -> r = 3 (right operand)
- (i) * (r) -> 6
Re: Math syntax parsing issue
Andy, I was just explaining how the bug works!
Perhaps "bug" is a matter of opinion here. I do call this a bug because it's a result that many did not expect or want-- so agree with you as well as boiler.
I had noted that the non-incremented operand "stops" the incrementing for operands to its left-- but do not feel that this is best!
It does explain why this is 7.
2 + 2 + 2
then 2 + 2 + 3.
Sensible? Not really!
Perhaps "bug" is a matter of opinion here. I do call this a bug because it's a result that many did not expect or want-- so agree with you as well as boiler.
I had noted that the non-incremented operand "stops" the incrementing for operands to its left-- but do not feel that this is best!
It does explain why this is 7.
Code: Select all
#Requires AutoHotkey v2.0
d := 1
MsgBox ++d + d + ++d
then 2 + 2 + 3.
Sensible? Not really!
Re: Math syntax parsing issue
My understanding was incorrect then. It still increments d from left to right along with the math operations.
I found a solution... avoid using ++x (in complex expressions). There are other ways that don't result in smoke coming out of my ears.
Thank you sir!
Time to start the weekend.
Andy
Re: Math syntax parsing issue
Yes, one can definitely work around this through using multiple math statements in sequence.
Re: Math syntax parsing issue
Yah, that's what I ended up doing as well. Very interesting discourse. An opinion was even changed
« AHK Portable Installer » | « CallTipsForAll » | « TheArkive AHK v1 Scripts » | « TheArkive AHK v2 Scrpts » | « TheArkive on GitHub »
Re: Math syntax parsing issue Topic is solved
This comment from the := is also true for pre-inc/dec:++
--
The operator may appear either before or after the variable's name. If it appears before the name, the operation is performed and its result is used by the next operation (the result is a variable reference in this case).
Source: Variables and Expressions - Definition & Usage | AutoHotkey v2
++d is evaluated and the result is d itself, as documented. As in some other languages, it is unspecified exactly when d will be evaluated/dereferenced. What you are expecting is for the left-hand variable in ++d + ++d to be dereferenced before the right-hand sub-expression is evaluated. It could be argued that doing so would contradict or remove any meaning from "the result is a variable reference".If an assignment is used as the input for some other operator, its value is the variable itself.
Source: Variables and Expressions - Definition & Usage | AutoHotkey v2
It is the same with [d, ++d] or any function call where a variable is modified as a side-effect of evaluating the parameters.
In v1, it is the means by which d or ++d can be passed to a ByRef parameter, by reference. In v2 that particular excuse doesn't apply, because &d must be used for ByRef.
In the current implementation (and this should not be taken as any kind of guarantee), a variable is not dereferenced before becoming input to an operator or function. The variable itself is the input, and the operator or function dereferences the variable if that is what it is designed to do. An operator will use whatever value the variable has when the operator is evaluated, not the value one operand had before the other operand was evaluated. This is consistent across all operators, so for instance, &++x takes a variable reference, (++x) /= 2 increments and then halves, and ++x + ++x does what it does.
Suppose that ++x resulted in the value of x when the next operator doesn't need a variable. In v2 there's no expectation that f(++x) will pass x by reference, so this would be reasonable; x:=0, [++x, ++x] could result in [1, 2], as you'd likely expect. x+=1 should behave the same as ++x, and maybe you would have the same expectations of it anyway. All compound assignments should behave consistently, so for instance, x:=1, [x *= 3, x <<= 2] should result in [3, 12]. This is all feasible so far, without sacrificing performance or other things.
But there's also .= and not just compound assignment, but := as well. For instance, a:="A", f(a, a:="B") should call f("A", "B"); but in order to do that, it needs to copy the string contained by a. This is implied by the fact that a variable has "string capacity" and an "internal string buffer". To limit the performance impact to just the necessary situations, more complexity is needed.
That could be in the form of more complex analysis at load-time to determine whether side-effects of an expression may alter a variable before its value will be used, in order to avoid copying when possible. This could be either very difficult or somewhat ineffective, as functions called by the expression might indirectly cause a variable's value to change. If we err on the side of caution and simplicity, and assume any function call could modify any variable, strings would still be copied unnecessarily.
Or it could be by changing how strings are implemented, such as to use reference-counted strings. More complexity is needed to preserve backward-compatibility. For instance, using StrPtr(x) or VarSetStrCapacity(&x) might imply that the string must be copied rather than referenced. There are also several different ways strings are represented in the current implementation, and the code mostly lacks the kind of abstraction that would facilitate this type of change. Over time, I have taken some opportunities to make the code more ready for this, and intend to do it eventually.
Aside from strings, there is also objects. If a variable reference evaluates to an object, a counted reference to the object must be held; otherwise f(a:=[], a:={}) would either pass the same object to both parameters, or pass a dangling pointer to the first parameter. This means an additional AddRef and Release, but it's probably nothing compared to the open-ended cost of copying a string. It probably should be done for other reasons anyway; for instance, f(Buffer(1).ptr, a := 2) is fine because the temporary object is guaranteed to be released only after the expression completes, but currently a:=Buffer(1), f(a.ptr, a := 2) won't work because a := 2 has the side-effect of deleting the object.
Re: Math syntax parsing issue
I appreciate all of these details (understood a couple of them! ).
My question: does the following script show the values that you would have predicted?
My question: does the following script show the values that you would have predicted?
Code: Select all
#Requires AutoHotkey v2.0
d := 1
MsgBox ++d + ++d + d
d := 1
MsgBox ++d + d + ++d
Re: Math syntax parsing issue
Yes.
They give different results because the two sub-expressions of the first + are evaluated, and their side-effects carried out, before the third sub-expression is evaluated. The result of the first + is a number, not a variable, so it is unaffected by the additional ++d in the second case.
They give different results because the two sub-expressions of the first + are evaluated, and their side-effects carried out, before the third sub-expression is evaluated. The result of the first + is a number, not a variable, so it is unaffected by the additional ++d in the second case.
Re: Math syntax parsing issue
Thanks for the in-depth explanation lexikos. I've certainly moved on to writing less ambiguous expressions, and it's interesting to see the inner workings of AHK explained, and see possible future trajectories for its development.
« AHK Portable Installer » | « CallTipsForAll » | « TheArkive AHK v1 Scripts » | « TheArkive AHK v2 Scrpts » | « TheArkive on GitHub »