[a103]Unfortunate collision of a few things

Discuss the future of the AutoHotkey language
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

[a103]Unfortunate collision of a few things

08 Jul 2019, 15:20

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
Recommends AHK Studio
HotKeyIt
Posts: 2364
Joined: 29 Sep 2013, 18:35
Contact:

Re: [a103]Unfortunate collision of a few things

08 Jul 2019, 15:42

return (a := 0, b := 1) or return (b := 1, a := 0) depending on what you want to return.
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: [a103]Unfortunate collision of a few things

08 Jul 2019, 15:53

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.
Recommends AHK Studio
HotKeyIt
Posts: 2364
Joined: 29 Sep 2013, 18:35
Contact:

Re: [a103]Unfortunate collision of a few things

08 Jul 2019, 16:20

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)
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: [a103]Unfortunate collision of a few things

08 Jul 2019, 16:58

So this is just bad language design then?
Recommends AHK Studio
HotKeyIt
Posts: 2364
Joined: 29 Sep 2013, 18:35
Contact:

Re: [a103]Unfortunate collision of a few things

08 Jul 2019, 18:05

I would not call it bad.
I think it makes it easier for the parser to have clear rules.
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: [a103]Unfortunate collision of a few things

09 Jul 2019, 00:51

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
swagfag
Posts: 6222
Joined: 11 Jan 2017, 17:59

Re: [a103]Unfortunate collision of a few things

09 Jul 2019, 01:53

speaking of bad language design, this pattern return a := 0, b := 1 and any variations thereof should be verboten
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: [a103]Unfortunate collision of a few things

09 Jul 2019, 02:12

It looks like returning multiple values, which it is implicitly reserved for, by being verboten.

Cheers.
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: [a103]Unfortunate collision of a few things

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 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.
Recommends AHK Studio
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: [a103]Unfortunate collision of a few things

09 Jul 2019, 02:56

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.
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: [a103]Unfortunate collision of a few things

09 Jul 2019, 03:09

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.
Recommends AHK Studio
swagfag
Posts: 6222
Joined: 11 Jan 2017, 17:59

Re: [a103]Unfortunate collision of a few things

09 Jul 2019, 03:30

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
}
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: [a103]Unfortunate collision of a few things

09 Jul 2019, 03:53

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*)
Recommends AHK Studio
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: [a103]Unfortunate collision of a few things

09 Jul 2019, 04:13

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.
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: [a103]Unfortunate collision of a few things

09 Jul 2019, 04:21

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.
Recommends AHK Studio
guest3456
Posts: 3454
Joined: 09 Oct 2013, 10:31

Re: [a103]Unfortunate collision of a few things

09 Jul 2019, 05:59

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

Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: [a103]Unfortunate collision of a few things

09 Jul 2019, 06:10

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.
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: [a103]Unfortunate collision of a few things

09 Jul 2019, 09:58

control flow statement and parameter list doesn't belong together.
Especially not for return, if etc.
Recommends AHK Studio
swagfag
Posts: 6222
Joined: 11 Jan 2017, 17:59

Re: [a103]Unfortunate collision of a few things

09 Jul 2019, 14:14

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

Return to “AutoHotkey Development”

Who is online

Users browsing this forum: No registered users and 51 guests