Allow Binding of ByRef Parameters via Bind() Method

Propose new features and changes
1100++
Posts: 78
Joined: 10 Feb 2018, 19:05

Allow Binding of ByRef Parameters via Bind() Method

04 Apr 2020, 15:58

Could it be made possible to bind variables to function objects using the Bind() method and have the passed variable be available to the function ByRef when it is called if the corresponding parameter is a ByRef parameter? For example:

Code: Select all

var := "Unaltered variable"
boundFn := Func("fn").Bind(var)

boundFn.Call()

MsgBox % var	; As of the current version of AutoHotkey, this message box displays the text
return			; "Unaltered variable".  I want it to display the message "Hello World!",
				; with or without the first line.

fn(ByRef var) {
	var := "Hello World!"
}
HotKeyIt
Posts: 2157
Joined: 29 Sep 2013, 18:35
Contact:

Re: Allow Binding of ByRef Parameters via Bind() Method

04 Apr 2020, 18:30

+1.

Just for info, using AHK_H you can do that using getvar() and Alias().

Code: Select all

var := "Unaltered variable"
boundFn := Func("fn").Bind(getvar(var))

boundFn.Call()

MsgBox % var	; As of the current version of AutoHotkey, this message box displays the text
return			; "Unaltered variable".  I want it to display the message "Hello World!",
				; with or without the first line.

fn(varptr:=0){
    Alias(var,varptr+0)
	var := "Hello World!"
}
lexikos
Posts: 7088
Joined: 30 Sep 2013, 04:07
GitHub: Lexikos

Re: Allow Binding of ByRef Parameters via Bind() Method

04 Apr 2020, 20:44

It's probably rare that this would be used with a global variable in a real script. Limitations of the current implementation would prevent this from being used safely with local variables, since each local variable is in fact a sort of singleton object; the variable always belongs to the top-most instance of the function still running. For a bound function being called, that would often not be the instance of the function that bound the variable, as that instance may have returned.

Closures work around this by using the concept of "free variables". Any local variable which may be captured by a closure is actually an alias for an unnamed "free variable". Each instance of the function allocates a block of free variables which are used for this purpose. When the closure is instantiated, it captures a reference to this block. These pointers are then shoved into the closure's own local aliases when the closure is called, so that it refers to the appropriate memory space.

Code: Select all

outer() {
    a := 1
    inner() {
        return a
    }
   return Func("inner")
}
outer and inner each have their own local variable named a, which is (in both cases) an alias for a "free variable". That is, an alias in the same sense as ByRef: the name a is associated with a Var struct, and that struct contains a pointer to some other Var where the real value can be found.
  • Within outer, a is an alias of a free variable belonging to the instance of outer which is currently executing.
  • Within inner, a is an alias of a free variable belonging to the instance of outer which is associated with whichever closure instance was called.
These variables cannot be individually bound or captured, because the free variables are allocated in a block and only the overall block is reference counted. Reference counting is not performed when each individual alias is assigned or cleared; only when a closure is instantiated or freed, or its outer function is called/returns.

If a local variable is not referenced by any closures (even a closure which is never used), it is not an alias--it always corresponds to the function's top-most running instance, and will be freed when the function returns. Binding it would not give correct results if that instance of the function is either not running or not the top-most instance when the bound function is called.

(The values of local variables are "backed up" when a new instance of the function interrupts a previous instance, and "restored" when it returns. This approach is optimal for functions which only ever have at most one instance, as the local variables do not need to be fully allocated and freed each time the function is called, and their addresses can be resolved at load time.)

Return to “Wish List”

Who is online

Users browsing this forum: No registered users and 1 guest