[a104] are builtin classes protected against accidental overwriting? Topic is solved

Get help for the alpha version of AutoHotkey v2 here. Please state the v2 version you are working with in the title when making a new topic.
swagfag
Posts: 3056
Joined: 11 Jan 2017, 17:59

[a104] are builtin classes protected against accidental overwriting?

20 Aug 2019, 07:30

title basically

Code: Select all

Array := '' ; overwrite

arr := [1, 2, 3]
MsgBox arr.Length ; still correctly displays '3', despite having been supposedly overwritten
Helgef
Posts: 4031
Joined: 17 Jul 2016, 01:02
Contact:

Re: [a104] are builtin classes protected against accidental overwriting?

20 Aug 2019, 08:03

Warn class overwrite, array is just a variable
swagfag
Posts: 3056
Joined: 11 Jan 2017, 17:59

Re: [a104] are builtin classes protected against accidental overwriting?

20 Aug 2019, 08:10

Array should be the name of class Array extends Object if im not mistaken.
anyway, when i enable #Warn ClassOverwrite heres what happens:

Code: Select all

#Warn ClassOverwrite
; warns u that 'Array' is about to be overwritten, hit OK
Array := '' ; overwrite it!

arr := [1, 2, 3]
MsgBox arr.Length ; still correctly displays '3', despite having been supposedly overwritten
contrast this to overwriting a user-defined class:

Code: Select all

#Warn ClassOverwrite
; warns u that 'MyClass' is about to be overwritten, hit OK
MyClass := '' ; overwrite it!

mc := new MyClass() ; "no object to invoke", which is expected

class MyClass 
{
}
Helgef
Posts: 4031
Joined: 17 Jul 2016, 01:02
Contact:

Re: [a104] are builtin classes protected against accidental overwriting?

20 Aug 2019, 08:18

As I said, array is just a variable, try new array() after you overwrite the variable. There can be references to the class even when you overwrite a variable with one reference.
swagfag
Posts: 3056
Joined: 11 Jan 2017, 17:59

Re: [a104] are builtin classes protected against accidental overwriting?

20 Aug 2019, 10:08

now im even more confused.

Code: Select all

#Warn ClassOverwrite
; warns u that 'Array' is about to be overwritten, hit OK
Array := '' ; overwrite it!

arr1 := [1, 2, 3] ; function shorthand
MsgBox arr1.Length ; still correctly displays '3', despite having been supposedly overwritten

arr2 := Array(1, 2, 3) ; function
MsgBox arr2.Length ; still correctly displays '3', despite having been supposedly overwritten

arr3 := new Array(1, 2, 3) ; class constructor, "no object to invoke"
this suggests that the Array class is in fact being overwritten, yet the Array() function and [] continue working as they normally would(one would expect that all 3 would throw with "no object to invoke").
do they keep a reference to some secret, hidden Array class or whats going on?
Helgef
Posts: 4031
Joined: 17 Jul 2016, 01:02
Contact:

Re: [a104] are builtin classes protected against accidental overwriting?  Topic is solved

20 Aug 2019, 15:09

The function array doesn't depend on the super global variable array. The variable array is not the only reference to the class.
User avatar
nnnik
Posts: 4315
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: [a104] are builtin classes protected against accidental overwriting?

20 Aug 2019, 15:10

imo an inconsistency in the behavior.
Why do we need a function named array?
Recommends AHK Studio
swagfag
Posts: 3056
Joined: 11 Jan 2017, 17:59

Re: [a104] are builtin classes protected against accidental overwriting?

20 Aug 2019, 16:26

for binding? i dont know, it probably has some uses
User avatar
jeeswg
Posts: 6904
Joined: 19 Dec 2016, 01:58
Location: UK

Re: [a104] are builtin classes protected against accidental overwriting?

20 Aug 2019, 16:54

- Potentially you could call %func%() with Array/Object/custom function MyArray etc, depending on the situation.
- There's also ease of conversion, if another language has a similar function.
- You might commonly interchange between Array/MyArray in quick scripts, or modify the existing Array function by adding safety checks, or extra checks for a one-off job.
- If you create a custom function called Array it overrides Array() and []. You can access the original array functionality by using the Array class object.
- Anything else?
- I don't see too much use for it, but I wouldn't get rid of it.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
User avatar
nnnik
Posts: 4315
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: [a104] are builtin classes protected against accidental overwriting?

21 Aug 2019, 02:04

If you want to overwrite all instances of the class it makes sense to overwrite the instance of the class.
If we overwrite:

Code: Select all

Array := MyArray
all instances of array should be of the class MyArray.
Yet they arent because there is this function called Array() which returns a different class and is more important to array objects than the array class itself.
This is highly suprising and even after looking at it for quite a while I cannot comprehend as to why we would overwrite all instances of array by overwriting a function named array instead of the very class array.
It is a competely foreign concept to AHKs Objects - all Objects you will ever create will be created with new %className%().

So even if we make Array overwrite what [] returns it would suprise people if Array() returned anything but the class currently used by [] and contained in Array.

At that point Array() becomes redundant and borderline harmful. If someone were to overwrite Array to do something different in an attempt to redefine Array we would get another strange situation.
[] would einter return what Array() or Array currently contains and the three would once again be very different (probably breaking the expectations established before).

Now we could try and make Array a read only variable and make it return what is defined via Array(). However Array() returns an object where as Array is a class object.
There is no good way to get the class object of an object in AHK. For all we know the object could be from an external COMObject and not have any class object altogether.

In the end removing one of the 2 ways seems like the best way to go.

Array is consistent with built in objects and provides more information and flexibility by providing a class object rather than a instance directly.
It also is more dynamic because Array is just a value you can copy/move and reference all over the place if you like to.
Array forces [] to be a AHK class which can be an advantage or disadvantage depending on the situation you are in.
Recommends AHK Studio
Helgef
Posts: 4031
Joined: 17 Jul 2016, 01:02
Contact:

Re: [a104] are builtin classes protected against accidental overwriting?

23 Aug 2019, 05:27

As far as I know, the fact that [] calls array() isn't documented. Anyways, this doesn't affect p* or strsplit etc. In v1 it has very limited use, in v2, at least you can override the function locally, that is as a nested function. If you want to modify array behaviour or capability, the natural way would be to modify array.prototype, this would affect all instances, present and future. I don't think it's important to be able to completely override the array class, but if it would be possible, I think changing array.new() would be the way to allow it, rather than overwriting the array variable. Consider this,

Code: Select all

F() {
    Local
    Isobject [] ; ?
}
Cheers :train:.
Helgef
Posts: 4031
Joined: 17 Jul 2016, 01:02
Contact:

Re: [a104] are builtin classes protected against accidental overwriting?

28 Sep 2019, 09:12

Helgef wrote:I don't think it's important to be able to completely override the array class, but if it would be possible, I think changing array.new() would be the way to allow it,
One problem would be if the overridden array.new() were defined to be variadic, it wouldn't work.
lexikos
Posts: 6657
Joined: 30 Sep 2013, 04:07
GitHub: Lexikos

Re: [a104] are builtin classes protected against accidental overwriting?

28 Sep 2019, 19:49

@nnnik
There are more "cooperative" ways to extend array functionality than to replace the Array class or redefine the constructor/function.

It isn't supported or recommended to "overwrite all instances of the class".

If "all instances of array should be of the class MyArray", what about MyArray itself or any other subclass, instances of which are also instances of array?

According to your statement, if you

Code: Select all

Array := MyArray
MyArray := UrArray
shouldn't "all instances of MyArray be of the class UrArray" and therefore "all instances of array be of the class UrArray"? Where does it end? This isn't how assignments and object references work.

Would you be happier if Array() was renamed to SquareBrackets()? It only serves as the implementation of [], and a means to override that operator. If you redefine it, there's no guarantee that it will return an Array. Above all, that's how it's been since v1.1. It was left this way for now because it would be a low priority change, and because I think the drawbacks of making [] 100% equivalent to Array.new() outweigh the benefits.

Yes, if the script redefines basic built-in functions, it will break standard expectations about what those functions do. That's a given. Changing expectations is more or less the purpose of redefining a function. At the very least, you're probably breaking the expectation that the object will have a known limited set of properties/methods. If you don't want to break expectations, don't do it.

#Warn ClassOverwrite should probably always be used, and should not be ignored.
lexikos wrote:
07 Apr 2018, 20:39
I might consider making class names read-only identifiers (not variable) in v2. It would not reduce flexibility much since one can still clone the class and modify the original object as needed.
lexikos wrote:
14 May 2019, 20:43
I will probably do this, or make #Warn ClassOverwrite the default, or make it mandatory behaviour, to be reimplemented later as constants.

Of course, there's still no guarantee Array.new() will return an Array, since you can redefine Array.new().

I cannot comprehend as to why we would overwrite all instances of array
Me neither. ;)
If you want to overwrite all instances of the class it makes sense to overwrite the instance of the class.
"If you want to eat all apples, it makes sense to eat an apple." I mean yes, I suppose it makes sense to you, to do something you want to do. But that's not saying much.
all Objects you will ever create will be created with new %className%().
Unless I remove the new operator... or you use any one of several built-in functions that create objects for you.
There is no good way to get the class object of an object in AHK.
No, not at the moment. Built-in objects do not even have class objects, except for Object, Array and Map. Obviously, whatever you're trying to do with the class object is not going to work if there is no class object.

With Object.ahk I toyed with the idea of aClass.Prototype.class = aClass (despite the circular reference), which would mean (new aClass).class = aClass. __Class should probably be __Type, since that's what it's for; to be returned by Type. Currently the presence of __Class is also used as a signal to prevent __Delete from executing for prototypes, and for Type to return "Prototype", but separating this behaviour from the type name would improve flexibility.

COM objects can be identified easily. However, it's quite possible that comobj.class returns something meaningful, perhaps even a Class object from a remote AutoHotkey script.


I suppose class objects have these purposes:
  • Identify the class for obj is aClass.
  • Access static methods and properties, including the constructor. Not helpful if there are none. GuiCreate, MenuCreate and MenuBarCreate can be replaced with constructors, although the functions are readily accessible even in assume-local functions. GuiFromHwnd, GuiCtrlFromHwnd and MenuFromHandle could also be replaced with static methods, but I see no real benefit.
  • Provide access to Prototype without creating an instance of the object, for adding extensions.
  • Be extended (be used with the extends keyword). For example, to extend functionality without risk of breaking unaware parts of the script. A subclass of GuiControl could be used to integrate a custom control with the standard Gui methods.
But classes other than Object, Array and Map were a low priority, and I was reluctant to reserve global variables named "Gui", "Menu", "File", etc. especially without first making #Warn ClassOverwrite default/mandatory.
User avatar
jeeswg
Posts: 6904
Joined: 19 Dec 2016, 01:58
Location: UK

Re: [a104] are builtin classes protected against accidental overwriting?

28 Sep 2019, 20:16

- Class names could use a separate namespace (a bit like window groups in AHK v1).
- And could be accessed via something like: ArrayClass := GetClass("Array")
- With 'ClassB extends ClassA' remaining as before.
- (Further advantages: you don't have to declare the class variable as global, and, whereas an undefined class variable would cause a #Warn error, the function would not.)

- Otherwise, since Object/Array/Map/Gui/Menu/File are useful variable names, the class variables could have longer/more unique names.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
lexikos
Posts: 6657
Joined: 30 Sep 2013, 04:07
GitHub: Lexikos

Re: [a104] are builtin classes protected against accidental overwriting?

28 Sep 2019, 20:56

Those all seem like poor solutions, which is part of the reason I left it as it is.

I consider consistency of built-in objects and classes with user-defined objects and classes, vs. convenience of shorter type names and familiarity (of the Gui/Menu/File prefix), vs. inconvenience of being unable to use those conveniently short names for other things, vs. being pushed to use clearer, more specific names for user-defined variables because the generic ones are already taken...

My initial thought (reoccurring, as I've been thinking about this for a long time) was for built-in classes to use A_, but obj is Array looks more natural and is easier to type than obj is A_Array. But then, the A_ prefix has always bothered me.

As one possibility for the future, I imagined having namespaces or modules similar to some other languages, where the script can choose to import the built-in class names into the global namespace. Helgef brought that closer to reality with PR #142, although (I think) it lacks any way to import names, other than by defining a duplicate variable or function in the current namespace.

With modules/namespaces, possibilities include std->Gui (class) and Gui->Gui (class in module) and something like Python's import Gui from std or import Gui. Having something up front importing a particular module (even if the module is built-in) has the benefit of showing that the script utilizes that functionality. It also becomes possible to have different versions of the module, with the script importing the appropriate version. There are likely to be other benefits of having functionality divided into modules (even if built-in).

In any case, the core types Object, Array and Map would be available by default, which is part of why I started out with just those (and Class, which I'm often forgetting).
User avatar
jeeswg
Posts: 6904
Joined: 19 Dec 2016, 01:58
Location: UK

Re: [a104] are builtin classes protected against accidental overwriting?

28 Sep 2019, 22:15

- While I appreciate that there may be some key issues you haven't mentioned, I see it like this ...
- In short, I see advantages in thinking of class definitions as like function definitions. Function names do not clash with the variable namespace, and you can create a function reference/check for a function's existence using Func. Also, Func doesn't have any issues re. global/local/#Warn, and you won't accidentally overwrite a function, and you can check if it's built-in or not.
- I see significant disadvantages in using normal variables as the main way to store/use class definitions. The dependency creates all kinds of problems for nothing. (E.g. overwrite issues/variable name availability/does variable exist #Warn issues.)
- (In my ideas below you can *create* such a class object variable, if you wanted it, but the script wouldn't *depend* on it. And you can still have special variables like 'base' *within* class definitions.)
- We have ComObjCreate(ClassName) to create COM objects, we could have a similar function for built-in classes and custom classes.

Code: Select all

;create COM object instance (for comparison):

oDict := ComObjCreate("Scripting.Dictionary")

;create object instance, 4 solutions (which can coexist):

oInstance := ObjNew("CustomClass")

oInstance := new "CustomClass"

;other names could be: Class (cf. Func), ClassGetDef, ObjGetClassDef
CustomClass := ObjGetClass("CustomClass") ;or a different function name
oInstance := new CustomClass

CustomClass := ObjGetClass("CustomClass") ;or a different function name
oInstance := CustomClass.New()
- These approaches are no more verbose than the existing ones, and avoid the problems outlined earlier.
- AHK v1 didn't have obj is ClassObject, and I never missed it. (I don't know if I've ever needed to check an object's class in any script, i.e. I created the object, so I know what class it has.)
- I'm curious as to how often people actually use class object variables *directly*, and whether these are actual common problems?
- E.g. I use various custom classes, but generally the instances are the return values of functions, I don't touch the class definition variables.
- E.g. I got by fine without built-in Array/Map/Object variables.
- (And like I said, you could create a class object variable if you needed it, to manipulate the class definition.)

- My key issues, all addressed above, would be:
- Create an instance of a class object.
- Check if a class definition exists. (ObjGetClass could fail (return a blank string), and/or you could have an IsClass function.)
- Manipulate a class definition variable. (Like before, except you must create the variable.)
- Get the class of an instance object. (Like before, use oInstance.__Class or Type.)
- (Did I miss anything?) Cheers.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
User avatar
jeeswg
Posts: 6904
Joined: 19 Dec 2016, 01:58
Location: UK

Re: [a104] are builtin classes protected against accidental overwriting?

04 Oct 2019, 03:12

- Array/Class/Map/Object, Gui/Menu/File, custom class names.
- I'd say these are much more useful as generic variable names than as reserved words/illegal variable names. (Gui/Menu/File appear frequently as variable names in documentation examples.)
- One programming language disallowed common variable names in this vein, it was one of my worst programming experiences, and reminded me of how much I liked AHK.

- If A_Array/A_Class/A_Map/A_Object, A_Gui/A_Menu/A_File, don't suit, you could have perhaps:

Code: Select all

Array := Class("Array") ;or equivalent
A_BIC.Array ;(built-in classes)
A_Class.Array ;for comparison, to help generate ideas
A_Classes.Array ;again, for comparison
- #Warn ClassOverwrite would still be useful however, the functionality redeployed to ban a custom list of keywords, to help write code consistent across multiple languages.

- Btw obj is Array, I could see it becoming useful because Array and Map have diverged, with users unsure of which class has which method/property. But IMO the better approach is to make Array and Map more similar again: e.g. restore Count for arrays, and restore array key handling for maps, e.g. for creating 0/n-based arrays, and perhaps other methods/properties too.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
Helgef
Posts: 4031
Joined: 17 Jul 2016, 01:02
Contact:

Re: [a104] are builtin classes protected against accidental overwriting?

04 Oct 2019, 03:28

jeeswg wrote: AHK v1 didn't have obj is ClassObject, and I never missed it. (I don't know if I've ever needed to check an object's class in any script, i.e. I created the object, so I know what class it has.)
Not that I understand what your point is, but this is a very useful feature, which have been greatly missed.
User avatar
jeeswg
Posts: 6904
Joined: 19 Dec 2016, 01:58
Location: UK

Re: [a104] are builtin classes protected against accidental overwriting?

04 Oct 2019, 12:06

- @Helgef: lexikos stated that 'obj is Array looks more natural and is easier to type than obj is A_Array' as one of the arguments for having classes as read-only variables. Yes, it's good for things to be short, but not necessarily *that* short, especially for something that isn't used incredibly often, that already has short alternatives. And also, for that shortness, you have the disadvantage of prohibiting variable names, for something that isn't incredibly common to do.
- I was perfectly happy with oArray.__Class = "Array" or Type(oArray) = "Array", I don't see the need for the check to be done against a *variable*. You could also have something like: IsClass(oArray, "Array").
- (In fact I'd rather we *never* had to use the 'is' operator, I find that an IsType/StrIsType function is generally more readable, and more convertible to other languages. For the same reasons, I'd want StrEquals(var1, var2, opt) in addition to '=', for case-insensitive comparisons/forced numeric comparisons/forced string comparisons/<=/>= etc in library functions, that I often convert to other languages. And it's good to be able to do comparisons in an if/else ladder all via functions or all via operators (for quick copy/paste/adjustment). And it's more intuitive than StrCompare.)
- Can you please try and justify that it's 'very' useful. Especially considering it was already possible with quite short code.
But then, the A_ prefix has always bothered me.
@lexikos: Interesting. I feel that AHK v2 has already removed all of the quirky/unfortunate aspects of the AHK v1 syntax, but I think that A_XXX gives AHK some charm and character, and that's it's actually quite useful. Built-in variables minus the 'A_' would clutter the namespace, and replacing them with built-in functions would make code more verbose. Also 'A_' is significantly easier to type than '()' (which requires more of a wrist stretch and the use of a smaller finger for the ')'.)
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
gregster
Posts: 3377
Joined: 30 Sep 2013, 06:48

Re: [a104] are builtin classes protected against accidental overwriting?

04 Oct 2019, 12:34

jeeswg wrote:
04 Oct 2019, 12:06
Also 'A_' is significantly easier to type than '()' (which requires more of a wrist stretch and the use of a smaller finger for the ')'.)
I always thought AHK would be able to help with things like that. ;)

Return to “AutoHotkey v2 Help”

Who is online

Users browsing this forum: No registered users and 15 guests