fat function in class method changes var outside itsscope

Discuss the future of the AutoHotkey language
User avatar
vvhitevvizard
Posts: 454
Joined: 25 Nov 2018, 10:15
Location: Russia

fat function in class method changes var outside itsscope

20 Jan 2019, 21:07

EDIT: TO SUM UP
1. if fat-arrow returns Func it has to be in assume-local mode! Simple as that.
2. fat-arrow Func ignores local keyword:

Code: Select all

t:="unchanged"
Unix()
msgbox(t)
Unix()=>(local, DllCall("GetSystemTimeAsFileTime", 'int64p',t), t//10000000-11644473600)
3. it doesn't have a proper #Warn LocalSameAsGlobal behavior.
4. declaring methods (and get/set halfmethods) via fat-arrow syntax is undeveloped. We cant just use name()=>: for methods:

Code: Select all

class classname{
		methodname()=>(var:=1)
}
---original post starts here---

Accidentally I found this weird behavior of AHK L v2.
as expected first method func1 doesn't change a variable outside its scope.
but whats going on with the second method func2 defined as fat-arrow method inside the class? Isnt it expected t var to be local here?
Am I missing something?

Code: Select all

t:="not changed"
s1:=class1.func1(), msgbox(t) ;="not changed"
s2:=class1.func2(), msgbox(t) ;="2"
msgbox(s1 " | " s2) ;="1 | 2"

class class1{
	func1(){
		t:=1
		return t
	}
	static func2:=()=>(t:=2)
}

And the syntax - I might be wrong but it feels somewhat inconsistent.
I can write func3()=>(t:=2) as a closure definition inside methods but
outside methods inside class it requires additional := and static word: static func3:=()=>(t:=2)
Last edited by vvhitevvizard on 21 Jan 2019, 22:13, edited 4 times in total.
swagfag
Posts: 6222
Joined: 11 Jan 2017, 17:59

Re: fat function in class method changes var outside itsscope

20 Jan 2019, 21:29

The function is assume-local if it is nested inside another function, otherwise it is assume-global.
User avatar
vvhitevvizard
Posts: 454
Joined: 25 Nov 2018, 10:15
Location: Russia

Re: fat function in class method changes var outside itsscope

20 Jan 2019, 21:39

the way to have it working with fat-arrow definition and w/o changing anything outside the class, I ended up with an additional auto-initializing method:

Code: Select all

Init(){
		static _:=class1.Init()
		this.func2:=()=>t:=2
	}
it requires explicit class name here static _:=class1.Init(). it seems base, this not yet defined at static evaluation time for prototype classes, thus static _:=this.Init() doesnt work as well.

2.
btw, A_ThisFunc inside Init() method says class1.Init at execution time - that's great! But I cant find a way to use it to call the current method at load time. A_ThisFunc.Call(), %A_ThisFunc%(), %A_ThisFunc%.Call(), Func(A_ThisFunc) doesnt work. Whatever I tried, constructions like static _:=Func(A_ThisFunc).Call() wont be evaluated at static vars initialization time (load time).

3.
swagfag wrote:
20 Jan 2019, 21:29
The function is assume-local if it is nested inside another function, otherwise it is assume-global.
Thx for feedback! :D
That's what I tried at first: static func2:=()=>(local t:=2), static func2:=()=>(locals, t:=2)
It doesnt work either :(

4.
I havent notified this behavior before cuz using object properties/methods inside fat-arrow definition doesnt change its behaviour.
Same goes for hack of "allocating" additional local vars via arguments list, working construction is: static func2:=(_,t:=0)=>t:=2 ;uses local t var here, This version is 7% slower tho.

But the following requres 'int64p',t and replacing it with object property makes it a) slower anyways and b) syntax goes wild this.GetAddress("t"), etc

Code: Select all

class time{
		static Unix:=()=>(DllCall("GetSystemTimeAsFileTime", 'int64p',t), t//10000000-11644473600)
}
btw, I understand obj.key returns string not an address, but why dont we have unified syntax here allowing to get address of obj's property with & operator: &obj.key the same way it works with variables?
Last edited by vvhitevvizard on 21 Jan 2019, 02:25, edited 5 times in total.
User avatar
vvhitevvizard
Posts: 454
Joined: 25 Nov 2018, 10:15
Location: Russia

Re: fat function in class method changes var outside itsscope

21 Jan 2019, 00:32

fat arrow definition works great for regular functions and closures inside method/function, it dramatically reduces code size and readability removing redundancy, e.g.:

Code: Select all

gp_SetClipRC(_g, x,y, w,h, _m:=0)=>DllCall("gdiplus\GdipSetClipRect"
		, 'ptr',_g, 'float',x, 'float',y, 'float',w, 'float',h, 'int',_m)
gp_SetClipRegion(_g, c, _m:=0)=>DllCall("gdiplus\GdipSetClipRegion", 'ptr',_g, 'ptr',c, 'int',_m)
gp_RegionCreate()=>(DllCall("gdiplus\GdipCreateRegion", 'uintp',r), r) ;r=region
gp_RegionDel(r)=>DllCall("gdiplus\GdipDeleteRegion", 'ptr',r)
short => syntax beats Python lambda, but when it comes to methods as fat-arrow definitions, convenience of fat-arrow sugar syntax disappears completely. :( And I cant get it why method's vars should be global by default for fat-arrow, a method relying upon a global var is a bad design to say the least.

PS: ofc I'm not an AHK developer and cant realize the whole AHK logic that goes internally. I just share my user experience & expectations. Correct me if I'm wrong
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: fat function in class method changes var outside itsscope

21 Jan 2019, 02:42

Every line that contains the prefix static is executed in global scope before the script fully starts.
Recommends AHK Studio
User avatar
vvhitevvizard
Posts: 454
Joined: 25 Nov 2018, 10:15
Location: Russia

Re: fat function in class method changes var outside itsscope

21 Jan 2019, 03:10

nnnik wrote:
21 Jan 2019, 02:42
Every line that contains the prefix static is executed in global scope before the script fully starts.
Hmm. I see. Well, I use static fat arrow method declarations cuz AHK doesnt allow me to declare methods the way I declare closures.
Fat arrow code itself is not executed at load time, I just assign a fat arrow method to a static object key.
I cant just use name()=>:

Code: Select all

class time{
		Unix()=>(DllCall("GetSystemTimeAsFileTime", 'int64p',t), t//10000000-11644473600)
}
It might be completely different inner logic compared to closures, but a user just wants to shorten method declaration the same way he shortened closure declarations.
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: fat function in class method changes var outside itsscope

21 Jan 2019, 03:42

And I cant get it why method's vars should be global by default for fat-arrow, a method relying upon a global var is a bad design to say the least.
static m := ()=> is not a method definition more than static m := func('f'), it's a class var assignment. The RHS function will exist in the global function name space, if you name it, and there is no hidden this parameter either. The documented way to define a method is to do a full function definition inside the class body.
I cant just use:
Hopefully, this will be allowed in the future. But even then, since you cannot force local in fat arrow directly, if there exist a super global variable t, the t in the method would refer to it.
That's what I tried at first: static func2:=()=>(local t:=2), static func2:=()=>(locals, t:=2)
It doesnt work either
Did you try static func2() => :eggplant: t := 2?
A_ThisFunc wrote:The name of the user-defined function that is currently executing (blank if none)
Cheers.
User avatar
vvhitevvizard
Posts: 454
Joined: 25 Nov 2018, 10:15
Location: Russia

Re: fat function in class method changes var outside itsscope

21 Jan 2019, 04:43

Code: Select all

Did you try [c]static func2() =>t := 2[/c]?
Read carefully above =) some examples I gave r w/o parenthesis. They dont affect anything in this case, but several statements divided by , have to be enclosed in parenthesis so I made a habbit of inserting parenthesis even tho for a single statement fat-arrow function it is not required. :D
Overloaded list of function arguments does the trick (see above) for now by the price of increased CPU load. Yet I cant accept the fat-arrow function to be with global-assume state by default. Its a quirk in my opinion. :D
Helgef wrote:
21 Jan 2019, 03:42
static m := ()=> is not a method definition more than static m := func('f'), it's a class var assignment.
Yes yes those r class keys. :D But whatever it is, it can be called as a function with (). Alternative way of planting those keys would be within New/Init-like methods. W.o static keyword but with this.. I have to resort to this trying to expand fat-arrow feature. W.o overestimation, I managed to reduce code size and line count of some of my projects down by 30%.
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: fat function in class method changes var outside itsscope

21 Jan 2019, 04:56

Well it assumes the scope it is defined in - which in your case is the global scope.
Recommends AHK Studio
User avatar
vvhitevvizard
Posts: 454
Joined: 25 Nov 2018, 10:15
Location: Russia

Re: fat function in class method changes var outside itsscope

21 Jan 2019, 04:57

Helgef wrote:
21 Jan 2019, 03:42
since you cannot force local in fat arrow directly...
Its ok fat-arrow to be restricted in some aspects. Honestly, I just cant fathom the reasons why outside-function fat-arrow declarations were made this way with local vars to be global by default. With AHK v2, we r not bound/restricted by compatibility issues so there r might be some profound restrictions I'm not aware of. Reading Lexikos posts I realize he is reasonable in making decisions. Or it might be just error of omission.
nnnik wrote:
21 Jan 2019, 04:56
Well it assumes the scope it is defined in - which in your case is the global scope.
Ok. Roger that. Tho every [not nested] function in every other language is supposed to have its own scope and there r no exceptions. And declaring fat-arrow outside a function body is supposed to be a function (not closure) declaration.
Lets hope Lexikos just extends fat-arrow support a tad more to cover within class method and half-property get/set declarations. :D
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: fat function in class method changes var outside itsscope

21 Jan 2019, 06:14

Read carefully above =) some examples I gave r w/o parenthesis.
The point is you shouldn't try random stuff, with or without parenthesis, read the documenation.
Honestly, I just cant fathom the reasons why outside-function fat-arrow declarations were made this way with local vars to be global by default.
It is a design choice with both pros and cons. I guess it is assumed that the user more often wants the var in,

Code: Select all

(var)
f := () => var
to be the same variable, and it will be regardless of whether you define the variable and the fat arrow function inside or outside a function.
declaring fat-arrow outside a function body is supposed to be a function (not closure) declaration.
Outside all functions, fat arrow is always a Func, never a Closure.

Cheers.
User avatar
vvhitevvizard
Posts: 454
Joined: 25 Nov 2018, 10:15
Location: Russia

Re: fat function in class method changes var outside itsscope

21 Jan 2019, 06:43

Helgef wrote:
21 Jan 2019, 06:14
Outside all functions, fat arrow is always a Func, never a Closure.
Exactly. A function with assume-globals. Guess what would happen in here (its fat-arrow declaration outside function/class brackets):

Code: Select all

gp_RegionCreate()=>(DllCall("gdiplus\GdipCreateRegion", 'uintp',r), r)
yeah, we rewrite r of the outer scope. And it should not happen by default in my opinion.
The point is you shouldn't try random stuff, with or without parenthesis, read the documenation.
Its not a random stuff, its a matter of convenience. to enclose expressions in additional brackets just to visually separate some parts or (like in the case above) to make sure every expressions list element divided by comma will belong to the same fat-arrow function. U missed the point of my question and I didnt pay enuf attention to remove all the unnecessary stuff from the post, my bad. :)

PS: Documentation lacks examples here and there and doesn't cover all the use cases unlike Lexikos's posts on this forum. Due to traditional AHK quirks in syntax a user has to fiddle with semantics. E.g. I recall a nightmare of understanding the difference between MaxIndex/Length for objects. :D
Last edited by vvhitevvizard on 21 Jan 2019, 06:56, edited 2 times in total.
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: fat function in class method changes var outside itsscope

21 Jan 2019, 06:50

But thats what the fat arrow definition is for? It is to create a func object/closure that interacts with the current scope.
e.g. in order to create a quick callback that sets a var of the current scope.
Its not to quickly define methods of classes.
Recommends AHK Studio
User avatar
vvhitevvizard
Posts: 454
Joined: 25 Nov 2018, 10:15
Location: Russia

Re: fat function in class method changes var outside itsscope

21 Jan 2019, 07:03

nnnik wrote:
21 Jan 2019, 06:50
But thats what the fat arrow definition is for? It is to create a func object/closure that interacts with the current scope.
I've read about free-variables of closures. Closure fat-arrows definition is completely different from function/method definition but the syntax expected to be the same.
IMHO fat-arrow is just a sugar syntax, a shortened variant of function declaration. We shouldn't destroy structured programming basics by esotericism of variable scope of variables used with functions/methods.
nnnik wrote:
21 Jan 2019, 06:50
Its not to quickly define methods of classes.
it is expected to be actually. :D
A lambda expression in Java is a concise way to express a method of a class in an expression.
NB: Java is top 1 popular language.
Last edited by vvhitevvizard on 21 Jan 2019, 07:08, edited 1 time in total.
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: fat function in class method changes var outside itsscope

21 Jan 2019, 07:07

Your humble opinion is proven wrong by facts - the fat arrow function is not syntax sugar for function definitions - it is used to define quick callbacks and similar things during execution and binding them to the containing scope.
Recommends AHK Studio
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: fat function in class method changes var outside itsscope

21 Jan 2019, 07:10

Yes and in java the -> lambda expression binds against the local scope.
Scope is just completely different in java - it doesn't even have a global scope to begin with.
Recommends AHK Studio
User avatar
vvhitevvizard
Posts: 454
Joined: 25 Nov 2018, 10:15
Location: Russia

Re: fat function in class method changes var outside itsscope

21 Jan 2019, 07:13

nnnik wrote:
21 Jan 2019, 07:07
Your humble opinion is proven wrong by facts - the fat arrow function is not syntax sugar for function definitions - it is used to define quick callbacks and similar things during execution and binding them to the containing scope.
Sure. I'm just expressing my experience as a user. :D
U r talking of Func/Bind and Closures, fat arrow is just a shortened syntax expanding function/closure body in my eyes. U can achieve the mentioned functionality w/o fat-arrows.
With one exception - fat arrows might be unnamed.
nnnik wrote:
21 Jan 2019, 07:10
Yes and in java the -> lambda expression binds against the local scope.
Scope is just completely different in java - it doesn't even have a global scope to begin with.
And thats exactly what I expect from every enclosed "module" (class, method, function, closure, for-loop, try-block, structure, etc) - to have its own scope by default.

AHK issue is there r way too many built-in global vars like A_YWeek, A_WinDelay, etc and an average AHK user accustomed to the bad programming style and every big script becomes an unstable mess with global name space polluted. I'm not even talking of encapsulation within classes, users used to do labels and goto/gosub instead of functions... No wonder not so many ppl (if any) complained about the issue in this topic.
its my humble opinion and I might be wrong and ready to well founded discussion ofc.

PS: I'll try to express in different wording: fat arrows expected to behave as if they were a function/closure bodies respectively (depending on the context) just w/o curly brackets and explicitly defined return statement. with no BUTs. :D Additional functionality of unnamed usage is a plus ofc.
PPS: Somewhat they compensate for macro expanded blocks and conditional preprocessor lacking in AHK.
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: fat function in class method changes var outside itsscope

21 Jan 2019, 09:07

AHKs scope system does not work that way.
What you want are changes to this scope system - not the fat arrow functions.
Recommends AHK Studio
User avatar
vvhitevvizard
Posts: 454
Joined: 25 Nov 2018, 10:15
Location: Russia

Re: fat function in class method changes var outside itsscope

21 Jan 2019, 09:24

nnnik wrote:
21 Jan 2019, 09:07
AHKs scope system does not work that way.
temporary iterators of for or loop having their own scope and which r deleted after the enclosed block is over.
classes encapsulation.
functions having assume-local by default.
u name it. Am I missed something in the paradigm? :D Ah yeah. Static initialization of random block lines... But its kinda a quirk of AHK.

And scope system of super global built-in vars, hotlabels and all that stuff can be called a... its rather a command syntax and legacy stuff. All those hotkeys, mouse, time and other subsets might be converted into structured objects one day. :)

Anyways implementation of lambda-like functionality may differ. Im grateful AHK version is not simplified to the extreme as its Python counterpart which is allowed to have only 1 expression and restricted to the end of just 1 line.
User avatar
vvhitevvizard
Posts: 454
Joined: 25 Nov 2018, 10:15
Location: Russia

Re: fat function in class method changes var outside itsscope

21 Jan 2019, 09:59

Helgef wrote:
21 Jan 2019, 06:14
It is a design choice with both pros and cons. I guess it is assumed that the user more often wants the var in,
to be the same variable, and it will be regardless of whether you define the variable and the fat arrow function inside or outside a function.
After some thinking, AHK could have a global variable to change this behavior. To change fat-arrows assume mode.
And to have #Warn LocalSameAsGlobal to highlight undeclared fat-arrow local vars which have the same name as a global var... At the moment fat-arrow functions just silently do nasty things.

Return to “AutoHotkey Development”

Who is online

Users browsing this forum: No registered users and 28 guests