Objects - preview of upcoming changes

Discuss the future of the AutoHotkey language
lexikos
Posts: 6397
Joined: 30 Sep 2013, 04:07
GitHub: Lexikos

Re: Objects - preview of upcoming changes

06 May 2019, 17:08

I have updated the script to utilize the __Item property added in v2.0-a101.

The x.Item[y] properties are removed. Use x[y] instead. When the script performs recursion into a property, such as with obj.prop[y] or arr[x, y], it now uses v[y] instead of v.Item[y]. To handle this in custom objects, override __Item rather than Item.

Do not use x[y] to access properties or methods. Use x.%y% instead.

__Item (added in v2.0-a101) is not intended to be invoked directly, and I felt that Item was too common a name to reserve. By contrast, the Item property in previous versions of this script had to be invoked directly, so I left out the underscores.


@Helgef I think I've demonstrated that any decision I make during the (very long) alpha stage is not necessarily final. At this point, it made much more sense to extend the %expr% syntax than to add something new or overload something that had a different meaning before. I also figured that it will be used considerably less often than the indexing operator [].

I do not like <fn>(), and would not even if it was not ambiguous. a <b>(c) is a valid but strange way to use the comparison operators. (If the parser was more flexible, I would perhaps interpret it as a < b && b > c, and a < b < c would be a < b && b < c.)

(obj[expr])() would mean obj[expr].Call(), as the context of "invoking obj" is limited to inside the parentheses. obj[expr]() is still unambiguous (and allowed in the current build), but I thought it best for properties and methods to be consistent. If () is allowed as the call operator on any expression, obj[expr]() should probably also mean obj[expr].Call() (or perhaps obj[expr].Call(obj) if the () binds more closely to the previous operator).
User avatar
kczx3
Posts: 833
Joined: 06 Oct 2015, 21:39

Re: Objects - preview of upcoming changes

10 May 2019, 18:52

Just wanted to say thanks for all the "Note" messages on the documentation for Objects in v2 . It definitely helps in understanding what is still to change.
lexikos
Posts: 6397
Joined: 30 Sep 2013, 04:07
GitHub: Lexikos

Re: Objects - preview of upcoming changes

10 May 2019, 19:47

I probably should have added more notes to the Object method documentation, but it wasn't a priority since: 1) I was more concerned with getting the build released by the end of the day; and 2) I was planning to start making the bigger script-breaking changes immediately anyway. (v2.0-a102 shows that I got a bit side-tracked, but some of it touches on what I've started doing with Array and the more fundamental changes that are planned.)

One can see how things are likely to turn out by using Object.ahk or looking at its documentation. If someone wants to volunteer to update the documentation with more cautionary notes, please do so and submit a pull request. However, depending on how things go over the next four days (I have off work), it might be redundant. On the other hand, the v1 documentation should perhaps get some attention too.



So far the only change I anticipate to how things are in Object.ahk (that I can recall) is with bound checking for arrays. I intend to support a[i++] := v as a means to grow the array, but aside from allowing a[a.Length+1] := v, any out of bounds access should be prohibited. Otherwise, attempting something like a[hwnd] := v might succeed, but actually increase the length and capacity of the array by a very significant amount. If it is intentional, the script should do a.Length := hwnd first.

Since a[n] is equivalent to a[n+a.Length+1] when n <= 0, a[0] := v is equivalent to a.Push(v) when a[a.Length+1] := v is permitted.
Helgef
Posts: 3777
Joined: 17 Jul 2016, 01:02
Contact:

Re: Objects - preview of upcoming changes

11 May 2019, 02:40

lexikos wrote: I think I've demonstrated that any decision I make during the (very long) alpha stage is not necessarily final.
Yes.
I do not like <fn>(), and would not even if it was not ambiguous.
That is fine, but do you like %fn%()? I think expr in %expr% is mostly just var, so it doesn't matter much that two %s doesn't work as brackets. <> doesn't work with implicit concatenation, it doesn't work to do partial%name%. But, removing implicit concatenation might be a good idea anyways, and likewise, there is no need to support partial%name%, since %% now takes any expression. I think it is better to remove partial%name% and along with it any mention of pseudo-arrays. No user searching for arrays in ahk should risk encountering and wasting time on pseudo-arrays. Perhaps * expr and * expr (), it is easy to type and non-blob like. I like the *expr syntax in v1, although it is not very useful. If you scrap %% for vars and funcs, I wouldn't mind keeping %% for #include.
I thought it best for properties and methods to be consistent
If you let the brackets [ ] be used for calclated names, methods, properties and indices can all be consistent, with the exception that indices cannot be accessed with any literal notation (unless you come up with something). I do not think calculated var and func names (refs) necessarily needs to be consistent with object notation. A summary of ideas to look at,

Code: Select all

; Calculated names:
; A
obj[index]
obj.*prop
obj.*method()
*var
*fun()

; B
obj[index]
obj<prop>
obj<method>()
<var>
<fun>()

; C
obj[index]
obj.[prop]
obj[method]()
%var%
%fun%()

; D (now)
obj[index]
obj.%prop%
obj.%method%()
%var%
%fun%()
I think C is better than D, and very uncontroversial. Again, there is really no need for obj.partial%name%()

Syntax aside, I'm very excited about the more impactful changes you are making :thumbup:.

So far the only change I anticipate to how things are in Object.ahk (that I can recall) is with bound checking for arrays. I intend to support a[i++] := v as a means to grow the array, but aside from allowing a[a.Length+1] := v, any out of bounds access should be prohibited
Specifically a[a.Length+1] would be a common out of bounds error I believe, allowing it might greatly reduce the usefulness of oob checks. Allowing a.push to expand would suffice.
a[0] := v is equivalent to a.Push(v) when a[a.Length+1] := v is permitted.
This doesn't seem beneficial at all, first, v := a[0] wouldn't work which is a symetrical disturbance in my view, second, a[0] := v also makes a looking like it's zero-based. Especially repeated use would look wired,

Code: Select all

loop x
	a[0] := y	; :(
loop x
	a.push y	; :)
Further, a[0] might also be a common out of bounds error, for example from something like a[--i] := v in a loop which does one iteration more than intended.

Overall, I very much appreciate out of bound checks.

Cheers.


Edit:
@lexikos , since
lexikos wrote: I considered .[] and a bunch of other ideas over several years, and my conclusion was that if it does the same thing as %expr% (substitute an expression for an identifier), it should use that syntax even if no one really likes percent signs.
I do not think this discussion is going to lead anywhere and I do not want to further derail this topic, I only leave a few comments,
Leaving partial%name% as an error?
Yes, if it is disabled it should either yield an error or have some other meaning.
Pseudo-arrays will still be possible with %"partial" name%, but uglier.
Exactly why there is no need to support partial%name%, since %% now takes any expression.
Parameter lists have higher precedence than any preceding operator, so *expr(x) would call the function expr() and dereference whatever it returns.
My thought was that *expr() would be equivalent to %expr%(), to do %(%expr%())%, it would be **expr(), that is, in effect *() is a sequence rather than two distinct operators, I think it is similar to []().
Why should methods and properties be consistent with indices but inconsistent with variables and functions? Methods and properties are meant to be distinct from array elements, not consistent with them.
It seems to me, that it makes more sense to have a consistent object syntax, than a object syntax which is partially consistent with variable and func, and partially inconsistent within itself. Elements represent a value, methods represent an action more than than a value, a property, usually represents a value and an action, that is, elements and methods are both connected to properties, so imo it doesn't make more sense for properties to have consistent syntax with methods than it does with elements. Some times inconsistent is a good thing, we can call it variety instead, consider for example, %var%.%prop% vs %var%.[prop] where the inconsistent syntax is much more readable (yeah, it is subjective).
this is unnecessarily inconsistent. The last one should be obj.[method]()
I suppose I omitted the . for habitual reasons rather than for logic / preference. I'm neutral to it.

Cheers.
Last edited by Helgef on 13 May 2019, 03:18, edited 1 time in total.
lexikos
Posts: 6397
Joined: 30 Sep 2013, 04:07
GitHub: Lexikos

Re: Objects - preview of upcoming changes

11 May 2019, 21:28

I do not think calculated var and func names (refs) necessarily needs to be consistent with object notation.
I do not think we need to avoid %% to the point of adding inconsistency.

That is fine, but do you like %fn%()?
More than any of the proposed alternatives, all things considered; and especially more than <>.

I think it is better to remove partial%name% and along with it any mention of pseudo-arrays.
Leaving partial%name% as an error? Pseudo-arrays will still be possible with %"partial" name%, but uglier. Ugly syntax discourages use, which is an argument for keeping % in general... :HeHe:

Perhaps * expr and * expr (), it is easy to type and non-blob like.
Parameter lists have higher precedence than any preceding operator, so *expr(x) would call the function expr() and dereference whatever it returns. In C, I suppose you would do (*expr)(x); but in that case, what do we need * for? In C++, expr and *expr have different types, and could potentially both implement operator ().

obj.*prop and obj.*method() is how it's done in C++, except that prop and method are strongly-typed pointers to members/member functions.

For * expr (x) with auto-concat, it would not be a function call, but a variable reference. Without auto-concat, fun (x) should be a function call, giving * expr (x) the same issue with precedence as *expr(x).

If * binds to the following identifier, like ., then *expr(x) is much the same as %expr(x), which was valid in v2.0-a001.

If you scrap %% for vars and funcs, I wouldn't mind keeping %% for #include.
Neither one seems likely. I plan to eventually give #include a subset of expression syntax, but ideally it would not require much unique code. If the expression parser supported constant folding, it would be trivial.

If you let the brackets [ ] be used for calclated names, methods, properties and indices can all be consistent
Why should methods and properties be consistent with indices but inconsistent with variables and functions? Methods and properties are meant to be distinct from array elements, not consistent with them.

obj[index]
obj.[prop]
obj[method]()
Even putting aside variables/functions, this is unnecessarily inconsistent. The last one should be obj.[method]().

I considered .[] and a bunch of other ideas over several years, and my conclusion was that if it does the same thing as %expr% (substitute an expression for an identifier), it should use that syntax even if no one really likes percent signs.

With the addition of __item, both x[y] and x.prop[y] are invoking a property with parameter y, which has meaning only to the property. x.[y] is another form I considered at some point for invoking the default property (i.e. because the property name normally found between the dot and bracket was omitted). I think that makes more sense than invoking the property named by y. By convention in v1, x.() invokes the default method of x (i.e. calls a function object), actually passing the method name ("") to __call if it's a user defined object.

makes a looking like it's zero-based
That's a good point. I think I was fixated on how it could be used (before I implemented bound checking) given what results the formula give, and didn't really think about whether it should.
lexikos
Posts: 6397
Joined: 30 Sep 2013, 04:07
GitHub: Lexikos

Re: Objects - preview of upcoming changes

12 May 2019, 19:33

v2.0-a103: yet another update which breaks scripts in only relatively minor ways. My intention is to make it easier to prepare for the changes, while also preparing on the development side.

After v2.0-a102 I resumed work on the Array object, but immediately found that it would need a replacement for (or duplication of) SetCapacity and GetAddress. So now we have the Buffer object (see related discussion).

Currently the (unreleased) Array acts like a built-in object; it does not allow new properties or methods. I will likely hold it back until there is no visible distinction between built-in objects and user-defined objects (so expect that in the near future). In the end, it should be easy to update a script to work with the new changes.

Return to “AutoHotkey v2 Development”

Who is online

Users browsing this forum: automatLife84 and 14 guests