Page 1 of 2

Break, continue - allow expression mode

Posted: 01 Jul 2014, 05:40
by trismarck
A similar functionality was requested in the past by HotkeyIt here.

When 'exiting' from a _function_, it _is_ possible to use the expression mode with return:

Code: Select all

fun() {
	; do something
	return, this, a+b, c*d, Errorlevel := 0
}
When 'exiting' from a _loop_ (by using either break or continue), it is _not_ possible to use the expression mode with break - a line before break has to be added to evaluate any expression prior to 'exiting' from the loop:

Code: Select all

Loop,
	if(a = b) {
		c++ ; <--
		break
	}
Often times, break is inside of an if() statement. Because the expression can't be in the same line where the command break is, brackets have to be used with the if() statement.

Code: Select all

Loop,
	if(a = b) { ; <--
		c++
		break
	} ; <--
If break would allow expression mode (like return already does), the four-line if() statement above could be converted to just two lines:

Code: Select all

Loop,
	if(a = b)
		break, , c++

Re: Break, continue - expression mode

Posted: 01 Jul 2014, 05:57
by tank
Sounds like a distinction without a difference. I can't think of any language where break/continue operate on an expression. I am not saying anything bout the value of doing it , only that no where else has that value made it into a language

Return exists within a function to send a result back to the caller. It for this reason accepts an argument. Notice that return outside a function will not accept argument.

Re: Break, continue - expression mode

Posted: 01 Jul 2014, 05:59
by HotKeyIt
I added breakif and continueif in AutoHotkey_H but then noticed that AutoHotkey v2 supports one line if statement which is even better :D

Code: Select all

Loop
  If (A_Index < 10), continue
  else if (20 > i:=A_Index), break
I left it in AutoHotkey_H v1, so you can do:

Code: Select all

Loop {
  continueif A_Index<10
  breakif (20 > i:=A_Index)
}

Re: Break, continue - expression mode

Posted: 01 Jul 2014, 06:50
by trismarck
Tank wrote:Sounds like a distinction without a difference. I can't think of any language where break/continue operate on an expression. I am not saying anything bout the value of doing it , only that no where else has that value made it into a language
Yes, I should have been more clear: the first parameter of break is _not_ an expression. The first parameter is a _constant_ that is either empty, a number or a string. What I'm after is to _leave_ the first parameter of break as it is now and just allow an expression to be the second, non-existent parameter of break.
As for the functionality of break in other languages - we could be the pioneers in doing that :D .
Tank wrote:Return exists within a function to send a result back to the caller. It for this reason accepts an argument. Notice that return outside a function will not accept argument.
Didn't know that, thanks. Not sure if it's a good idea to allow expressions be part of return outside of functions (at first glance, nothing _bad_ would happen).
HotKeyIt wrote:

Code: Select all

Loop
  If (A_Index < 10), continue
  else if (20 > i:=A_Index), break

Code: Select all

Loop {
  continueif A_Index<10
  breakif (20 > i:=A_Index)
}
That I like.

Could something like this be added too? :

Code: Select all

If (A_Index < 10), continue
else if (20 > A_Index), break, , i := A_Index
If A_Index less than 20, break and set a few variables along the way.

Re: Break, continue - allow expression mode

Posted: 01 Jul 2014, 07:19
by Coco
trismarck wrote:Perhaps this could be implemented then:

Code: Select all

If (A_Index < 10), continue
else if (20 > A_Index), break, , i := A_Index
If A_Index less than 20, break and set a few variables along the way.
Well, you can already do this if you put it in a block. There is no real benefit other than one-liner statement...
If you're after shorter, one-liner statement(s), I'd rather have:

Code: Select all

if (A_Index > 20) { i := A_Index; some_var := some_value; break }

Re: Break, continue - allow expression mode

Posted: 01 Jul 2014, 07:27
by Coco
Workaround:

Code: Select all

b := "Hello World"
Loop {
	if (A_Index > 10 && dummy:=(true, i:=A_Index, a:=b))
		break
}
MsgBox %i%
MsgBox %a%

Re: Break, continue - allow expression mode

Posted: 01 Jul 2014, 08:01
by tank
ok so i want to understand something
the entire purpose is to reduce lines of code and not use handlebars {}
trismarck wrote:What I'm after is to _leave_ the first parameter of break as it is now and just allow an expression to be the second, non-existent parameter of break.
Break accepts a label reference not just any string or integer. a distinction WITH a difference
Hotkeyit is using an expression to operate break/continue a distinction AND a difference
your OP
trismarck wrote:If break would allow expression mode (like return already does), the four-line if() statement above could be converted to just two lines:
Code: [Select all] [Expand/Collapse] [Download] (Untitled.txt)
Loop,
    if(a = b)
        break, , c++
seems to indicate you just want to execute an unrelated expression on the same line?

Re: Break, continue - allow expression mode

Posted: 01 Jul 2014, 08:11
by trismarck
Tank wrote:seems to indicate you just want to execute an unrelated expression on the same line?
Yes, that's exactly the case. Just like with return.

Re: Break, continue - allow expression mode

Posted: 01 Jul 2014, 08:22
by trismarck
To clarify: I _don't_ want the _result_ of the evaluation of the expression being the non-existent second parameter of break to trigger the break or not. Moreover I'd say that that would be impossible by design. I just want to evaluate some expression before break exits the loop. Just like it is already possible to evaluate an expression before return exits the function.

Re: Break, continue - allow expression mode

Posted: 01 Jul 2014, 08:28
by tank
So then one solution would also be to allow break to operate in multistatement
thus would not offer a second parameter to break but instead offer this

Code: Select all

c=0
a=1
b=1
loop 5
	if (a = b)
		++c, break
msgbox % c
Unfortunately break seems to only operate when it is the only statement on the line of code so either IEA requires code change
sidenote: if this were allowed almost every function Sean ever wrote would have been 3 lines func name and opening handlebar 1 long statement and a closing handlebar. cause that fella abused multistatement for performance

Re: Break, continue - allow expression mode

Posted: 01 Jul 2014, 08:41
by Coco
tank wrote:sidenote: if this were allowed almost every function Sean ever wrote would have been 3 lines func name and opening handlebar 1 long statement and a closing handlebar. cause that fella abused multistatement for performance
:lol:
@trismarck:
See workaround above, if you are after shorter code... there'll be a slight performance hit though due to the evaluation+object Edited: removed usage of object

Re: Break, continue - allow expression mode

Posted: 01 Jul 2014, 08:46
by trismarck
To clarify further: (from the point of view of AHK _1.1_)
Tank wrote:Unfortunately break seems to only operate when it is the only statement on the line of code so either IEA requires code change
At compile time, when Autohotkey parses each line of the script, Autohotkey determines, if the line of the script is:
  • one of the predefined commands or whether the line is
  • an expression or
  • something else I have no idea about
(lets say this happens after continuation sections were processed).
Because of the following limitation: for a given line of code to be interpreted as a _command_, that line of code has to _start_ with the name of the command, a given line of code _can't_ start with an _expression_ and at the same time be followed with a _command_ - as it is the case here:

Code: Select all

        ++c, break
The command has to be the first 'token' of the line:

Code: Select all

Break, ++c
Note also that I don't know how Autohotkey _2_ works in this context.
Tank wrote: sidenote: if this were allowed almost every function Sean ever wrote would have been 3 lines func name and opening handlebar 1 long statement and a closing handlebar. cause that fella abused multistatement for performance
Yes, I've seen that. I guess the only thing Sean was concerned about was the 512 token limitation :lol: .

Re: Break, continue - allow expression mode

Posted: 01 Jul 2014, 08:52
by tank
Coco the problem with adding something like that is that it complicates the If and must be certain to evaluate as true or false or else it affects the logic. In addition this isnt about a conditional break/continue its about being able to execute an unrelated expression same line as the break without the curly braces

@trismarck
there are already exceptions to that with many of the window functions can be executed on same line without being so called tokens of each other. But your right it does open a rather dangerous precedent. by not making the statement part of break/continue it would continue to draw a need for other exceptions

How would multiple expressions be handled by your idea?

Re: Break, continue - allow expression mode

Posted: 01 Jul 2014, 09:21
by trismarck
Tank wrote:How would multiple expressions be handled by your idea?
In case of return, the first parameter can be an expression. Because of that, it is possible to just add a sub-expression separator (a comma) and evaluate whatever is needed (as 'yet another' sub-expression). I'd like to have the same functionality for break. What I want would have been already possible with break if expression mode was allowed for the first parameter of break. This isn't the case - the first parameter of the break command _has to_ be a constant (a constant that is the name of the existing label / a number that identifies one of the nested Loop statements).
Coco wrote:

Code: Select all

b := "Hello World"
Loop {
   if (A_Index > 10 && dummy:=(true, i:=A_Index, a:=b))
      break
}
MsgBox %i%
MsgBox %a%
Yes, I'd like this to be improved:

Code: Select all

b := "Hello World"
Loop {
   if (A_Index > 10)
      break, , true, i:=A_Index, a:=b
}
MsgBox %i%
MsgBox %a%
To implement this, break could have an implicit second parameter, for which the expression mode is allowed. Then, after the expression is evaluated, break does _nothing_ with the parameter being the result of the evaluation of the expression.

Re: Break, continue - allow expression mode

Posted: 01 Jul 2014, 09:51
by tank
i think i understand your idea now but i would never ever ever write such a line of code even if i could
i mean the point of break is to stop here not to stop here and do these other things first
returns point is to go back to where you came from. with functions to return with a value

Re: Break, continue - allow expression mode

Posted: 01 Jul 2014, 10:34
by Coco
It makes the code look more confusing... no benefit at all except for one-liner multistatements. Why avoid the braces?
From an observer's standpoint:

Code: Select all

b := "Hello World"                       ; assignment
Loop {                                   ; something that repeats a series of commands
    if (A_Index > 10)                    ; condition
        break, , true, i:=A_Index, a:=b  ; ... what's this??
}
MsgBox %i%
MsgBox %a%

Re: Break, continue - allow expression mode

Posted: 01 Jul 2014, 15:55
by trismarck
Tank wrote:I mean the point of break is to stop here not to stop here and do these other things first
returns point is to go back to where you came from. with functions to return with a value
Break is a command. Every command has parameters. Some of the parameters can be expressions. Expressions are evaluated before the command is called. From the point of view of how Autohotkey works, this is perfectly logical I'd say.
Coco wrote:It makes the code look more confusing
Perhaps the reasoning behind creating the forum thread will sort this out. This is what I originally wrote:

Code: Select all

obj := ["aaa", "bbb", "aaa", "ddd", "eee", "aaa"]

for each, val in obj, Count := 0, found := false {
	if(val = "aaa")
		Count++
	if(Count = 3) {
		result := val, found := true
		break
	}
}
MsgBox, % found
I wanted to shorten this up to:

Code: Select all

for each, val in result, Count := 0, found := false {
	if(val = "aaa")
		Count++
	if(Count = 3)
		break, , result := val, found := true
}
In this example, break works as sort of a mini-return from the Loop function and just like it is the case with return, break could _also_ evaluate an expression on the same line, before 'exiting'. Break could be considered a return that doesn't return a value, but that _does_ evaluate an expression before returning. I mean break, similar to return, makes the flow of execution jump to the 'address' where the end of the loop/function call was.

I'd consider the above to be more readable than doing all of the assignments inside of the if() statement:

Code: Select all

for each, val in obj, Count := 0, found := false {
	if(val = "aaa")
		Count++
	if(Count = 3 && (1, result := val, found := true) )
		break
}

Re: Break, continue - allow expression mode

Posted: 01 Jul 2014, 16:24
by HotKeyIt
In v2:

Code: Select all

obj := ["aaa", "bbb", "aaa", "ddd", "eee", "aaa"]
for each, val in (Count := 0, found := false, obj)
    if (val = "aaa" && Count++) && (Count=3 && result:=val && found:=true),break
ListVars
Pause

Re: Break, continue - allow expression mode

Posted: 01 Jul 2014, 19:12
by Coco
trismarck wrote:I'd consider the above to be more readable than doing all of the assignments inside of the if() statement:
That was a workaround to satisfy your need for a shorter code, I wouldn't really use it nor suggest it as a practice.
trismarck wrote:Break is a command. Every command has parameters. Some of the parameters can be expressions. Expressions are evaluated before the command is called. From the point of view of how Autohotkey works, this is perfectly logical I'd say.
Break is more like a control flow statement rather than a command. If it were one, I would expect this to work for v2, but nope, it doesn't...:

Code: Select all

for k, v in ['ABC', 'DEF', 'GHI']
	if (v == 'DEF'), break() ; Command(s) can be called using function syntax -> this throws an error
You can use until in this scenario... nonetheless, I'd rather use braces..

Code: Select all

obj := ["aaa", "bbb", "aaa", "ddd", "eee", "aaa"]

for each, val in obj, Count := 0, found := false {
    if(val = "aaa")
        Count++
} until (Count == 3, result := val, found := true)

MsgBox, % result

Re: Break, continue - allow expression mode

Posted: 01 Jul 2014, 21:07
by lexikos
Coco wrote:It makes the code look more confusing... no benefit at all except for one-liner multistatements.
This.