AHK V2: passing objects to non-byref param?

Discuss the future of the AutoHotkey language
SAbboushi
Posts: 122
Joined: 08 Dec 2014, 22:13

AHK V2: passing objects to non-byref param?

Post by SAbboushi » 02 Jul 2018, 17:00

I've been looking at this paragraph for 2 months, but think I'm still missing a distinction:
Because a variable only ever contains a reference to an object and not the object itself, when you pass such a variable to a non-ByRef parameter, what the function receives is a reference to the same object. This allows the function to modify the object, but it does not allow the function to modify the variable which the function's caller used, because the function only has a reference to the object, not the variable.
What variable is
the variable which the function's caller used
referring to? Is it referring to e.g. "x" in

Code: Select all

x := SomeFunction(SomeObject)
And
when you pass such a variable [an object] to a non-ByRef parameter
isn't it always passed "ByRef" since it is an object?
coffee
Posts: 74
Joined: 01 Apr 2017, 07:55

Re: AHK V2: passing objects to non-byref param?

Post by coffee » 02 Jul 2018, 23:32

SAbboushi wrote:I've been looking at this paragraph for 2 months, but think I'm still missing a distinction:
Because a variable only ever contains a reference to an object and not the object itself, when you pass such a variable to a non-ByRef parameter, what the function receives is a reference to the same object. This allows the function to modify the object, but it does not allow the function to modify the variable which the function's caller used, because the function only has a reference to the object, not the variable.
What variable is
the variable which the function's caller used
referring to? Is it referring to e.g. "x" in

Code: Select all

x := SomeFunction(SomeObject)
And
when you pass such a variable [an object] to a non-ByRef parameter
isn't it always passed "ByRef" since it is an object?
The contents of the variable is the reference to the object, like what the doc says, the variable itself is not the object.
Think of the variable as a pointer to an object in this case.
If you pass it by value to a function, you are copying the object reference to the internal variable of the function.
The internal variable of the function in this case is not an alias to the external variable.
The object is always a reference. The variable is simply a container to something (number, string, object). They are not always a reference to each other, unless you choose to pass it byref.

If you do
i := object()
j := i
you are not copying the object, you are copying it's reference, unique identifier, name, place in memory, pointer.
j is not the same as i either, they are two different variables.

Code: Select all

tmp := object()
; tmp as a variable contains a reference to an object
; The object reference is a value that the tmp variable will hold.
; tmp is not the object.
; Think of tmp as pointer type.
; You can see the object address in the list vars window.
; Oversimplified like tmp := 0x42314

; tmp and the object are two different entities
; tmp simply holds a pointer to it, i.e content of tmp is an object reference.
; Similar to saying tmp := 10, content of tmp is an integer.
; Think of an object reference as an integer you can't see, something like 0x42314.
; tmp, please hold this object, 0x42314
; The easiest way to access the object after the expression that created is done evaluating is through a variable.
; (maybe you can do some fuckery with NumGet, but never tried).
; dot operator and brackets work like derefencing.

tmp[1] := "hello"

function(tmp) ; Reference to object is copied to the parameter of the function
; i.e content of tmp is copied over to internal parameter of function.
; Say tmp holds an object which is: 0x42314, now copy this number to the internal variable.

msgbox(tmp[1] " " tmp[2]) ; hello world
; tmp as show above, still holds the reference to the object.


function2(tmp) ; Tmp is passed by reference.
; Its contents are not copied to the internal variable, tmp and param are emulated by autohotkey as being the same variable.
; Like a file system hard link in windows and linux.

msgbox(tmp[1] " " tmp[2]) ; Exception
; Because tmp was cleared inside function2.

function(param)
{
	; param contains a pointer to an object
	; which was copied from tmp, emphasis on copied.
	; Like 0x42314 was copied from tmp, so param now has 0x42314 as its content.
	; tmp content is 0x42314
	; param content is 0x42314
	; param and tmp point to the same object, they have the same content
	; but they are not an alias of each other.
	; Not emulated as being the same variable.
	
	param[2] := "world"
	param := ""
	; Since param is not an alias of tmp
	; blanking out param only clears the object reference inside the function
	; param no longer as 0x42314 as its content.
	; Outside variable tmp still has an object reference outside the function (still has 0x42314)
	; therefore object remains in existence outside of the function.
	; An object dies when all references to it, (no variable holds 0x42314 anymore), are cleared.
}

function2(byref param)
{
	; param is an alias of tmp.
	; Sort of like the same variable, just with a different name.
	; param and tmp, by default, both contain an object reference, since they are emulated as the same variable.
	; The object reference wasn't copied over. Param is now tmp and tmp contains the object reference.
	; so tmp := 0x42314, param is tmp, so param content is 0x42314
	
	; We set param[2] before blanking it out, futile due to below.
	param[2] := "world"
	
	param := ""
	; Since param is an alias of tmp, i.e they are the same, if you blank param
	; inside the function, it is equivalent to blanking out tmp (outside the function).
	; So now the object reference is lost both inside the function and outside the function.
	; 0x42314 is no longer the content.
	; So the object is garbage collected.
}
SAbboushi
Posts: 122
Joined: 08 Dec 2014, 22:13

Re: AHK V2: passing objects to non-byref param?

Post by SAbboushi » 03 Jul 2018, 12:30

Thanks coffee - your script made it crystal clear. Much appreciated.

Wondering though since I'm still wrapping my mind around this: can anyone provide examples of why someone might want the function to mess with "the variable which the function's caller used" other than to release the object like in coffee's VERY NICELY DOCUMENTED script?
User avatar
jeeswg
Posts: 5136
Joined: 19 Dec 2016, 01:58
Location: UK

Re: AHK V2: passing objects to non-byref param?

Post by jeeswg » 03 Jul 2018, 12:39

There are some points made here that may be relevant:
objects: passing objects ByRef to a function - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=5&t=46310
SAbboushi
Posts: 122
Joined: 08 Dec 2014, 22:13

Re: AHK V2: passing objects to non-byref param?

Post by SAbboushi » 03 Jul 2018, 13:01

Thanks jeeswg. Good stuff!
lexikos
Posts: 6175
Joined: 30 Sep 2013, 04:07
GitHub: Lexikos

Re: AHK V2: passing objects to non-byref param?

Post by lexikos » 07 Jul 2018, 01:08

In short: ByRef is typically used to provide additional return values. One would use ByRef if a new object should be constructed inside the function and returned by assigning it to the caller's variable.
Post Reply

Return to “AutoHotkey v2 Development”