AutoHotkey Homepage AutoHotkey Community
Let's help each other out
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Unexpected Result (left to right paramater passing)
Goto page Previous  1, 2, 3, 4, 5  Next
 
Post new topic   Reply to topic    AutoHotkey Community Forum Index -> Bug Reports
View previous topic :: View next topic  
Author Message
Titan



Joined: 11 Aug 2004
Posts: 5068
Location: imaginationland

PostPosted: Thu Sep 27, 2007 12:39 pm    Post subject: Reply with quote

I may have read defensive but that wasn't my intent, sorry.
_________________

RegExReplace("irc.freenode.net/ahk", "^(?=(.(?=[\0-r\[]*((?<=\.).))))(?:[c-\x73]{2,8}(\S))+((2)|\b[^\2-]){2}\D++$", "$u3$1$3$4$2")
Back to top
View user's profile Send private message Visit poster's website
Laszlo



Joined: 14 Feb 2005
Posts: 4016
Location: Pittsburgh

PostPosted: Thu Sep 27, 2007 12:51 pm    Post subject: Reply with quote

Xander wrote:
proclaim that:

i, ++i, j-- * k

is bad style!

Especially since it is in the documentation that comma separated list of expressions are evalutated from left to right…
AHK would unfortunately be a language that violates the Principle of Least Astonishment, hence the function name SurpriseMe.

Titan wrote:
function parameters aren't evaluated as multi-statements when they should be.
They are very different things. Function parameters are syntactically different, they are converted to implicit assignments, they have default values, etc. If you want function parameters to be evaluated from left-to-right, post it in the Whish list.

As I said repeatedly, the documentation does not specify the evaluation order, and having a different order than what you like, is not a bug.
Back to top
View user's profile Send private message
majkinetor



Joined: 24 May 2006
Posts: 3626
Location: Belgrade

PostPosted: Thu Sep 27, 2007 1:51 pm    Post subject: Reply with quote

It shouldn't be like that anyway.
This shold be fixed.
_________________
Back to top
View user's profile Send private message MSN Messenger
Laszlo



Joined: 14 Feb 2005
Posts: 4016
Location: Pittsburgh

PostPosted: Thu Sep 27, 2007 4:07 pm    Post subject: Reply with quote

majkinetor wrote:
It shouldn't be like that anyway..
If you mean, the parameter evaluation order should be specified in the AHK documentation, I agree. The evaluation order of sub-expressions could also be specified, otherwise the result of expressions like i+i++ is undefined, as already discussed a couple of times. Post it to the Wish list! There is no bug here.
Back to top
View user's profile Send private message
Xander



Joined: 23 Sep 2007
Posts: 142

PostPosted: Thu Sep 27, 2007 5:42 pm    Post subject: Reply with quote

Laszlo wrote:
Titan wrote:
function parameters aren't evaluated as multi-statements when they should be.
They are very different things. Function parameters are syntactically different, they are converted to implicit assignments, they have default values, etc.

Syntactically different? I don't see why you think an assignment makes such a big deal. In the example given in the documentation of "list of expressions", three of the four so-called expressions are assignments! Perhaps one or both of y+=2 and ++index are not caught by the untrained eye as assignments but they are.
Back to top
View user's profile Send private message
majkinetor



Joined: 24 May 2006
Posts: 3626
Location: Belgrade

PostPosted: Thu Sep 27, 2007 5:43 pm    Post subject: Reply with quote

I don't really care how do you call it. Bug or not, this system is bug prone.

The problem is apperent - if other languages do it one way and AHK another, that is not good, especialy if we take into account C orientation in expressions.
_________________
Back to top
View user's profile Send private message MSN Messenger
Xander



Joined: 23 Sep 2007
Posts: 142

PostPosted: Thu Sep 27, 2007 5:50 pm    Post subject: Reply with quote

Sean wrote:
It doesn't prove anything, just a guess.
It may be done this way to ease the preparation of the stack.
Notice the addresses of parameters.

Code:
Test(1,2,3,4)

Test(prm1, prm2, prm3, prm4){
   MsgBox, % &prm1 . "|" . &prm2 . "|" . &prm3 . "|" . &prm4
}

probably just means the 4 parameter addresses are grabbed as a group. Says nothing about which order they are assigned their values.
Back to top
View user's profile Send private message
Sean



Joined: 12 Feb 2007
Posts: 1338

PostPosted: Thu Sep 27, 2007 11:20 pm    Post subject: Reply with quote

Xander wrote:
probably just means the 4 parameter addresses are grabbed as a group. Says nothing about which order they are assigned their values.

I didn't claim that the assignments are really done in reverse order, which doesn't explain your second example, then.

Anyway, try this.

Code:
test := 0
MsgBox, % &test . "`n"
   . Test(1,1,1,1)
   . Test(1234,1234,1234,1234)
   . Test(12345678,12345678,12345678,12345678)

Test(prm1, prm2, prm3, prm4){
   Return   &prm4 . "|" . &prm3 . "|" . &prm2 . "|" . &prm1 . "`n"
}


To me, it seems two-stage operations. (again, a mere guess)
1) pre-evaluation (in left-to-right order)
2) final assignment (in right-to-left, i.e., reverse, order)

But, in the first pre-evaluation stage, AHK doesn't fully evaluate all the expressions, maybe for performance or for ByRef parameters. I mean, if the parameter is a variable, AHK doesn't dereference it at this stage, just keep the reference to the variable.

Another example:

Code:
Test(test.=1234,test.=5678)

Test(prm1, prm2){
   MsgBox, % prm1 . "|" . prm2 . "`n"
      . &prm1 . "|" . &prm2
}
Back to top
View user's profile Send private message
Xander



Joined: 23 Sep 2007
Posts: 142

PostPosted: Fri Sep 28, 2007 3:16 am    Post subject: Reply with quote

Sean wrote:

Anyway, try this.

Code:
test := 0
MsgBox, % &test . "`n"
   . Test(1,1,1,1)
   . Test(1234,1234,1234,1234)
   . Test(12345678,12345678,12345678,12345678)

Test(prm1, prm2, prm3, prm4){
   Return   &prm4 . "|" . &prm3 . "|" . &prm2 . "|" . &prm1 . "`n"
}


To me, it seems two-stage operations. (again, a mere guess)
1) pre-evaluation (in left-to-right order)
2) final assignment (in right-to-left, i.e., reverse, order)


I don't understand how you are getting evaluation/assignment order based on memory addresses.

All needed memory addresses needed in a statement should be grabbed before any evaluations in the statement. Their order probably has more to do with how available memory addresses are retrieved.

Sean wrote:
But, in the first pre-evaluation stage, AHK doesn't fully evaluate all the expressions, maybe for performance or for ByRef parameters. I mean, if the parameter is a variable, AHK doesn't dereference it at this stage, just keep the reference to the variable.

I think you are close here. Did you see my example in a prior post? If there is evaluation involved, those are done first. Then anything that is just being passed as the value of a variable is assigned. I cannot think of any good reason to do it this way. It certainly can't be faster or anything, all the same operations must be done regardless. In fact it probably introduces a slowdown somewhere as it is necessary to check if an evaluation is required or not and reorder things.
Back to top
View user's profile Send private message
Sean



Joined: 12 Feb 2007
Posts: 1338

PostPosted: Fri Sep 28, 2007 3:38 am    Post subject: Reply with quote

Xander wrote:
I don't understand how you are getting evaluation/assignment order based on memory addresses.

Let's see if others think the same as you on the result of my example.
Anyway, it's not a real proof as I said, however, a highly likely evidence IMO.

Quote:
If there is evaluation involved, those are done first.

Looks like you're using the term evaluation slightly differently from me here.
My usage of it also includes dereferencing the variables too in this case.

Quote:
I cannot think of any good reason to do it this way.

Assuming my guess about the two-stage operation is correct, IMO, the final assignment stage may be termed more accurately as the stack preparation.
Back to top
View user's profile Send private message
Xander



Joined: 23 Sep 2007
Posts: 142

PostPosted: Fri Sep 28, 2007 4:16 am    Post subject: Reply with quote

Sean wrote:
Assuming my guess about the two-stage operation is correct, IMO, the final assignment stage may be termed more accurately as the stack preparation.

Is there a good reason to do a two stage process? If I am understanding you correctly anything that requires an operation is done,
then the variables are dereferenced.

Take for example:

index = 1
doSomething(index, ++index, index/2)

becomes

[operation stage]
a = ++index
b = index/2

[dereference stage]
p1 = index
p2 = a
p3 = b
doSomething(p1, p2, p3)
Back to top
View user's profile Send private message
Sean



Joined: 12 Feb 2007
Posts: 1338

PostPosted: Fri Sep 28, 2007 5:03 am    Post subject: Reply with quote

Xander wrote:
Is there a good reason to do a two stage process?

I don't really know. I don't even know if it's really done in two stage.
Don't get me wrong. What I have told so far were about what I observed and guessed, not about my opinion how things should be done.
I can guess further why it's been done this way, but I think better wait for the reply from Chris.
One thing though. Some operation in the reverse-order is inevitable, as the stack should be filled with the parameters, pointers to the strings of actual parameters in AHK case, in reverse order, unless AHK implements its own operation to reorder.

Quote:
If I am understanding you correctly anything that requires an operation is done, then the variables are dereferenced.

Again, I didn't say it should be done this way. My opinion on this is that the dereference of the variables should be done too in the first stage, not in the second stage. However, I understand it could really slow down the operations if the variable holds very large string, and simply be a wrong operation if the corresponding parameter is of ByRef.

I think it's a consequence that AHK really treats the parameters as mere comma separated expressions (in the first stage).

Code:
test.=1234, test.=5678

In this mere comma separated expression, dereferencing the variable test after assignment is really meaningless.
Back to top
View user's profile Send private message
Lexikos



Joined: 17 Oct 2006
Posts: 2558
Location: Australia, Qld

PostPosted: Fri Sep 28, 2007 3:45 pm    Post subject: Reply with quote

Xander wrote:
I don't understand how you are getting evaluation/assignment order based on memory addresses.
Perhaps a more straight-forward test would be:
Code:
f(p(1),p(2),p(3),p(4))

f(a,b,c,d) {
  msgbox f(%a%,%b%,%c%,%d%)
}
p(n) {
  msgbox param %n%
  return n
}
The message boxes show the order: 1, 2, 3, 4.
Sean wrote:
Xander wrote:
Is there a good reason to do a two stage process?

I don't really know. I don't even know if it's really done in two stage.
It is, in the sense that value -> parameter assignment is done after (and is distinctly separate from) expression evaluation. I've spent several hours going over Line::ExpandExpression(), which does all the work. (I still don't understand it fully...)
Quote:
But, in the first pre-evaluation stage, AHK doesn't fully evaluate all the expressions, maybe for performance or for ByRef parameters.
I think it would be more accurate to say that:
  • AHK fully evaluates each expression, pushing each result onto the stack,
  • then assigns these results to the parameters (represented by variables) in right-to-left order (i.e. starting with the value most recently pushed onto the stack.)
The issue is that an expression consisting solely of a variable name results in a reference to - not the value of - the variable. (Actually, the same applies to assignments, like index+=1.)
Quote:
However, I understand it could ... simply be a wrong operation if the corresponding parameter is of ByRef.
As (it seems) you've concluded, ByRef parameters rely on the aforementioned behaviour.


By the way, 'return' behaves in a similar way when using multi-expressions:
Code:
msgbox % f(1)
f(i) {
  return i, ++i  ; returns 2
  ;return i+0, ++i  ; returns 1
}
Back to top
View user's profile Send private message
Laszlo



Joined: 14 Feb 2005
Posts: 4016
Location: Pittsburgh

PostPosted: Fri Sep 28, 2007 4:18 pm    Post subject: Reply with quote

Why is relying on side effects in function parameters is bad style?
- It makes the code non-portable, hard to understand and document, difficult to optimize
- It could make the compiler/interpreter slower or larger.

If a piece of code does not rely on side effects, any parameter evaluation order gives the same result. Good programming style does not depend on parameter evaluation order.

Why is requesting a specific parameter evaluation order possibly too limiting?

- There are languages, where you can enter an expression as a parameter, and it will be newly evaluated each time it is used inside the function. Like an inline function definition. These parameters should NOT be evaluated at entering the function (call), so a fixed evaluation order precludes this useful feature forever. Like sum(i:=2,i<=10,i+=2,i**2) could compute the sum of the first 5 even squares.

- Lazy evaluation could prevent run-time errors. Like this:
Code:
Select(x,sqrt(x),1/x,0)
Select(x,a,b,c) {
   Return x > 0 ? a : (x < 0 ? b : c)
}
It will not get in trouble with sqrt(-1) or 1/0.

- Lazy evaluation could save a lot of memory and execution time, not evaluating complex expressions in parameters, which are not actually used.

A fix parameter evaluation order would necessitate complex if-then-else statements or ternary operators, outside of the function calls.

AHK leaves open the possibility to implement these features, by not specifying the parameter evaluation order. It is important for a fast evolving language, and relying on undocumented features could break your code at the next AHK release, without you knowing the cause. (Changes of documented features get documented, so you would know what hit you.)
Back to top
View user's profile Send private message
Laszlo



Joined: 14 Feb 2005
Posts: 4016
Location: Pittsburgh

PostPosted: Fri Sep 28, 2007 4:36 pm    Post subject: Reply with quote

...Nevertheless, you can experiment also with a version of lexikos' script, to figure out the current AHK behavior (which you must not rely on):
Code:
f(p(1),p(2),p(3))
Msgbox %order% ; 1 2 3
order =
g(a:=p(1),b:=p(2),c:=p(3))
Msgbox %order% ; 1 2 3
order =
i = 0
f(p(i++),p(++i),p(i))
Msgbox %order% ; 0 2 2

f(a,b,c) {
}
g(a,ByRef b,c) {
}
p(n) {
  Global order
  order .= n . "  "
}
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    AutoHotkey Community Forum Index -> Bug Reports All times are GMT
Goto page Previous  1, 2, 3, 4, 5  Next
Page 2 of 5

 
Jump to:  
You can post new topics in this forum
You can reply to topics in this forum


Powered by phpBB © 2001, 2005 phpBB Group