I intentionally separated these replies (excluding the last one) from my previous post, then forgot to post them.
Sean wrote:
__Get/__Set doesn't support parameters?
They do, but they have the usual problem when it comes to detecting how many were passed:
Quote:
Each meta-function can accept only as many individual parameters as it defines; excess parameters are discarded. Since the r-value of a "set" operation is treated as the final parameter, it is the first to be discarded if too many parameters are passed.
Although a varying number of parameters can be handled by declaring some as optional, the actual number of available parameters can be determined only by comparing each parameter to its default value. Consequently, a value must be reserved for this purpose.Source: AutoHotkey_L - Objects: Meta-Functions (Known limitations) However,
obj.item[n]:=v currently translates into
ObjSet(ObjGet(obj,"item"),n,v), which mightn't be intuitive with COM. I intend to make it equivalent to
obj["item",n]:=v which translates into
ObjSet(obj,"item",n,v). With the default behaviour described under
Arrays of Arrays, it'll end up doing the same thing except that
obj.item can be automatically initialized.
HotKeyIt wrote:
Why is set function not launched when a key is removed?
As explained in
the documentation, __Set is invoked when a new key-value pair is about to be created. It is not invoked if the key-value pair already exists, even if it is being changed or removed. It's loosely based on Lua's
__newindex metamethod.
Quote:
Is there another way to do that?
Don't store values in the object directly.
Code:
x := Object("", Object() ; MUST be set before base.
, "base", Object("__Set", "x_Set", "__Get", "x_Get"))
x.A := "Apple" ; Sets x[""].A via x_Set.
x.B := "Bravado"
MsgBox % x.A ; Retrieves x[""].A via x_Get.
MsgBox % x.C ; Returns an empty value since x[""].C doesn't exist.
MsgBox % x["","B"] ; Bypasses x_Get.
x_Set(x, n, v)
{
MsgBox, 0, %A_ThisFunc%, % n "=" v
; Store the value in our real storage object and return its result
; to indicate that no new key-value pair should be created.
return x["",n] := v
}
x_Get(x, n)
{
; Retrieve the value from our storage object. This should never recurse
; because x_Get would only be called if x[""] doesn't exist, and we made
; sure to store an object in it before associating this meta-function with x.
v := x["",n]
MsgBox, 0, %A_ThisFunc%, % n "=" v
return v
}
To prevent direct access (i.e.
x["","B"]), you may use a private object as a key instead of "".
ahklerner wrote:
how can i make this work?
Here's the documentation for the new feature:
Quote:
To cast an address previously retrieved via address := &object back into a usable object reference, use Object(address). This is an advanced feature which should be used only with caution; see Reference Counting. It may be useful for associating an object with a callback via A_EventInfo.Source: AutoHotkey_L - Objects: Object() Quote:
However, taking the address of an object (via address := &object) does not increment its reference count. To ensure the address remains valid when all other references to the object are released, follow this example:
Code:
; Increment the object's reference count to "keep it alive":
DllCall(NumGet(NumGet(address+0)+4), "uint", address)
...
; Decrement the object's reference count to allow it to be freed:
DllCall(NumGet(NumGet(address+0)+8), "uint", address)
Source: AutoHotkey_L - Objects: Reference-Counting Example (oversimplified--passing by address is entirely unnecessary in this case):
Code:
e := object()
func(&e)
MsgBox % e.text
return
func(ObjAddress) {
Object(ObjAddress).text := "some text"
}
Be warned that although Object() detects some obvious errors, attempting to use an invalid address (such as the address of an object which has been deleted) will likely crash the script.
infogulch wrote:
ahklerner: I think this would have more to do with a general variable Alias() function than objects specifically, though it might be especially nice for objects.
The problem with passing variables via A_EventInfo is that each callback must have its own, uniquely-named variable. Objects aren't as tightly bound to the script.
Quote:
Alias(newVar, A_EventInfo+0) ; possible syntax for your example
It's been done already; see
LowLevel (__getVar and __alias) or
AutoHotkey.dll (getVar and alias). Just don't try to hand it an object's address; objects and variables are two very different things.
Quote:
Now that we have objects, a handy function definition sugar would be to allow the last param in the definition be passed as an object that contains all remaining params from the caller.
I plan to implement that functionality, but not necessarily with new syntax.
Quote:
It would be especially handy for the object __call meta function, since it handles an arbitrary number of params
__Get and __Set also accept multiple parameters, but since there isn't yet any clean way to handle it in script, none of my examples have shown it. Part of the problem is that there's no easy way to pass a variable number of parameters to a function, as your Default_Call example demonstrates.
Quote:
A somewhat similar idea, perhaps the "opposite" of the above, is to dynamically turn an object into multiple params.
Although I'm not in favour of overloading "*", I appreciate your suggestion.
HotkeyIt wrote:
Since you can pass on an object address as a parameter to a function,
I think you're missing something; specifically, that objects can be passed by
reference, by simply removing &. Please note,
Quote:
This is an advanced feature which should be used only with caution
HotkeyIt wrote:
o.__Delete()
__Delete() should not be called explicitly unless you want it called
twice. In that particular case it doesn't appear to exist anyway.
Quote:
Return Object("base",Object(...))
I would recommend creating a single base object and using it for each WideObject. COMo shows how simple it is. Creating a new base object for each new object more or less defeats the main point of that feature.