Array of Arrays - [non]Automatic object creation?

Get help with using AutoHotkey and its commands and hotkeys
User avatar
joedf
Posts: 7452
Joined: 29 Sep 2013, 17:08
Facebook: J0EDF
Google: +joedf
GitHub: joedf
Location: Canada
Contact:

Array of Arrays - [non]Automatic object creation?

16 Mar 2014, 13:29

I know that according to the docs : http://ahkscript.org/docs/Objects.htm#U ... _of_Arrays
Method A will fail and Method B will automatically create an object and store it.

Code: Select all

table:=Object()
table[1][2] := "contentA"  ; A
table[3, 4] := "contentB"  ; B
MsgBox % table[1][2]
MsgBox % table[3][4]
Basically, to make Method A work, we would have to add just one more statement :

Code: Select all

table:=Object()
table[1]:=Object()
table[1][2] := "contentA"  ; A
MsgBox % table[1][2]
But what is the particular reason for this? Doesn't this possibly add more confusion?
basically it's

Code: Select all

table[1]:=Object()
table[1][2] := "contentA"  ; A
Versus

Code: Select all

table[1,2] := "contentA"  ; A
meaning that only a few characters differences... changes the behaviour from functional to non-functional
][ versus , in between the indexes...

It's good that the docs were well written, another wise, i would have never known why it would not store anything...
even adding #Warn at the top of script, it does not say it, probably because it is not a syntax error, but it would be well
for one to be notified of this, "Warning table[1][2] := "contentA" will fail since table[1] is a non-existant object" or something...

But, as I have said, is there a particular reason for this subtle difference?
2 character differences ][ versus ,? why?
Image Image Image Image Image
Windows 10 x64 Professional, Intel i5-8500, NVIDIA GTX 1060 6GB, 2x8GB G.Skill RipJaws V - DDR4 3280 MHz | [About Me] | [ASPDM - StdLib Distribution]
[Populate the AHK MiniCity!] | [Qonsole - Quake-like console emulator] | [LibCon - Autohotkey Console Library] | [About the AHK Foundation]
lexikos
Posts: 6680
Joined: 30 Sep 2013, 04:07
GitHub: Lexikos

Re: Array of Arrays - [non]Automatic object creation?

16 Mar 2014, 16:14

There's no reason to use table[1][2] := "contentA" for arrays of arrays. That's the point.

It is two operations: temp_result := table[1] and temp_result[2] := "contentA". It doesn't automatically create an object because the first operation is just retrieving a value (nothing), and the second operation has nothing to work with.
User avatar
joedf
Posts: 7452
Joined: 29 Sep 2013, 17:08
Facebook: J0EDF
Google: +joedf
GitHub: joedf
Location: Canada
Contact:

Re: Array of Arrays - [non]Automatic object creation?

16 Mar 2014, 16:39

Ok, I see. So it is treated as a double expression,
eg. (a[1])[2]
Thanks
Image Image Image Image Image
Windows 10 x64 Professional, Intel i5-8500, NVIDIA GTX 1060 6GB, 2x8GB G.Skill RipJaws V - DDR4 3280 MHz | [About Me] | [ASPDM - StdLib Distribution]
[Populate the AHK MiniCity!] | [Qonsole - Quake-like console emulator] | [LibCon - Autohotkey Console Library] | [About the AHK Foundation]
User avatar
trismarck
Posts: 506
Joined: 30 Sep 2013, 01:48
Location: Poland

Re: Array of Arrays - [non]Automatic object creation?

18 Mar 2014, 05:30

In addition to what Lexikos said:
Joedf wrote: even adding #Warn at the top of script, it does not say it, probably because it is not a syntax error, but it would be well
It is possible to debug the object syntax used with non-object values with the default base object:
Spoiler
The other difference between [,,] and [][] is the number of parameters meta-functions get.

//Edit: made an upgrade of the example code.
Last edited by trismarck on 08 Jul 2014, 14:22, edited 5 times in total.
lexikos
Posts: 6680
Joined: 30 Sep 2013, 04:07
GitHub: Lexikos

Re: Array of Arrays - [non]Automatic object creation?

18 Mar 2014, 22:11

Same difference.

The meta-function gets exactly the parameters which each object operation gets. [1][2] splits the parameters across two operations ([] denotes a parameter list), and the meta-functions getting a different number of parameters is a direct consequence of that. More importantly, the meta-functions are called differently, because different operations are performed (get and then set, rather than just set).
User avatar
trismarck
Posts: 506
Joined: 30 Sep 2013, 01:48
Location: Poland

Re: Array of Arrays - [non]Automatic object creation?

20 Mar 2014, 05:56

Yeah, turns out I haven't understood what I tested. Thanks.
lexikos wrote:The meta-function gets exactly the parameters which each object operation gets.
To clarify: in the documentation on Objects, there is an example code in the Sub-classing arrays of arrays section. In that example, upon doing x[1,2,3] := "...", the 'set' meta-function is called _two_ times. So a given meta-function can be called _multiple_ times upon performing _one_ operation; but if that is the case, then we can be sure that:
  • arguments passed to all instances of that meta-function are from the same set (vs each instance of meta-function gets exactly the same [number of] parameters)
  • only one _type_ of meta-function is called per one operation (get/set/call)
lexikos
Posts: 6680
Joined: 30 Sep 2013, 04:07
GitHub: Lexikos

Re: Array of Arrays - [non]Automatic object creation?

21 Mar 2014, 02:45

In that example, upon doing x[1,2,3] := "...", the 'set' meta-function is called _two_ times.
Not on the same object, so not necessarily the same meta-function.

The meta-function is called once as a direct consequence of invoking the object. Then, the object internally invokes a sub-object in order to emulate a multi-dimensional array. This invocation of the sub-object can cause the sub-object's meta-functions to execute.

Rather than "operation" in the sense of just what you see in the expression, I really mean "invocation" (of the object). x[1,2]:=3 is evaluated like ObjSet(x, 1, 2, 3) (where ObjSet is an internal function not directly accessible to script, though it was in early versions) while x[1][2]:=3 is evaluated like ObjSet(ObjGet(x,1),2,3).

In any case, a single invocation can execute multiple meta-functions (one from each base object/class), up until one uses return, but all of them get the same parameters.
User avatar
trismarck
Posts: 506
Joined: 30 Sep 2013, 01:48
Location: Poland

Re: Array of Arrays - [non]Automatic object creation?

07 Jul 2014, 04:47

Thank you Lexikos.
I have two minor complaints about this:
  • Meta-functions wrote:Otherwise a new key-value pair is created and stored in the object.
    This _doesn't_ happen in all but last invocation of the multi-parameter assignment operator.
  • Meta-functions wrote:Otherwise a new key-value pair is created and stored in the object.
    It is not documented what the return value of __Set is in this case; the documentation only mentions what _should_ be returned:
    Meta-functions wrote:Set: If the operation was successful, __Set should return the new value of the field, which may differ from the original r-value.
lexikos
Posts: 6680
Joined: 30 Sep 2013, 04:07
GitHub: Lexikos

Re: Array of Arrays - [non]Automatic object creation?

07 Jul 2014, 05:41

This _doesn't_ happen in all but last invocation of the multi-parameter assignment operator.
What do you mean? Please give an example. For something like x[1,2,3]:=4, new key-value pairs are created and stored in x[1], x[1][2] and x[1][2][3]. The first two are objects, and the final one is the value, 4.
It is not documented what the return value of __Set is in this case; the documentation only mentions what _should_ be returned
The return value is whatever you make it, since you write the function.

Edit: Puzzling over the context (quote), I'm not sure I understand your "complaint". The particular case you're talking about is "If (and only if) no base object handles the operation ... a new key-value pair is created and stored in the object." If __Set returned something, that counts as a base object handling the operation, and a new key-value pair is not created. That's implied, but the documentation is very explicit about what happens if __Set returns anything:
If the meta-function explicitly returns, the return value is used as the result of the operation and no further processing occurs.
User avatar
trismarck
Posts: 506
Joined: 30 Sep 2013, 01:48
Location: Poland

Re: Array of Arrays - [non]Automatic object creation?

07 Jul 2014, 07:06

Lexikos wrote:Edit: Puzzling over the context (quote), I'm not sure I understand your "complaint". The particular case you're talking about is "If (and only if) no base object handles the operation ... a new key-value pair is created and stored in the object." If __Set returned something, that counts as a base object handling the operation, and a new key-value pair is not created.
Yes. I'm talking only about the situation where _none_ of the __Set functions in the inheritance tree handles the operation. In that case, the return value of __Set is not documented. All of the examples in this post are in this context (__Set doesn't handle the operation).

Example1 - if operation is not handled by __Set, the value of the key is returned implicitly:
Example1 - if operation is not handled, __Set, returns the _value_ that was requested to be assigned to the key (~return value undocumented in this scenario):
Spoiler
Lexikos wrote:What do you mean? Please give an example.
Examples for this quote:

Example2 - non-multi-parameter assignment operator overwrites value of key at end of the first [and only] invocation:
Spoiler
Example 3 - _multi_-parameter assignment operator does _not_ overwrite value of key in all but last invocations:
Spoiler
//edit: notes pertaining to the first part of this post:
Lexikos wrote:The return value is whatever you make it, since you write the function.
Yes, I've meant: what is the value if __Set _doesn't_ explicitly return. If there is no explicit return inside of the custom-made __Set. There can be 'extra-processing' in user-defined __Set and that __Set may _still_ not handle the operation (lack explicit return).
Last edited by trismarck on 08 Jul 2014, 17:02, edited 1 time in total.
User avatar
trismarck
Posts: 506
Joined: 30 Sep 2013, 01:48
Location: Poland

Re: Array of Arrays - [non]Automatic object creation?

08 Jul 2014, 16:51

After additional analysis:
  • Meta-functions wrote:Otherwise a new key-value pair is created and stored in the object.
    What is the meaning of this quote in the context of _more than one_ key being passed as parameter to __Set()? (if more than one key passed, there is no key-value pair anymore, there is a key1, key2, value triplet)
  • At what point does the multi-parameter assignment algorithm trigger if the object, upon which the multi-parameter assignment operator was invoked, also has bases with __Set meta-functions? Does MPAA trigger directly _after_ the last __Set in the inheritance tree has finished working? - like this:
    • invoke object with multi-parameter assignment operator (invoke this particular invocation)
    • call all __Set's in the inheritance tree (which may set the value of key to something custom and still not return explicitly)
    • run MPAA algorithm (determine what value is inside of key)
    • initialize key with empty object, if needed
    • invoke object under key, if required (calling __Set's of that object, in turn, as part of another invocation)
lexikos
Posts: 6680
Joined: 30 Sep 2013, 04:07
GitHub: Lexikos

Re: Array of Arrays - [non]Automatic object creation?

08 Jul 2014, 17:15

I think you're asking the wrong question. If __Set doesn't explicitly return, clearly the return value of __Set was "", as with all other functions.

What you probably meant is that the documentation doesn't say what the result of the operation is when __Set doesn't return a value. This is because it is not specific to meta-functions. Assignments return the value being assigned. Otherwise there's nothing to return, so nothing is returned.
Example1 - if operation is not handled by __Set, the value of the key is returned implicitly:
Your example does not demonstrate that at all. It discards the return value of the assignment.

Code: Select all

class cx {
    __Set(k) {
        MsgBox, % "__Set: cx"
    }
}

x := new cx()
return_value := x[1] := "chicken"
MsgBox % x[1]  ; Retrieves the value from the object.
MsgBox % return_value  ; Displays the RETURN VALUE.
Okay, so I think your point is that if __Set specifically assigns the key-value pair but then doesn't return a value, a new key-value pair is not necessarily created after __Set returns. The key here is "processing will continue as normal". The documentation doesn't describe, in great detail, every aspect of the normal processing. It only seems to matter in this specific, rare case.

Technically a new key-value pair was created, but in __Set... ;)
What is the meaning of this quote in the context of _more than one_ key being passed as parameter to __Set()?
Only one key is relevant; the one that would be found in the object. For instance, x[1,2], x[1] is assigned a new object and for that new object, ..[2] is assigned the value.
Does MPAA trigger directly _after_ the last __Set in the inheritance tree has finished working?
Yes; at the same point an assignment is normally carried out. However, a base class may also define a value for the key. For example,

Code: Select all

class cy {
    foo := {bar: "baz"}
}
class cx extends cy {
}
x := new cx()
x.foo[1] := 2
MsgBox % x.foo[1] " " x.foo["bar"]
I'm not sure about your bullet points - there's no distinct "MPAA algorithm"; it's mixed with the other inheritance and assignment code.
User avatar
trismarck
Posts: 506
Joined: 30 Sep 2013, 01:48
Location: Poland

Re: Array of Arrays - [non]Automatic object creation?

13 Jul 2014, 16:24

Lexikos wrote:I think you're asking the wrong question. If __Set doesn't explicitly return, clearly the return value of __Set was "", as with all other functions.

What you probably meant is that the documentation doesn't say what the result of the operation is when __Set doesn't return a value. This is because it is not specific to meta-functions. Assignments return the value being assigned. Otherwise there's nothing to return, so nothing is returned.
Example1 - if operation is not handled by __Set, the value of the key is returned implicitly:
Your example does not demonstrate that at all. It discards the return value of the assignment.

Code: Select all

class cx {
    __Set(k) {
        MsgBox, % "__Set: cx"
    }
}

x := new cx()
return_value := x[1] := "chicken"
MsgBox % x[1]  ; Retrieves the value from the object.
MsgBox % return_value  ; Displays the RETURN VALUE.
Yes, example1 was flawed, because the example I originally wrote was showing something else and I've just re-crafted the example, so that the stream of thinking in the post is more or less consistent, but at the same time I've broken the example. Thanks. Also, I wasn't aware of the fact that, in case of an assignment, it is possible that the assignment operation itself will define the return value of the assignment (vs the return value is always the result of the meta-function).
Lexikos wrote:Otherwise there's nothing to return, so nothing is returned.
I guess this quote is about the scenario in which __Set would be called _directly_ (vs as a result of an assignment operation).
Lexikos wrote:Okay, so I think your point is that if __Set specifically assigns the key-value pair but then doesn't return a value, a new key-value pair is not necessarily created after __Set returns.
Yes, that is _exactly_ my point ... but the reasoning behind that point was different.
Lexikos wrote:The key here is "processing will continue as normal". The documentation doesn't describe, in great detail, every aspect of the normal processing. It only seems to matter in this specific, rare case.

Technically a new key-value pair was created
I guess _you_ have put an emphasis on the word "pair" (vs a triplet or quadruplet). This was _also_ what _I_'ve originally put an emphasis on, but _again_, the reasoning behind putting an emphasis on the word _pair_ was _different_:
Lexikos wrote: , but in __Set... ;)
What is the meaning of this quote in the context of _more than one_ key being passed as parameter to __Set()?
Only one key is relevant; the one that would be found in the object. For instance, x[1,2], x[1] is assigned a new object and for that new object, ..[2] is assigned the value.
So this quote presumably 'translates' what _normal processing_ means, if there is _more_ than one key. Ok.
Lexikos wrote:
Does MPAA trigger directly _after_ the last __Set in the inheritance tree has finished working?
Yes; at the same point an assignment is normally carried out.
Now the key phrase here that I was lacking is "the assignment is carried out".

-------------------------------------
Lexikos reasoning was this:
If (and only if) no base object handles the operation, processing will continue as normal:
•Set: If the key is "base", the object's base is set; non-object values cause the existing base to be removed.
Otherwise a new key-value pair is created and stored in the object.
In case of a multi-parameter assignment operation, in the first, second and all but last invocations, there is no key-value _pair_ being the argument of the operation, there is rather a _vector_ of _multiple_ keys an one value being the argument of the operation. So it [kind of] makes no sense to say that the normal processing will insert a key-value _pair_, because we don't know, in _which_ key the object will be stored. So Lexikos clarified that the key-value pair is created from the _first_ key in the vector. I also agree on the sentence with "_technically_": _in general_, _technically_, a key-value _pair_ _is_ always inserted into the object.
_My_ reasoning was this:
In case of a multi-parameter assignment operation, in the first, second and all but last invocations, there is no key-value _pair_ being the argument of the operation, there is rather a _vector_ of _multiple_ keys an one value being the argument of the operation. So, after the last __Set in the inheritance tree returns and doesn't handle the operation, the documentation says that a key-value is [always] inserted into the object. Now my point is this: _regardless_ of how many keys we currently have in the vector of parameters, instead of saying: "the key-value pair is stored in the object", the documentation should have said:
Otherwise a new key-value pair is created and stored in the object.
Otherwise, the _assignment operation_ is carried out
This is because the key-value pair is _not_ always created, because the assignment operation may abort operation/not store the object in the key if there already is an object under the key. The assignment operation may abort in case of a _multi_-parameter assignment operation:
Arrays of Arrays wrote:Multi-dimensional assignments such as table[a, b, c, d] := value are handled as follows:

•If there is only one key remaining, perform the assignment and return. Otherwise:
•Search the object for the first key in the list.
•If a non-object is found, fail.
•If an object is not found, create one and store it.
•Recursively invoke the sub-object, passing the remaining keys and value - repeat from the top.
Example1: a non-object prevents the key-value pair to be inserted:
Spoiler
Example2: - see example3 in the previous post - the object that exists in the requested key makes the assignment operation _not_ to insert an empty object into that key. The object under the key is just _checked_ if it's there and if it's there, it's just _left_ as it was.
Lexikos wrote:However, a base class may also define a value for the key. For example,

Code: Select all

class cy {
    foo := {bar: "baz"}
}
class cx extends cy {
}
x := new cx()
x.foo[1] := 2
MsgBox % x.foo[1] " " x.foo["bar"]
I guess this example was written to show one, that the object _doesn't_ have to be assigned (~stored) in the key inside of __Set. The key may be initialized with the object _earlier_, i.e. when an instance of a class is created. I haven't thought doing it like this, thanks. To clarify, this example is sort of 'another issue' as compared to what the rest of this post describes.
Lexikox wrote:I'm not sure about your bullet points - there's no distinct "MPAA algorithm"; it's mixed with the other inheritance and assignment code.
By the MPAA algorithm (or actually, by the 'assignment carried in' algorithm), I've just meant this part of the documentation:
Arrays of arrays wrote:Multi-dimensional assignments such as table[a, b, c, d] := value are handled as follows:

•If there is only one key remaining, perform the assignment and return. Otherwise:
•Search the object for the first key in the list.
•If a non-object is found, fail.
•If an object is not found, create one and store it.
•Recursively invoke the sub-object, passing the remaining keys and value - repeat from the top.
//edit:
Instead of MPAA, I should have said MDAA - (multi _dimensional_ assignment algorithm) - I've just called that algorithm wrongly from the beginning.

Another ambiguity I see now is that there could be three meanings of the word 'operation':
  • a["b", "c", "d"] := 3 - an assignment operation
  • (a["b"])["b", "c", "d"] := 3 - lets suppose this expression symbolizes is one _invocation_ of the operation (~also an operation?)
  • the _core_ assignment [_operation_] that happens during _every_ _invocation_: namely when the last __Set in the inheritance tree doesn't handle the operation and 'the assignment operation is carried out' (so perhaps 'carried out' here means that the flow of execution of the assignment operation (which one? operation/invocation) just _continues_ [its normal processing]).
lexikos
Posts: 6680
Joined: 30 Sep 2013, 04:07
GitHub: Lexikos

Re: Array of Arrays - [non]Automatic object creation?

14 Jul 2014, 03:38

trismarck wrote:I guess this quote is about the scenario in which __Set would be called _directly_ (vs as a result of an assignment operation).
No, I was talking about "get" and "call" operations.
I guess _you_ have put an emphasis on the word "pair" (vs a triplet or quadruplet).
No. There is a key-value pair in each object: for x[1,2,3], x, x[1] and x[1][2]. x itself only stores the "top dimension" - the first parameter becomes the key, while a new object becomes the value. Actually, I didn't have multi-dimensional arrays in mind when I wrote it; the explanations apply to each object involved individually: for x[1,2,3], there is x and might be x[1] and x[1][2] (or they might be created by the operation).
This is because the key-value pair is _not_ always created, because the assignment operation may abort operation/not store the object in the key if there already is an object under the key.
You're forgetting something:
Objects wrote:Meta-functions are methods defined by an object's base which can define exactly how the object should act when an unknown key is requested.
Before any of the logic we're talking about is applied, it has been established that the key does not already have a value associated with it. If it has a value, the meta-function is not called.
trismarck wrote:Another ambiguity I see now is that there could be three meanings of the word 'operation':
...
the _core_ assignment [_operation_] that happens during _every_ _invocation_: namely when the last __Set in the inheritance tree doesn't handle the operation
But it doesn't happen during every invocation. Also, the following references to "the operation" contradict the last of your "three meanings":
If the meta-function explicitly returns, the return value is used as the result of the operation
...
Set: If the operation was successful, __Set should return the new value of the field,
(a["b"])["b", "c", "d"] := 3 - lets suppose this expression symbolizes is one _invocation_ of the operation (~also an operation?)
I don't know what point you're trying to make, but this is two operations: a["b"], followed by something["b", "c", "d"] := 3, where something is the result of the first operation. This is reflected in the meta-function calls, which would be a.__Get("b") and something.__Set("b", "c", "d", 3).

Multiplication is an operation. A function call is an operation. a["b", "c", "d"] := 3 is an operation, like a function call with 5 parameters: ObjSet(a, "b", "c", "d", 3). However, this last case can result in additional operations which can each cause a meta-function to be called: something1["c", "d"] := 3 and something2["d"] := 3. This is how multi-parameter assignments work.
User avatar
trismarck
Posts: 506
Joined: 30 Sep 2013, 01:48
Location: Poland

Re: Array of Arrays - [non]Automatic object creation?

14 Jul 2014, 06:09

Lexikos wrote:
trismarck wrote:I guess this quote is about the scenario in which __Set would be called _directly_ (vs as a result of an assignment operation).
No, I was talking about "get" and "call" operations.
I don't get that sentence. Obviously either __Get or __Call _can't_ be directly triggered by an _assignment_ operation. But, even if __Get and __Call can be triggered by some other operation (get value of key, call a method), _something_ is returned as a result of the operation (because every operation returns something). Perhaps the sentence was meant to mean: otherwise, when [any] meta-function is called and it doesn't explicitly return, nothing is returned _from the meta-function_. But the result of the _operation_ may still define its own return value.
//edit:
Ok, I guess the quote is about the following:
Meta-functions wrote:•If this is a get or call operation, search for a matching key in the base object's own fields.
Get: If found, the value of that field is returned.
Call: If found, the function stored in the field (by name or reference) is called, passing the original target object as the this parameter.
While the assignment can always return the requested value, even if requested key is not present in the object/its bases, a get value of key or a function call simply can't return anything, when there is nothing found in the inheritance tree (and thus nothing is returned).

(note to self) Also note that while __Get and __Call _do_ perform this additional step of searching for a key, __Set does not.
Lexikos wrote:
This is because the key-value pair is _not_ always created, because the assignment operation may abort operation/not store the object in the key if there already is an object under the key.
You're forgetting something:
Objects wrote:Meta-functions are methods defined by an object's base which can define exactly how the object should act when an unknown key is requested.
Before any of the logic we're talking about is applied, it has been established that the key does not already have a value associated with it. If it has a value, the meta-function is not called.
But an _unknown_ key _is_ requested _every_ time (~in examples 2 and 3 provided above). At the beginning of a particular _invocation_ of the multi-dimensional assignment operation, the key has _no_ value (actually, there isn't even a key at that point). __Set stores the value in the key Inside of the user-written __Set (__Set which doesn't explicitly return) the key is initialized with a value, but _at the beginning_ of the invocation, the object _didn't_ have that key. So that would mean that the 'unknown key requested' logic does apply in this scenario. Also, if the object _would_ have a key, why does __Set trigger at beginning of every invocation in Example 3. It looks like I have an incorrect definition on what an operation is.
Lexikos wrote:
trismarck wrote:Another ambiguity I see now is that there could be three meanings of the word 'operation':
...
the _core_ assignment [_operation_] that happens during _every_ _invocation_: namely when the last __Set in the inheritance tree doesn't handle the operation
But it doesn't happen during every invocation.
I don't get it. The core assignment operation _does_ happen during every invocation. What I mean by the _core_ assignment operation is the MDAA algorithm quoted before. MDAA happens always. The first bullet happens when there is only one key and the rest of the algorithm happens when there is more than one key. Note that by the core assignment operation, I _don't_ mean that the key-value pair is inserted into the object. The key-value pair may not be inserted, if there already is an object under that key (~object that one of the __Set meta-functions has inserted, when an _unknown_ key was requested from an object at the beginning of the invocation) or when there is already a non-object value under that key (also inserted by __Set in the exact same scenario). By the core assignment operation I mean the execution of the MDAA algorithm. MDAA happens _always_ in the scenario in which the last user-defined __Set in inheritance tree ends and doesn't explicitly return.
Lexikos wrote:Also, the following references to "the operation" contradict the last of your "three meanings":
If the meta-function explicitly returns, the return value is used as the result of the operation
...
Set: If the operation was successful, __Set should return the new value of the field,
Lexikos wrote:
(a["b"])["b", "c", "d"] := 3 - lets suppose this expression symbolizes is one _invocation_ of the operation (~also an operation?)
I don't know what point you're trying to make, but this is two operations: a["b"], followed by something["b", "c", "d"] := 3, where something is the result of the first operation. This is reflected in the meta-function calls, which would be a.__Get("b") and something.__Set("b", "c", "d", 3).
Ok, I get this. I've just meant one invocation. (as if tmp["b", "c", "d"] := 3 was invoked, tmp["b"] would get a value and that invocation would then stop). I only wrote the three bullet points to _differentiate_ between possible meanings one could derive from the word 'operation'. The examples were just an additional part of the explanation, to visualize what I mean. That second example may have been unfortunate, I admit.
Lexikos wrote:Multiplication is an operation. A function call is an operation. a["b", "c", "d"] := 3 is an operation, like a function call with 5 parameters: ObjSet(a, "b", "c", "d", 3). However, this last case can result in additional operations which can each cause a meta-function to be called: something1["c", "d"] := 3 and something2["d"] := 3. This is how multi-parameter assignments work.
So the _multi-parameter_ assignment is not a _single_ operation, but the assignment in general _is_ an operation? So perhaps it would be better to call multi-parameter assignment a _sequence_ of operations and then one could say that a multi-parameter assignment _operation_ (vs the multi-parameter assignment) _would_ indeed be a _single_ operation.
  • multi-parameter assignment - sequence of operations
  • single-parameter assignment - an operation
  • multi-parameter assignment _operation_ - an operation
  • assignment operation - incorrect, because an assignment can either be a single operation or a sequence of operations. But perhaps one could say that a single operation is _also_ a sequence of operations, there is just only one element in the sequence...
So again:
  • multi-parameter assignment - sequence of operations
  • single-parameter assignment - an operation (or a sequence of operations with one element)
  • multi-parameter assignment _operation_ - an operation
  • assignment operation - a sequence of operations?
I'd say bullet 4 is still ambiguous - one operation is multiple operations.
//edit-----------------------------
After rethinking, perhaps I've misunderstood this quote:
Lexikos wrote:What you probably meant is that the documentation doesn't say what the result of the operation is when __Set doesn't return a value. This is because it is not specific to meta-functions. Assignments return the value being assigned.
I've thought that assignment is like a function call - an operation?
Is an assignment an operation?
Is a single-parameter assignment an operation?
is a multi-parameter assignment an operation?
If an assignment is not an operation, what additional steps does the assignment algorithm do in addition to 'enwrapping' an algorithm that performs an operation?

Also, that quote:
Arrays of Arrays wrote:Multi-dimensional assignments such as table[a, b, c, d] := value are handled as follows:

•If there is only one key remaining, perform the [single-parameter] assignment and return
would indicate that a multi-parameter assignment is an algorithm whose single-parameter assignment is _part of_. If that is the case, then what's an assignment? I'd say that the assignment is an algorithm of _multi_-parameter assignment. That definition would be ok for single-parameter assignments also, because the multi-parameter assignment algorithm _contains_ the single-parameter assignment algorithm.
lexikos
Posts: 6680
Joined: 30 Sep 2013, 04:07
GitHub: Lexikos

Re: Array of Arrays - [non]Automatic object creation?

14 Jul 2014, 21:49

This has gotten tedious. Is there something you don't understand, or are we just debating semantics?
Obviously either __Get or __Call _can't_ be directly triggered by an _assignment_ operation.
I said something like "Assignments <statement about assignments>. Otherwise <statement about every other type of operation, i.e. get and call>."
But an _unknown_ key _is_ requested _every_ time
You said "if there already is an object under the key". In that case, it is not an "unknown key". The key already has a value associated with it (an object) and therefore no meta-function will be called for that key. A meta-function might be called on the sub-object, after eliminating that key from the parameter list. In that case, the original target object can be excluded from consideration because none of the meta-functionality is being applied to it.
The core assignment operation _does_ happen during every invocation.
I think we disagree as to what "the core assignment" means. In any case, the multi-parameter logic does not necessarily run if __Set returns a value.
I've thought that assignment is like a function call - an operation?
The operation is whatever caused the meta-function to be called.
So the _multi-parameter_ assignment is not a _single_ operation, but the assignment in general _is_ an operation?
Is a function call a single operation, if that function calls other functions? This is the same.

Stop focusing on this one term; as with most English words, it can mean different things in different contexts. If you don't understand some part of the documentation it is used in, ask about that.
If that is the case, then what's an assignment?
Again, it depends on the context. := is the assignment operator. Any sub-expression which uses it is an assignment. Assignment might also occur internally (i.e. the storage of a value in a container).
User avatar
trismarck
Posts: 506
Joined: 30 Sep 2013, 01:48
Location: Poland

Re: Array of Arrays - [non]Automatic object creation?

15 Jul 2014, 08:31

Lexikos wrote:This has gotten tedious. Is there something you don't understand, or are we just debating semantics?
I'd say, semantics needs to be debated to help one to understand why the documentation was written the way it was written.
Lexikos wrote:
Obviously either __Get or __Call _can't_ be directly triggered by an _assignment_ operation.
I said something like "Assignments <statement about assignments>. Otherwise <statement about every other type of operation, i.e. get and call>."
Ok, I've finally got that part.
Lexikos wrote:
But an _unknown_ key _is_ requested _every_ time
You said "if there already is an object under the key". In that case, it is not an "unknown key". The key already has a value associated with it (an object) and therefore no meta-function will be called for that key. A meta-function might be called on the sub-object, after eliminating that key from the parameter list. In that case, the original target object can be excluded from consideration because none of the meta-functionality is being applied to it.
Yes, the implied context was: "if there already is an object under the key, supposing that there was no key in the object at beginning of invocation and during that same invocation, user-made __Set was used to store an object into the key", which I haven't specified, thus the sentence was really about an other scenario. Thanks.

Lexikos wrote:I think we disagree as to what "the core assignment" means.
Yes. I mean MDAA (which is kind of pointless, since MDAA may decide not to assign), I think you mean: in case of multi-parameter assignment: "the part of MDAA that effectively assigns the value to the key" or in case of a single parameter-assignment: when the key effectively gets the value. But please lets leave this aside, as I might even be wrong as it again might depend on the context.

Lexikos wrote:
The core assignment operation _does_ happen during every invocation.
[...]In any case, the multi-parameter logic does not necessarily run if __Set returns a value.In any case, the multi-parameter logic does not necessarily run if __Set returns a value.
Yes, I should have been more clear - the context was: if __Set doesn't handle the operation. If any __Set in any invocation of the operation _does_ explicitly return, the return is treated as if the _whole_ operation (multiple invocations) was successful and even if, at that point, the requested key of the currently invoked object contains an object, the whole operation will end and the object under that key will not be invoked.
Lexikos wrote:
So the _multi-parameter_ assignment is not a _single_ operation, but the assignment in general _is_ an operation?
Is a function call a single operation, if that function calls other functions? This is the same.
I admit I haven't thought about the operation this way. By the analogy, I've thought about the operation as a sequence of function calls, called in turn, not as a function which calls a function which calls a function and then the outermost function returns. But this could again be my mistake, because the result of the whole operation depends on the results of invocations. And, nesting of functions also occurs in the source code:

Code: Select all

return obj->Invoke(aResultToken, obj_token, aFlags & ~IF_META, aParam + 1, aParamCount - 1);
Lexikos wrote:Stop focusing on this one term; as with most English words, it can mean different things in different contexts. If you don't understand some part of the documentation it is used in, ask about that.
Lexikos wrote:
If that is the case, then what's an assignment?
Again, it depends on the context.
Ok.

-----------------------------------------
So to reiterate after what I've learned:
  • the description of what happens when an unknown key is requested from the object in the documentation on Meta-functions doesn't describe how meta-functions behave when the operation is the _multi_-parameter assignment (or the multi-parameter get operation, in case of __Get, but lets focus on __Set for now as this is the only thing I've tested).
  • Especially, I'd like this part of the documentation to be changed:
    Meta-functions wrote:•Set: If the key is "base", the object's base is set; non-object values cause the existing base to be removed.
    Otherwise a new key-value pair is created and stored in the object.
    Into something like this:
    • Set: If the key is "base", the object's base is set; non-object values cause the existing base to be removed.
      • Otherwise:
        • in case of a single-parameter assignment:if just one key was requested:
          • a new key-value pair is created and stored in the object
            • Note that if inside of __Set, the user has stored a value under that key, the value of that key _will_ be overwritten at this point. (*1)
        • in case of a multi-parameter assignment:if more than one key was requested:
          • the following section of the documentation describes of whether the key-value pair is stored in the object or not: Arrays of Arrays
            • Note that if inside of __Set, the user has stored a value under that key, the value of that key will _not_ be overwritten.(*2)
Comments on some of the bullets:
  • 1 - in single-parameter assignments, we don't care if the user stores object in key in user-defined __Set and then doesn't handle operation, because this (storing and not handling operation) is generally considered bad practice, unless the value of the key would need to be passed to __Set of one of the bases of the object for further processing. See Example 2.
  • 2 - in multi-parameter assignments, we _do_ care if user stores object in key, because the expectation is that the stored object could be used to sub-class the multi-dimensional array. So in this case, the fact that the key is _not_ overwritten _should_ be documented (if the value of key was overwritten, sub-classing would simply not work). Example:
    Spoiler
//edit: if the change to the documentation is not specific to meta-functions, perhaps a separate section in the documentation (related to assignments) could be created.
lexikos
Posts: 6680
Joined: 30 Sep 2013, 04:07
GitHub: Lexikos

Re: Array of Arrays - [non]Automatic object creation?

15 Jul 2014, 20:46

The documentation for objects is not intended as a technical specification, or to cover all the inner workings and describe every scenario in detail. It was written like a technical document originally and users complained that it was too hard to understand. It has since been dumbed down, and at least fewer users complain...

Return to “Ask For Help”

Who is online

Users browsing this forum: Google [Bot], peter9999, vsub, willwilliamsdh and 297 guests