no it couldn't, a directive would work, but please spare us.After some thinking, AHK could have a global variable to change this behavior. To change fat-arrows assume mode.
fat function in class method changes var outside itsscope
Re: fat function in class method changes var outside itsscope
Re: fat function in class method changes var outside itsscope
Yes spare us - this is what we fought against - this is what we wanted to remove.
This is why we made v2 - to remove all those global settings and variables that change the global state of the language.
Your suggestion is way worse than how arrow functions currently behvave imo.
You completely change the language with a single variable essentially creating 2 versions of it.
This is why we made v2 - to remove all those global settings and variables that change the global state of the language.
Your suggestion is way worse than how arrow functions currently behvave imo.
You completely change the language with a single variable essentially creating 2 versions of it.
Recommends AHK Studio
- vvhitevvizard
- Posts: 454
- Joined: 25 Nov 2018, 10:15
- Location: Russia
Re: fat function in class method changes var outside itsscope
U have a point. I'm not an advocate of global vars that change language behavior and would like the whole AHK language to have uniformity. It was just brainstorming Thou some global settings make sense, e.g. defining:
A_FileEncoding:="UTF-8"
saves lots of space and relieves from a headache of having that param all over FileOpen, FileAppend, etc functions.
A_FileEncoding:="UTF-8"
saves lots of space and relieves from a headache of having that param all over FileOpen, FileAppend, etc functions.
- vvhitevvizard
- Posts: 454
- Joined: 25 Nov 2018, 10:15
- Location: Russia
Re: fat function in class method changes var outside itsscope
ok. back to the topic. here is what expected from a closure. it allows to change a topvar of the function containing the current closure. it is ok - it affects only the current function. The rationale behind that is we can create CallBacks with Closures - it is understood.
but please pay attention that a closure cant change a var outside a function by default, w/o declaring it global.
when we create a fat arrow closure we expect it to mess up with the body of the function at most.
so in the next example a fat arrow method (object key assigned a Func, whatever - its callable) is not expected to change global vars by default, w/o declaring its name as global.
simply because methods and functions behave this way. Doesnt matter what rationale stands behind static object key - what we have after static initialization procedure done is object key assigned a Func and that object method should behave as expected respecting enclosed class/object scope by default.
when we create a fat arrow func (method here) we dont expect it to mess up with the vars outside functions (outside class/object here), in auto-execute code, etc.
but please pay attention that a closure cant change a var outside a function by default, w/o declaring it global.
when we create a fat arrow closure we expect it to mess up with the body of the function at most.
Code: Select all
t:="not changed"
u:="not changed"
func0()
msgbox("#3| " u)
func0(){
msgbox("#1| " t)
func1()
msgbox("#2| " t) ;here we access to downvar in the closure
func1(){
t:=1 ;it changes upvar t inside the function
u:=2 ;this doesnt change global u
}
}
so in the next example a fat arrow method (object key assigned a Func, whatever - its callable) is not expected to change global vars by default, w/o declaring its name as global.
simply because methods and functions behave this way. Doesnt matter what rationale stands behind static object key - what we have after static initialization procedure done is object key assigned a Func and that object method should behave as expected respecting enclosed class/object scope by default.
when we create a fat arrow func (method here) we dont expect it to mess up with the vars outside functions (outside class/object here), in auto-execute code, etc.
Code: Select all
t:="not changed"
s1:=class1.func1(), msgbox(t) ;global var: "not changed"
s2:=class1.func2(), msgbox(t) ;NOT EXPECTED: global var: "2"
msgbox(s1 " | " s2) ;retvals: "1 | 2"
class class1{
func1(){
t:=1
return t
}
static func2:=()=>(t:=2, t)
}
Last edited by vvhitevvizard on 21 Jan 2019, 20:24, edited 5 times in total.
Re: fat function in class method changes var outside itsscope
i thought what if it was called from within another lambda, so as to game the " The function is assume-local if it is nested inside another function" rule, but it doesnt work
it would be nice if u could force local with a keyword though
Code: Select all
global Time := (() => ({Unix: () => (DllCall("GetSystemTimeAsFileTime", 'int64p', t), t // 10000001 - 11644473600)})).Call()
global Time := {Unix: () => ((() => (DllCall("GetSystemTimeAsFileTime", 'int64p', t), t // 10000001 - 11644473600)).Call())}
- vvhitevvizard
- Posts: 454
- Joined: 25 Nov 2018, 10:15
- Location: Russia
Re: fat function in class method changes var outside itsscope
its 5 am here. Im afraid I didn't get ur construction. .Call() doesnt call the 2nd nested lambda - it never gets to msgbox("here") inside it.
Code: Select all
t:="unchanged"
global Time := (() => ({Unix: () => (DllCall("GetSystemTimeAsFileTime", 'int64p', t)
, msgbox("here"), t // 10000001 - 11644473600)})).Call()
global Time := {Unix: () => ((() => (DllCall("GetSystemTimeAsFileTime", 'int64p', t)
, msgbox("here"), t // 10000001 - 11644473600)).Call())}
msgbox(Time " | " t)
Last edited by vvhitevvizard on 21 Jan 2019, 21:11, edited 1 time in total.
- vvhitevvizard
- Posts: 454
- Joined: 25 Nov 2018, 10:15
- Location: Russia
Re: fat function in class method changes var outside itsscope
And concerning warnings:
I neither want to know the rationale of that nor the fact that it is not an omission and even might be documented somewhere as a "feature" (the way closures not having "base" keyword support is documented).
It just feels inconsistent and it doesn't allow me to debug. I try to highlight such quirks.
Code: Select all
#Warn LocalSameAsGlobal
t:="unchanged"
func0(){
t.=" changed" ;OK: warning "local var has the same name as a global"
}
func1()=>t.=" changed" ;BAD: no warning here
func2(){
local t
t.=" changed" ;OK: we declared it local explicitly
}
func3(t:=""){
t.=" changed" ;OK: we "allocated" t in the arg list making it effectively local
}
It just feels inconsistent and it doesn't allow me to debug. I try to highlight such quirks.
Re: fat function in class method changes var outside itsscope
u havent called Time.Unix()
- vvhitevvizard
- Posts: 454
- Joined: 25 Nov 2018, 10:15
- Location: Russia
Re: fat function in class method changes var outside itsscope
Oh indeed. yeah. it corrupts t in both cases
2.
btw, v2 documentation states (at least at one place):
Functions are assume-local by default. Variables accessed or created inside an assume-local function are local by default
No. Overall, the current scope system is fine. The unexpected issues start with fat-arrow shortcomings and quirks.
3. To sum up:
1. if fat-arrow returns Func -> its body has to be in assume-local mode! Simple as that.
2. fat-arrow Func ignores local keyword:
3. fat-arrow Func doesn't have a proper #Warn LocalSameAsGlobal behavior: it never raised.
4. declaring methods (and get/set halfmethods) via fat-arrow syntax is undeveloped.
5. oh. It doesnt allow ListVars executed inside fat-arrow body so we cant even check AHK's namespace logic inside fat-arrows:
Code: Select all
t:="not changed"
class1.func1()
class1.func2()
class class1{
func1(){
t:=1
ListVars
return t
}
static func2:=()=>(t:=2, ListVars, t)
}
Re: fat function in class method changes var outside itsscope
i thought what if it was called from within another lambda, so as to game the " The function is assume-local if it is nested inside another function" rule, but it doesnt work
You can let the outer function's parameters be free vars, then you get a (inner) function without parameters which has vars which doesn't reference globals, assuming that was the goal. This is of course a game with syntax and nothing to recommended. If you want to control the scope, use a full function definition instead.Nested funcions wrote:if the outer function is assume-global, nested functions behave as though assume-global by default
There is nothing wrong with #warn, when a function is assume global it has no locals with the same name as a globals.
Cheers.
Last edited by Helgef on 22 Jan 2019, 02:18, edited 1 time in total.
Re: fat function in class method changes var outside itsscope
Please, listvars()oh. It doesnt allow ListVars executed inside fat-arrow body so we cant even check AHK's namespace logic inside fat-arrows:
Expressions wrote: () => expr
Re: fat function in class method changes var outside itsscope
AHKs classes are not their own scope - you are in global scope thats why the callback func (defined by a fat arrow) defined in global scope messes with global scope.
This is not a keyword - it's a hidden 1st parameter on any method.
This is not a keyword - it's a hidden 1st parameter on any method.
Recommends AHK Studio
Re: fat function in class method changes var outside itsscope
im not entirely sure what u meant by this. there is a vague idea concocting in my head, but i cant be too sure. can u elaborate with an exampleHelgef wrote: ↑22 Jan 2019, 01:41i thought what if it was called from within another lambda, so as to game the " The function is assume-local if it is nested inside another function" rule, but it doesnt workYou can let the outer function's parameters be free vars, then you get a (inner) function without parameters which has vars which doesn't reference globals, assuming that was the goal. This is of course a game with syntax and nothing to recommended. If you want to control the scope, use a full function definition insteadNested funcions wrote:if the outer function is assume-global, nested functions behave as though assume-global by default
the goal and the reasoning were as follows:assuming that was the goal
Code: Select all
; we want 'Time.Unix()', callable from anywhere, to return the correct timestamp, w/o clobbering other vars named 't'
global Time := (() => ({Unix: () => (DllCall("GetSystemTimeAsFileTime", 'int64p', t), t // 10000001 - 11644473600)})).Call()
; ^----------------------------------------------------------------------------------------------------^^^^^^^^ - this calls the outer-lambda
; ^^^^^^^--------------------------------------------------------------------------------------------^ - we make an outer-lambda, with the intention of abusing "The function is assume-local if it is nested inside another function" when we later create the inner-lambda
; ^^^^^^^------------------------------------------------------------------------------------^ - the outer-lambda when called, returns an obkect with key 'Unix' and value 'the inner-lambda', so when u do Time.Unix(), it calls the inner-lambda
; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - the inner-lambda, which wouldve hopefully been force-local by now, since it was 'nested inside another function'
also i hadnt taken Nested funcionswrote: if the outer function is assume-global, nested functions behave as though assume-global by default into consideration
Re: fat function in class method changes var outside itsscope
Code: Select all
global Time := ((t) => ({Unix: () => (DllCall("GetSystemTimeAsFileTime", 'int64p', t), t // 10000001 - 11644473600)})).Call("")
Tested it works - but dont use that please.
Recommends AHK Studio
Re: fat function in class method changes var outside itsscope
that works actually lol
now i only have to figure out why...
now i only have to figure out why...
Re: fat function in class method changes var outside itsscope
We can ignore and overwrite the first parameter due to the object call we are doing:
For any extra variables we need .bind():
Code: Select all
class Time {
static Unix := (t) => (DllCall("GetSystemTimeAsFileTime", 'int64p', t), t // 10000001 - 11644473600)
}
Code: Select all
class Time {
static Unix := (t, n) => (DllCall("GetSystemTimeAsFileTime", 'int64p', t),("Do something with n"), t // 10000001 - 11644473600).bind("")
}
Recommends AHK Studio
Re: fat function in class method changes var outside itsscope
@swagfag the inner lambda binds against the outer scopes variables.
t is a parameter of the outer scope - therefore local to the outer scope.
The inner scope then references this local parameter essentially creating a local variable.
Also please don't use this to define methods is ugly af - just use normal methods or wait until there is a feature added for this.
t is a parameter of the outer scope - therefore local to the outer scope.
The inner scope then references this local parameter essentially creating a local variable.
Also please don't use this to define methods is ugly af - just use normal methods or wait until there is a feature added for this.
Recommends AHK Studio
Re: fat function in class method changes var outside itsscope
i see
and no, im not disputing its handsomeness. multi-statement lambdas already prod my eyes as it is
and no, im not disputing its handsomeness. multi-statement lambdas already prod my eyes as it is
Re: fat function in class method changes var outside itsscope
Yes that is what I meant, maybe it is clearer like this,
equivalent to
with hidden this param ofc.
@ OP.
Even if fat arrow was changed (back) to assume local for outside function fat arrows, since you cannot force local in fat arrow, you should always use a full function/method definition if you are going to reference any non parameter/upvar in a fat arrow, unless you really want to reference a global var. So your complaints are futile, what you really want is to ask for is full function body fat arrows, eg,
Code: Select all
class Time {
static Unix := ((t:=0) => () => (DllCall("GetSystemTimeAsFileTime", 'int64p', t), t // 10000001 - 11644473600)).call()
}
Agree . I think it is reasonable that you can define a method likejust use normal methods or wait until there is a feature added for this.
Code: Select all
class t {
method() => expr
}
Code: Select all
class t {
method(){
return expr
}
}
@ OP.
Even if fat arrow was changed (back) to assume local for outside function fat arrows, since you cannot force local in fat arrow, you should always use a full function/method definition if you are going to reference any non parameter/upvar in a fat arrow, unless you really want to reference a global var. So your complaints are futile, what you really want is to ask for is full function body fat arrows, eg,
Code: Select all
() => {
local
DllCall("GetSystemTimeAsFileTime", 'int64p', t)
return t // 10000001 - 11644473600
}
- vvhitevvizard
- Posts: 454
- Joined: 25 Nov 2018, 10:15
- Location: Russia
Re: fat function in class method changes var outside itsscope
kk. it requires explicit use of () for function calls inside fat arrow expr. I skipped them in a haste and didn't even realize there is a difference. In a normal method body with 1 line per built-in function it accepts it w.o (). I would prefer expression evaluation tell me about if some var has a name as a built-in function instead of just failing silently.
Code: Select all
class1.func1()
class1.func2()
class class1{
func1(){
ListVars
Pause
}
static func2:=()=>(ListVars(), Pause())
}
Code: Select all
func1(){
ListVars, Pause
}
BUT
For fat-arrow's body it fails silently. So the issue persists tho in another form. Due to that unexpected difference using static func2:=()=>(ListVars, Pause) I fell into thinking ListVars simply fails inside fat-arrow.
PS: Please understand me correctly: writing ListVars is unusual to me, I write something like this for one-time breakpoints for debugging just for brevity, I do use () for every function call normally, e.g. I always write ExitApp() instead of ExitApp and for the majority of expressions, e.g. return(var). Just b/c its a good programming style and it does simplify cross-language programming.
But if I missed () by mistake I would expect the expression either a) work as if () r in the place (bad but thats how AHK and high-level interpreters work in general) or 2) give me some hint of error.
Thats right. Its not #warn misbehavior, the cause of it is inability to change assume-mode for fat-arrow expression. But as a matter of fact I cant find a way to control correctness of my namespace.Helgef wrote: There is nothing wrong with #warn, when a function is assume global it has no locals with the same name as a globals.
Return to “AutoHotkey Development”
Who is online
Users browsing this forum: No registered users and 21 guests