Page 1 of 2

[a103]Unfortunate collision of a few things

Posted: 08 Jul 2019, 15:20
by nnnik
AutoHotkey v2 allows the calling of functions in command style.
AutoHotkey v2 throws if a function receives a bad parameter count
AutoHotkey v2 has no real way of differentiating between a multi-expression comma and command list in this case
AutoHotkey v2 apparently evaluates return and similar control flow statements as functions being called in command style and verifies their parameter count before the script starts.

The combination of this leads to very suprising behaviour when combining multi-expression comma with control statements in command style mode.
The code:

Code: Select all

Msgbox "Hello World"
fn()
fn() {
	return a := 0, b := 1
}
Will throw the error:

Code: Select all

"Return" accepts at most 1 parameter.
     Specifically: return a := 0, b := 1
I couldn't really find a way to fix it but Im about 90% sure it relates to this:
https://github.com/Lexikos/AutoHotkey_L/blob/alpha/source/script.cpp#L9068

Re: [a103]Unfortunate collision of a few things

Posted: 08 Jul 2019, 15:42
by HotKeyIt
return (a := 0, b := 1) or return (b := 1, a := 0) depending on what you want to return.

Re: [a103]Unfortunate collision of a few things

Posted: 08 Jul 2019, 15:53
by nnnik
Yeah I know how to circumvent the behaviour - the error shouldn't appear - even if it should throw an error the error should indicate that return is not a function.

Re: [a103]Unfortunate collision of a few things

Posted: 08 Jul 2019, 16:20
by HotKeyIt
If I remember correct from the changes that is how it should be.
The error also does say properly that only one parameter is allowed for return but I remember it was not obvious for me because I am used to do it like this.
Probably error should also say:

Code: Select all

"Return" accepts at most 1 parameter.
     Specifically: return a := 0, b := 1
         Consider: return (a := 0, b := 1)

Re: [a103]Unfortunate collision of a few things

Posted: 08 Jul 2019, 16:58
by nnnik
So this is just bad language design then?

Re: [a103]Unfortunate collision of a few things

Posted: 08 Jul 2019, 18:05
by HotKeyIt
I would not call it bad.
I think it makes it easier for the parser to have clear rules.

Re: [a103]Unfortunate collision of a few things

Posted: 09 Jul 2019, 00:51
by Helgef
This is intendent and documented,
expressions wrote: Comma is also used to delimit the parameters of a function call or control flow statement.

AutoHotkey v2 apparently evaluates return and similar control flow statements as functions being called in command style and verifies their parameter count before the script starts.
This is not the case.
I couldn't really find a way to fix it but Im about 90% sure it relates to this:
https://github.com/Lexikos/AutoHotkey_L/blob/alpha/source/script.cpp#L9068
It does not.

Cheers

Re: [a103]Unfortunate collision of a few things

Posted: 09 Jul 2019, 01:53
by swagfag
speaking of bad language design, this pattern return a := 0, b := 1 and any variations thereof should be verboten

Re: [a103]Unfortunate collision of a few things

Posted: 09 Jul 2019, 02:12
by Helgef
It looks like returning multiple values, which it is implicitly reserved for, by being verboten.

Cheers.

Re: [a103]Unfortunate collision of a few things

Posted: 09 Jul 2019, 02:44
by nnnik
Then what about if a,b and similar?
speaking of bad language design, this pattern return a := 0, b := 1 and any variations thereof should be verboten
Thats personal preference. , is a multi-statement operator and can be used in any expression.
If return cannot handle this operator return is simply unable to handle expressions. I will promote the general use of return () in all cases to circumvent this behavior.
There was a good reason I needed this:

Code: Select all

			try 
				return (thisLine := exception(""), Object(targetObjPointer).%fnName%(params*))
			catch e
				if (thisLine.file == e.file && thisLine.line == e.file && thisLine.what == e.file)
					throw exception(e.message, -1, e.extra)
			else
				throw e
This is a highly suprising little detail in AHK v2 - not really a bug though you are right.
There probably is a better solution to this.
I know that AHKs v2 syntax and generally documentation are in a dysfunctional state right now but this is a bit extreme imho.
I got a request about porting a library of mine to the current v2 version - I'm not convinced I can fulfill that request.

Re: [a103]Unfortunate collision of a few things

Posted: 09 Jul 2019, 02:56
by Helgef
Then what about if a,b and similar?
It is also prohibited.

Take Loop Files FilePattern [ , Mode] as an example, do you think that for the last parameter, Mode which also takes an expression, it should be allowed to do Mode, expr1, ..., exprN? That would pass exprN as the Mode parameter, and if it wasn't intended it couldn't be detected.

Cheers.

Re: [a103]Unfortunate collision of a few things

Posted: 09 Jul 2019, 03:09
by nnnik
Loop Files, FilePattern does not exist in AHK v2 as far as Im concerned and even if it does it should not limitate actual valid useable syntax.

Re: [a103]Unfortunate collision of a few things

Posted: 09 Jul 2019, 03:30
by swagfag
i dont know what if a,b is meant to do(which coincidentally also happens to be the reason for my personal preference to verbot all constructs of this type)
if u can rewrite it, for lack of a better term, the normal way, then this is how it should be written. i dont think there exists a case where u absolutely couldnt rewrite it, and the only way to achieve what u wanted to do would be to employ one of these constructs. do u know of cases like these?

I will promote the general use of return ()
please, dont. return does just fine with expressions. there is no reason for

Code: Select all

fn() {
	return (a := 0, b := 1)
}
to be written like this or like this

Code: Select all

fn() {
	return (
		a := 0,
		b := 1
	)
}
instead of like this

Code: Select all

fn() {
	a := 0
	return b := 1
}
other than "u wanted to save lines". i could maybe see the point for some supertrivial examples like fn() => (a := 0, b := 1), but lets be real, we know there arent gonna be supertrivial ever
what was wrong with just writing

Code: Select all

try
	return Object(targetObjPointer).%fnName%(params*)
catch e
{
	thisLine := exception("")

	if (thisLine.file == e.file && thisLine.line == e.file && thisLine.what == e.file)
		throw exception(e.message, -1, e.extra)
	else
		throw e
}

Re: [a103]Unfortunate collision of a few things

Posted: 09 Jul 2019, 03:53
by nnnik
I try to propagate errors that appear to target the line:
return Object(targetObjPointer).%fnName%(params*)
upwards to the caller of this function. But to do that I first need to identify if the thrown exception targets the line.
To do that I create an exception object with the exception function on the same line.
That should explain why neither

Code: Select all

fn() {
	return (
		a := 0,
		b := 1
	)
}
nor

Code: Select all

fn() {
	a := 0
	return b := 1
}
are an option.

Code: Select all

try
	return Object(targetObjPointer).%fnName%(params*)
catch e
{
	thisLine := exception("")

	if (thisLine.file == e.file && thisLine.line == e.file && thisLine.what == e.file)
		throw exception(e.message, -1, e.extra)
	else
		throw e
}
is completely unrelated and always executes the same as:

Code: Select all

return Object(targetObjPointer).%fnName%(params*)

Re: [a103]Unfortunate collision of a few things

Posted: 09 Jul 2019, 04:13
by Helgef
Note that, in

Code: Select all

fn() {
	return (
		a := 0,
		b := 1
	)
}
return (, a := 0,, b := 0, and ) are all on the same line (line 2 in this case).

Cheers.

Re: [a103]Unfortunate collision of a few things

Posted: 09 Jul 2019, 04:21
by nnnik
Im 100% not gonna rely on that.
What if AHK actually finally decides that it is better to throw errors on the lines the code it is written on not the internal "line" model.

Re: [a103]Unfortunate collision of a few things

Posted: 09 Jul 2019, 05:59
by guest3456
nnnik wrote:
09 Jul 2019, 02:44
Then what about if a,b and similar?
speaking of bad language design, this pattern return a := 0, b := 1 and any variations thereof should be verboten
Thats personal preference. , is a multi-statement operator and can be used in any expression.
If return cannot handle this operator return is simply unable to handle expressions.
i agree with this^

do these things handle expressions or not?

but i guess it comes down to precedence, does a func call like Func(a := 1, b: = 1) pass two params? or does it pass one param with the multi-statement comma operator?

and lets just get rid of this bullshit command-like syntax

Re: [a103]Unfortunate collision of a few things

Posted: 09 Jul 2019, 06:10
by Helgef
It is not a multi-statement comma when used directly inside a parameter list, neither for a function nor a control flow statement, as documented. Again,
expressions wrote: Comma is also used to delimit the parameters of a function call or control flow statement. To include a multi-statement expression in a parameter list, enclose it in an extra set of parentheses. For example, MyFn((x, y)) evaluates both x and y but passes y as the first and only parameter of MyFn.
Cheers.

Re: [a103]Unfortunate collision of a few things

Posted: 09 Jul 2019, 09:58
by nnnik
control flow statement and parameter list doesn't belong together.
Especially not for return, if etc.

Re: [a103]Unfortunate collision of a few things

Posted: 09 Jul 2019, 14:14
by swagfag
im not sure i fully understand what u meant by exceptions which "appear to target the line". do u mean exceptions generated by the line Object(targetObjPointer).%fnName%(params*)? that is, not an object exception(thrown by Object(ptr), although im not sure either whether this would ever throw. if a bad/notanobject ptr is passed in, the script would crash) and nonexistent method(thrown by .%fnName%()) exception?
if so, wouldnt the solution be to push for better introspection facilities rather than making return work with multiple statements, eg:

Code: Select all

obj := Object(targetObjPointer)
if !obj.HasMethod(fnName)
	throw exception('method not found', -1, fnName)

return obj.%fnName%(params*)

guest3456 wrote:
09 Jul 2019, 05:59
and lets just get rid of this bullshit command-like syntax
+1