Fat arrow =>

Discuss the future of the AutoHotkey language
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: Fat arrow =>

28 Mar 2018, 07:47

That is just auto concat nnnik, returning an object with the result, not multiple lines. You cannot do a loop in it, for example.
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: Fat arrow =>

28 Mar 2018, 07:53

I think this is the perfect example where a nested function is more useful than a lambda expression.
That would change if lambda expressions had access to the containing scope and DllCall would automatically create callback for every func object that gets passed to it.
Recommends AHK Studio
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: Fat arrow =>

28 Mar 2018, 07:54

Helgef wrote:That is just auto concat nnnik, returning an object with the result, not multiple lines. You cannot do a loop in it, for example.
Yeah I mention that in my post.
Still I think it's cleaner than using , at the beginning of ever new line.
Recommends AHK Studio
User avatar
kczx3
Posts: 1640
Joined: 06 Oct 2015, 21:39

Re: Fat arrow =>

28 Mar 2018, 08:02

nnnik wrote:using the recent update with automatic continuation inside {} and [] allows for:

Code: Select all

() => [
	DllCall( 1 )
	DllCall( 2 )
	DllCall( 2 )
]
and

Code: Select all

() => {
	lambda:
	DllCall( 1 )
	DllCall( 2 )
}
Still no If/Else throw Loops or break.
To me, a novice/intermediate developer, I don't see the benefit of the fat arrow expressions if you can't use loops or if/else statements. Sometimes its hard for me to understand without a few good use case examples. If using a ternary is basically the extent of its logic, then why not just do that in a normal expression where the variables you would pass to a fat arrow expression are already in scope?
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: Fat arrow =>

28 Mar 2018, 08:04

On another note I think that we might need some new functions to adjust AutoHotkey to this new syntax.
I'm currently writing a sort function. And there might be more functions that might be nice to have with the combination of lambda and arrays/objects.
Do you guys have any ideas for such functions?
Recommends AHK Studio
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: Fat arrow =>

28 Mar 2018, 08:09

To me, a novice/intermediate developer, I don't see the benefit of the fat arrow expressions if you can't use loops or if/else statements. Sometimes its hard for me to understand without a few good use case examples. If using a ternary is basically the extent of its logic, then why not just do that in a normal expression where the variables you would pass to a fat arrow expression are already in scope?
lambda expressions are mostly used to define callback functions on the spot. For example if you have a list view and want it to update it's data automatically you wouldn't pass an array but rather a function that returns an array with items.
I agree that this is a strong limitation on the lambda expressions. I don't know the reason for that though. It might be limitations in the current framework.
Recommends AHK Studio
User avatar
kczx3
Posts: 1640
Joined: 06 Oct 2015, 21:39

Re: Fat arrow =>

28 Mar 2018, 08:37

nnnik wrote:lambda expressions are mostly used to define callback functions on the spot. For example if you have a list view and want it to update it's data automatically you wouldn't pass an array but rather a function that returns an array with items.
I agree that this is a strong limitation on the lambda expressions. I don't know the reason for that though. It might be limitations in the current framework.
Certainly probable. Many reasons plausible and all are reasonable since its just Lexikos doing all of this amazing work. Just great to see progress like this and goes to show how anything is possible. Love to see the bar continuously being raised.
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: Fat arrow =>

28 Mar 2018, 10:11

I have created the sort function for AHK v2 based on functions I commonly see in other languages:
https://autohotkey.com/boards/viewtopic.php?f=6&t=46260
It might be a good examples what lambda expressions can be used for.
Recommends AHK Studio
User avatar
Flipeador
Posts: 1204
Joined: 15 Nov 2014, 21:31
Location: Argentina
Contact:

Re: Fat arrow =>

28 Mar 2018, 10:26

Helgef wrote:you could make your function like this instead
Very nice! Thanks for that :bravo:
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: Fat arrow =>

28 Mar 2018, 11:32

Helgef wrote: I'm not sure there is a well defined scope when the static initialising takes place
Well it seems the local variables exists, no surprise I guess, eg,

Code: Select all

f()
f()
f(){
	static a := b := 1
	msgbox b
}
Still, I do not think it is what you needed. (@ Flipeador)
Yeah I mention that in my post.
Still I think it's cleaner than using , at the beginning of ever new line.
Either you edited your post while I wrote, or I missed that. I think it is cleaner to avoid creating an unnecessary object, you can use (), eg,

Code: Select all

() => (
	DllCall( 1 ),
	DllCall( 2 ),
	DllCall( 2 )
)
where the commas can be omitted. I wouldn't omit them though, unless I really wanted to return the result from all calls, concatenated to a string.
guest3456
Posts: 3454
Joined: 09 Oct 2013, 10:31

Re: Fat arrow =>

28 Mar 2018, 11:45

Helgef wrote:

Code: Select all

() => (
	DllCall( 1 ),
	DllCall( 2 ),
	DllCall( 2 )
)
where the commas can be omitted. I wouldn't omit them though, unless I really wanted to return the result from all calls, concatenated to a string.
+1

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

Re: Fat arrow =>

28 Mar 2018, 11:47

I edited my post - immediately after posting I often notice that I missed something.
i also think that your version is the best one ( I will choose to omit , though )
Recommends AHK Studio
User avatar
kczx3
Posts: 1640
Joined: 06 Oct 2015, 21:39

Re: Fat arrow =>

29 Mar 2018, 08:39

Curious if this should be expected to work?

Code: Select all

mainGui := GuiCreate("", windowTitle), mainGui.BackColor := "White", mainGui.MarginX := mainGui.MarginY := 10
mainGui.OnEvent("Close", (g) => ExitApp)
User avatar
Flipeador
Posts: 1204
Joined: 15 Nov 2014, 21:31
Location: Argentina
Contact:

Re: Fat arrow =>

29 Mar 2018, 08:44

kczx3 wrote:Curious if this should be expected to work?
This works:

Code: Select all

Gui := GuiCreate()
Gui.OnEvent("Close", () => ExitApp())
Gui.Show("w500 h350")
Return

Code: Select all

f()
MsgBox
f()
{
    Return ExitApp    ; this is happening: ExitApp is a variable
}
(g) => ExitApp --> f(g) {return exitapp}
User avatar
kczx3
Posts: 1640
Joined: 06 Oct 2015, 21:39

Re: Fat arrow =>

29 Mar 2018, 09:20

@Flipeador - Thanks!
lexikos
Posts: 9553
Joined: 30 Sep 2013, 04:07
Contact:

Re: Fat arrow =>

30 Mar 2018, 23:40

v2.0-a091 fixes the assignment bug reported by Helgef.

I borrowed the name "fat arrow function" from ECMAScript 6, although C# and probably other languages also use this syntax. It is more descriptive than "lambda", and might avoid some misconceptions since it's clearly a reference to how the function is written, not what it can do. Fat arrow functions are not necessarily "nested functions" (they can be global) or "closures" or even "anonymous functions" (in v2.0-a091).

As for ease of typing =>, is it harder than typing >=? The latter is surely much more common.

The bug regarding oWindows and Visible reported by Flipeador only applies to nested functions referring to the local variables of a function outside the immediate outer function (i.e. multi-level nesting). The problem was not unique to fat arrow functions, as Helgef demonstrated. It has been fixed in v2.0-a091.

I'll address the issues with static initializers in another post.

As documented, fat arrow functions can only evaluate an expression and return its result. Expressions cannot contain statements. Other languages allow the body of a fat arrow function to be an expression or a block, as in () => { statements }. This could be allowed in future (with significant changes to the parser), but consider the ambiguity; is () => {} a function which creates an empty object, or a function with an empty block?

I imagine that the normal function definition syntax could be used in an expression, optionally omitting the function name. For example:

Code: Select all

Gui.OnEvent("Close", (Gui) {
    if MsgBox("Sure?",, "y/n") = "yes"
        ExitApp()
})
I had this in mind when I added JSON syntax, so the sequence ) { is already reserved; it produces an an Unexpected "{" error. However, I don't consider this a priority, and I have mixed feelings about including a multi-line function inside the parameter list of another function (or another expression). I sometimes think that it is better to name the function and write it separately (even if just above or below the function call).

As I see it, the benefits of a fat arrow function are:
  • brevity
  • ability to define it inline
  • ability to leave it unnamed
If the function's body is a simple one-line expression, you might save three lines (or four if you don't use OTB):

Code: Select all

OnClose() {
    ExitApp()
}
Gui.OnEvent("Close", Func("OnClose"))

Gui.OnEvent("Close", () => ExitApp())
But if the function's body requires multiple lines, there's less (proportional) benefit. As a matter of style (and subjective readability), it might be better to avoid including a block of statements inside an expression. Sometimes a descriptive function name will serve as a comment, and having a name at all may have value for debugging. Other times, as in the example above, it just adds repetition. I think that functions which merely return an expression (i.e. what => allows) are the ones most likely to benefit from shorthand syntax.
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: Fat arrow =>

31 Mar 2018, 02:54

Thank you for this update
lexikos wrote:I imagine that the normal function definition syntax could be used in an expression, optionally omitting the function name. For example:

Code: Select all

Gui.OnEvent("Close", (Gui) {
    if MsgBox("Sure?",, "y/n") = "yes"
        ExitApp()
})
I had this in mind when I added JSON syntax, so the sequence ) { is already reserved; it produces an an Unexpected "{" error. However, I don't consider this a priority, and I have mixed feelings about including a multi-line function inside the parameter list of another function (or another expression). I sometimes think that it is better to name the function and write it separately (even if just above or below the function call).[/code]
I also like that idea and got it after learning about the JSON syntax in AHK. It's great to hear that this might become a reality.
As I see it, the benefits of a fat arrow function are:
  • brevity
  • ability to define it inline
  • ability to leave it unnamed
If the function's body is a simple one-line expression, you might save three lines (or four if you don't use OTB):

Code: Select all

OnClose() {
    ExitApp()
}
Gui.OnEvent("Close", Func("OnClose"))

Gui.OnEvent("Close", () => ExitApp())
But if the function's body requires multiple lines, there's less (proportional) benefit. As a matter of style (and subjective readability), it might be better to avoid including a block of statements inside an expression. Sometimes a descriptive function name will serve as a comment, and having a name at all may have value for debugging. Other times, as in the example above, it just adds repetition.
What about accessing local vars inside functions it is defined in? In Java I liked to define object relations with -> ( javas equivalent of => ).
However in AutoHotkey that will only be possible by using super global vars, functions or by using bind.
E.g. if we used a class called Program and want to call Program.Exit() rather than ExitApp().
What is the proper way to do this using =>?
I think that functions which merely return an expression (i.e. what => allows) are the ones most likely to benefit from shorthand syntax.
In the past AutoHotkey seemed to avoid specific one line logic - e.g. a StrJoin or an AssociativeArrayCombine method.
Do you have plans to change this in the future? I mean a shorthand for single line expressions when there are barely any single line expressions is not very useful.
Recommends AHK Studio
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: Fat arrow =>

31 Mar 2018, 03:40

Regarding () => { statements }, I do not think it would add a whole lot unless you could do same line statements, eg, while(x) y() or while(x) { ... }.
is () => {} a function which creates an empty object, or a function with an empty block?
Either only permit braces on multiline definitions or always demand, i.e, () => { {} }, the latter is less desirable imo.
As for ease of typing =>, is it harder than typing >=? The latter is surely much more common.
It is ok, and it will help me remeber that comparison is is not =>, hence it is >= (Pathetically, I struggle to remember). My guess is though, that I will use fat arrow much more than >= (and <=)
Added the capability to name fat arrow functions.
:thumbup: very nice.
Error:

Code: Select all

f ()=>1 ; Error:  Missing operator or space before "(". ; Naming it works
f(f){
}

Code: Select all

f f := ()=>1 ; Error:  Invalid assignment. ; Naming it works
f(f){
}

What about accessing local vars inside functions it is defined in?
nnnik, possibly I misunderstand you :think:. You can access locals, eg,

Code: Select all

msgbox f().call()
f(){
	local x := 0
	return () => x
}
E.g. if we used a class called Program and want to call Program.Exit() rather than ExitApp().
What is the proper way to do this using =>?
You do () => Program.Exit() unless the outer function has declared (either explicitly or due to forced local) Program as local in which case it might not refer to the class
Cheers.
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: Fat arrow =>

31 Mar 2018, 03:53

Oh I guess I misunderstood then.
Helgef wrote:Regarding () => { statements }, I do not think it would add a whole lot unless you could do same line statements, eg, while(x) y() or while(x) { ... }.
I disagree. If you could use:

Code: Select all

Gui.OnEvent( "Close", closeApplication() => { 
if ( msgbox( "Do you really want to exit?" ) = "Yes" ) ;imagine the button options as Yes/No
	ExitApp()
} )
it would be incredibly useful
Recommends AHK Studio
User avatar
kczx3
Posts: 1640
Joined: 06 Oct 2015, 21:39

Re: Fat arrow =>

31 Mar 2018, 05:28

nnnik wrote:Oh I guess I misunderstood then.
Nnnik wrote: I disagree. If you could use:

Code: Select all

Gui.OnEvent( "Close", closeApplication() => { 
if ( msgbox( "Do you really want to exit?" ) = "Yes" ) ;imagine the button options as Yes/No
	ExitApp()
} )
it would be incredibly useful
Agreed

Return to “AutoHotkey Development”

Who is online

Users browsing this forum: No registered users and 47 guests