U r talking of classes. but the question here is scope of methods (aka class functions) here. U cant even run a code of class scope itself - its impossible.
Code: Select all
class class1{
;try to run some code outside methods here
}
U r talking of classes. but the question here is scope of methods (aka class functions) here. U cant even run a code of class scope itself - its impossible.
Code: Select all
class class1{
;try to run some code outside methods here
}
All function calls require () in an expression, except as described here.it requires explicit use of () for function calls inside fat arrow expr.
There is no silent failure, function names aren't reserved. I do not think they should unless we have case sensitive variables and function names etc...I would prefer expression evaluation tell me about if some var has a name as a built-in function instead of just failing silently.
f() => expr is equivalent toIf I combine built-in function calls in 1 line:
Code: Select all
f(){
return expr
}
Helgef, u try to explain everything in terms of semantics. I share my expectation as a user of the language - every unexpected quirk adds up to negative experience for a user.
It was enclosed in brackets in the example =>(ListVars, Pause). So both parts devided by , r evaluated before returning.f() => expr is equivalent to
But we do have a function to differ Built-in function names from UDF. So I expected this check to be inside expressions. For static names such a check should have been made at load time, right?There is no silent failure, function names aren't reserved.
1 line stuff like that is so disgusting.etc to be evaluated inside it so I could combine them on 1 line
AHKs behaviour - regardless of the varname - is it to create the variable as soon as it's referenced. IMO it might make more sense to remove the command style call for functions so that people cannot run into this limitation anymore.What I try to point out is it neither accepts my syntax nor raises an error here. Im against any silent failure behavior like this one. If I want ListVars to be a var I either enclose it in brackets (Listvars) or add function syntax to it Listvars() or assign it some value ListVars:="" or declare it local ListVars (I migth miss some use cases here but u got my idea). I've done nothing of that explicitly and I don't expect AHK to take ListVars , Pause silently. Here should be any hint of error.
Which does not make any difference in the slightest.It was enclosed in brackets in the example =>(ListVars, Pause). So both parts devided by , r evaluated before returning.
You referenced a variable - do you want a #Warn mode that tells you when you used a variable that has the same name as a function?There is no silent failure, function names aren't reserved.
Yuppers! We want a revolution!
Yeah. That example of command-like syntax remaining in v2 drives me mad:
Add(2, 3)
Add 2, 3 ; Parentheses can be omitted if used at the start of a line.
Well, it doesn't imply everyone HAS to use that style. its like OTB brackets, a matter of choice. I, for one, would like to combine bracket enclosement commands (if, loop, try, etc) especially if they dont have a bracketed body. e.g.:
Code: Select all
if(a)
b++
else
continue
Code: Select all
if(a) b++, else continue
Code: Select all
if(a)
b++, break
Yes! That's what I wish with all my heart. And we have that chance with v2. We r still in alpha state and bound to radical changes and not fully interrelated to v1.AHKs behaviour - regardless of the varname - is it to create the variable as soon as it's referenced. IMO it might make more sense to remove the command style call for functions so that people cannot run into this limitation anymore.
yes. I just answered Helgef post where he broke down fat-arrow logic. we dont return right after first sub-expression there.
Not just User-Defined Function, Built-in Function! And done that w.o any assignment... Just Listvars. It should be load-time error cuz expr like this makes no sense and prolly a mistype. If we need to let AHK know we want to reference it (for free variables and other cases), it should be written as (Listvar) at least.You referenced a variable - do you want a #Warn mode that tells you when you used a variable that has the same name as a function?
I don't understand. Could u rephrase please.
I do my best to express my personal experience and expectations. Ofc its up to the active developers to implement anything of this. But I would not even create a single post if I didn't care of the AHK future.
U effectively added argument to it. As I wrote before about that hack of allocating local vars in arguments list, u can write it directly Time(t:=0)=>... and use that t as if its a local var. But it reduces performance compared to direct declaration or straightforward usage of the var cuz it adds initialization and shadowing (redundant copying) of that var into local var with the same name. Anyways that's what I HAD to do for now to return stability to my fat-arrow lines.
fat-arrow Func (we put aside fat-arrow Closure) should act the same way as if a full function definition is placed in its place. If the AHK developers don't want to add assume-mode change command support then yes - for irregular stuff a user would have to use full function definitions. But again - default for function body should be assume-local, no other kinky default variants. Normally global vars (upvars) should be passed via arguments to a function. Class methods should be even more encapsulated. by default. Twisty-minded users r allowed to do whatever they want with full-body declarations. Everyone is happy.Helgef wrote: ↑22 Jan 2019, 05:16@ 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,
Flow control statements, keyword statements, action commands and expressions are processed in separate stages of the script. Declaration keywords are not even considered in the expression parser, so they are just variables. Only callables in expressions are functions, commands called as functions and function objects using parenthesis. Commands without function parenthesis in expressions are not considered commands, only variables, because they are not handled in the expression parser.
It's a matter of knowing what is what, commands are not functions and vice versa (but they can be converted). Not everything is an expression either, or is even handled during the evaluation of the expression, some stuff is handled well before that (directive, hotkeys, function definitions, variable declarations, etc).vvhitevvizard wrote: ↑23 Jan 2019, 01:58What I try to point out is it neither accepts my syntax nor raises an error here. Im against any silent failure behavior like this one. If I want ListVars to be a var I either enclose it in brackets (Listvars) or add some operands around it ++ListVars or add function syntax to it Listvars() or assign it some value ListVars:="" or declare it local ListVars (I migth miss some use cases here but u got my idea). What the heck is ListVars here? I've done nothing of that explicitly and I don't expect AHK to take ListVars , Pause silently. Here should be any hint of error.
Code: Select all
foo := 1
msgbox(foo)
msgbox(foo())
foo() {
return 10
}
Code: Select all
mbox ; calls the function
mbox() {
msgbox()
}
Commands can't be called inside expressions, unless they are called like a function. Functions can only be called inside expressions with ().vvhitevvizard wrote: ↑23 Jan 2019, 01:58It was enclosed in brackets in the example =>(ListVars, Pause). So both parts devided by , r evaluated before returning.
Code: Select all
local := 1
global := 1
msgbox(local + global)
Code: Select all
list := [
"hello",
"world"
]
msgbox(list[2])
text := (
"what's "
"up "
"brother?"
)
msgbox(text)
Oh One that statement of urs explains many things! Thx for ur feedback.
But what do u think of using just a bare variable name in the expression? Not ( (var) ) as if we wanted to evaluate it (such syntax is currently used in AHK for evaluation of key names inside objects/array declaration), just ( var ). Especially if variable's value is not used further on in the expression (like Listvars in here): ()=>(ListVars, Pause) Shouldn't it be signaled as an error, should it?Functions and variables do not share the same storage. A variable can be named like a function without breaking the function. You can also override built in functions with your own of the same name.
I believe the major AHK issue here we have that rudimentary command syntax. One language here, another language there. Logic inside expressions seems much more mature and logic outside pushes us back to the dark past of batch scripts.some_name by itself in a line will either call a command, or a function, not declare a variable. They are not considered variables even if you force commands to be called with parenthesis (i.e prevent command param).
Well, w.o major overhaul of expressions parser, making an expected proper assume-mode for fat-arrow Func would fix the things. No need for local, static, etc keywords support inside expressions. Function (Func object's referenced body) should be assume-local by default, do u agree with me?(local, static, global) variables.
I'm not sure what you mean here. You don't need to use parenthesis to evaluate a variable inside an expression, or outside of one, barring that exception of object creation syntax and gosub/goto.vvhitevvizard wrote: ↑24 Jan 2019, 06:26But what do u think of using just a bare variable name in the expression? Not ( (var) ) as if we wanted to evaluate it (such syntax is currently used in AHK for evaluation of key names inside objects/array declaration), just ( var ). Especially if variable's value is not used further on in the expression (like Listvars in here): ()=>(ListVars, Pause) Shouldn't it be signaled as an error, should it?
Code: Select all
(var1, var2, var3 := 1, var4) ; These variables will continue to exist after the expression is done. The result of the expression will be value of var4, which is discarded, since there's nothing receiving it.
; If they didn't exist previously and nothing is done to them, then they simply hold an empty string.
; You can also simply chain them, no parenthesis needed.
varA := varB := varC := "", varD := 1
;or
varE := varF := varG := varH
msgbox(varG == '') ; 1
(var5, var6 := 1, var6) ; var5 is created, if not found, otherwise it's value is retrieved and discarded, but the result of the main expression is var6 evaluated, i.e 1, rightmost.
; so
var8 := (var7, 10) ; it will find or create var7, and the result, 10, will be stored in var8
var11 := (var22 := 22, var33 := var22, var44 := var33 + 1) ; var11 and var44 contain 23, all the other ones contain 22.
msgbox(var11 " | " var33 " | " var44)
Why would it error? the body of a fat arrow is strictly an expression in a return statement, think of syntax sugar like classes are for objects, unlike fat arrows or function expressions in javascript for example. If you follow the rules of expressions, there are no wrongdoings, listvars or pause are just variables in that example. They are not looked up as, or considered, functions or commands. Only reserved words are flow control statements and some word operators.vvhitevvizard wrote: ↑24 Jan 2019, 06:26()=>(ListVars, Pause) Shouldn't it be signaled as an error, should it?
Code: Select all
ab() => (1,2,3,4,5) ; will return 5
; is the same as, barring the scoping
ab() {
return (1,2,3,4,5) ; key point in the parenthesis here. That's what the fat arrow *is*. A function that returns a main expression that can have any number of subexpressions.
}
Code: Select all
var1 := "key5"
obj := {
key1: "value1", ; looks similar to obj.key1 := "value1"
key2: value2, ; value2 here is a variable that is evaluated. Right key values are expressions.
key3: msgbox "hi", ; msgbox is considered a variable. Unless defined, it's empty, so "hi" is concatenated to it.
"key4": 10, ; Quoting the key is optional unless it has a space (there may be more conditions for this).
(var1): "value5",
(var2): "value6" ; if var2 doesn't exist, it will retardedly be an empty string key. Variable is created and is ''.
}
msgbox(obj.key3) ; "hi" -- No need for quotes as obj."key3". Only when accessing it with square brackets.
++obj.key4 ; No need for quotes.
msgbox(obj["key4"]) ; 11
msgbox(obj.key5) ; value5 -- Can also do obj[var1], no need to enclosre var1 in parenthesis.
msgbox(obj['']) ; value6 -- Only way to access empty string key is with square brackets.
For commands yes, I don't like command "calling" either which is why I disabled that in my setup. For other statements you can't do that since you have no mandatory delimiters. e.g: ifs do not require condition to be in parenthesis. I think enforcing that is easy, but then making it process statements in the same line would be pandora's box, specially since autohotkey doesn't have a non-expression statement separator.vvhitevvizard wrote: ↑24 Jan 2019, 06:26I believe the major AHK issue here we have that rudimentary command syntax. One language here, another language there. Logic inside expressions seems much more mature and logic outside pushes us back to the dark past of batch scripts.
Download visual studiovvhitevvizard wrote: ↑24 Jan 2019, 06:26Well, w.o major overhaul of expressions parser, making an expected proper assume-mode for fat-arrow Func would fix the things. No need for local, static, etc keywords support inside expressions. Function (Func object's referenced body) should be assume-local by default, do u agree with me?
Similar syntax already exists for array declarations with variables enclosed in parenthesis:
I would like the interpreter to be more strict and accept only such a way of using variables if they r meant to be used without any declaration/operations on them, e.g.:Associative Arrays help wrote:Any expression can be used as a key, but to use a variable as a key, it must be enclosed in parentheses. For example, {(KeyVar): Value}
I see. Irregularity over irregularity. Well, mandatory quotes for key names would fix the ambiguity - that's actually what I do myself in my AHK scripts. And thats what required in JSON syntax - key names r always in quoteskey1: "value1", ; looks similar to obj.key1 := "value1"
Code: Select all
while(++n<=n1)
InStr(" `t`n`r",c:=SubStr(_s,n, 1),1) || ( ;1=CaseSensitive
InStr(z,c,1) || E()
, (c==q) ? (d:=InStr(_s,q,1, n+1),v:=SubStr(_s, n+1, d-n-1) ;str literals
, n:=d, (!t) ? (k:=v, z:=':'):a ? (b.Push(v), z:=",]"):(b[k]:=v, z:=",}"))
: (c==':') ? (t:=1, z:=x)
: (c==',') ? (z:=(t:=a) ? x:q "{[")
: InStr("}]",c,1) ? ((s.1=root) && E()
, s.RemoveAt(1), y>>=1, b:=s.1, z:=(a:=y&1) ? ',]' : ',}')
: InStr("{[",c,1) ? (s.Count()>o.Depth && E()
, (c=='{') ? (t:=0, y:=y<<1&~1, z:=q '}') : (y:=y<<1|1, z:=x ']')
, b.SetCapacity(256), s.InsertAt(1,v:={})
, a ? b.Push(v):b[k]:=v, b:=s.1, a:=y&1)
: (NumPut(&_s+n*2,fa), v:=SubStr(_s, n, d:=DllCall(fc)), n+=d-1 ;number
, (v is "Number") ? v+=0:E(), a ? (b.Push(v), z:=",]"):(b[k]:=v, z:=",}"))
)
100.0% (if we dont count in exceptions). Sub-expression returns at least empty string "" or 0 (for boolean logic)I'm 99.99% positive every subexpression returns something
if removed completely, it would reduce resulting .exe file as well. Btw what other changes have u made for ur setup? Its getting interesting.For commands yes, I don't like command "calling" either which is why I disabled that in my setup.
Well, enforcing an expression to be enclosed in parenthesis obligatorily should fix it. e.g.: return(var), if(var==5), loop(var)For other statements you can't do that since you have no mandatory delimiters. e.g: ifs do not require condition to be in parenthesis. I think enforcing that is easy, but then making it process statements in the same line would be pandora's box, specially since autohotkey doesn't have a non-expression statement separator.
Yet fat arrow (Func type) as a whole is a bit more than just an expression w/o context (I return to the topic). lets pretend curly brackets, assume-xx commands and command in-lining r allowed in fat arrow's right expression:Code: Select all
ab() { return (1,2,3,4,5) ; key point in the parenthesis here. That's what the fat arrow *is*. A function that returns a main expression that can have any number of subexpressions. }
Code: Select all
ab()=>{global, 1,2,3,4, return 5}
Code: Select all
label:
x:=1 ;x may be of global scope by default here - I couldn't care less. labels outside functions r just a bad programming style
(2,3,4)
return 5
Download visual studio
Delete these two lines (may take a while to jump to it)
https://github.com/Lexikos/AutoHotkey_L/blob/alpha/source/script.cpp#L5710
Code: Select all
if (!g->CurrentFunc->mOuterFunc)
g->CurrentFunc->mDefaultVarType = VAR_DECLARE_GLOBAL;
this is merely a parameter of a method, supplied a value when the method is called. The value is supplied either implicitly (from target in target.method()), or as an explicit parameter when the method's implemention function is called directly or via .Call(). Static initializers may be contained within a method, but are evaluated on startup. The function is not called, so the parameter is not supplied a value. Static initializers for class variables have no method in the first place, so no this. You can refer to a global variable by that name if you wish...it seems base, this not yet defined at static evaluation time for prototype classes
A_ThisFunc contains the name of the currently executing function. Static initializers are either contained by a function which is not executing at the time the initializer is evaluated, or not even contained by a function.I cant find a way to use [A_ThisFunc] to call the current method at load time.
The expression var does not return a value, but a variable reference. It is not dereferenced until another operator is applied to it, or it is passed to a function, or it becomes the result of the overall expression. For instance, the expression (c ? a : b) can be passed ByRef or used as the target of an assignment.vvhitevvizard wrote: ↑20 Jan 2019, 21:39btw, 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?
This could be misleading with respect to static initializers inside functions. "Scope" is usually used in reference to how names are resolved, but most names are resolved at load time, in local scope. Static initializers can refer to other static variables, and those exist only in local scope. I think it's better to say that static initializers are executed in global context, and as a result, dynamic references use global scope.
That's true only by definition. If the script is executing a static initializer, some static variables haven't been initialized yet, so you could say the script hasn't "fully started". Where do you draw the line? Maybe the script does initialization in the auto-execute section, in which case it hasn't "fully started" until the auto-execute section finishes. But maybe the auto-execute section never finishes. In that case, has the script "fully started" only when the program finally exits?... before the script fully starts.
Thats good infoThis could be misleading with respect to static initializers inside functions. "Scope" is usually used in reference to how names are resolved, but most names are resolved at load time, in local scope. Static initializers can refer to other static variables, and those exist only in local scope. I think it's better to say that static initializers are executed in global context, and as a result, dynamic references use global scope.
Yeah but what is script code?That's true only by definition. If the script is executing a static initializer, some static variables haven't been initialized yet, so you could say the script hasn't "fully started". Where do you draw the line? Maybe the script does initialization in the auto-execute section, in which case it hasn't "fully started" until the auto-execute section finishes. But maybe the auto-execute section never finishes. In that case, has the script "fully started" only when the program finally exits?
I prefer to think that the "start" is when script code begins to execute. In that case, static initializers are executed at the very "start", before anything else (except other functions that are called by static initializers). You can instead say that static initializers are executed before the auto-execute section.
Code: Select all
#include gdip.ahk
pToken := Gdip_startup() ;script starts here
GUi,XYZ:New
Return to “AutoHotkey Development”
Users browsing this forum: No registered users and 15 guests