Type(object)

Discuss the future of the AutoHotkey language
lexikos
Posts: 9553
Joined: 30 Sep 2013, 04:07
Contact:

Type(object)

14 May 2017, 06:00

I am planning to change Type() to return more specific type names.
  • For class objects (obj.HasKey("__Class")), return "Class", mainly because it would seem semantically incorrect/misleading to return the class name (or the base class name).
  • For instances of a class, return obj.base.__Class (the class name).
  • For COM objects, it seems appropriate to return different type names depending on the variant type, since it affects which methods and properties the object supports:
    • For VT_ARRAY, return "ComObjArray". (Supports array indexing and a few methods.)
    • For VT_BYREF, return "ComObjRef". (Supports ref[] and ref[] := value.)
    • For VT_DISPATCH or VT_UNKNOWN:
      • If the object implements IProvideClassInfo, return the class name.
      • Else if the type is VT_DISPATCH, return "ComObject".
    • Else return "ComObjValue".
I'm not so sure about VT_UNKNOWN. I think it should be different to VT_DISPATCH, since VT_UNKNOWN does not support any properties or methods. If you try to invoke it, you get a "No COM object" error. The only difference between it and other variant types is that Release() is called from the destructor.

I considered "ComObjVariant" rather than "ComObjValue", but it's really not a VARIANT (it just has common properties: a variant type and value), and its value can't be changed. So it basically just represents that one value for its entire lifetime. I chose not to use "ComObjParameter" or similar (based on function names used in v1) because it's not always passed as a parameter, and that function doesn't exist in v2.

The other built-in object types would be:

File (was FileObject)
Func
BoundFunc
RegExMatch (was RegExMatchObject)
Object.Enumerator (was Object::Enumerator)
ComObject.Enumerator (was ComEnum)
ComObjArray.Enumerator (was ComArrayEnum)
Gui (was GuiType)
GuiText, GuiEdit, GuiButton, etc. (because several control types have additional methods).

(In the current build the name is automatically derived from the object's C++ class name.)

These type names would also be displayed in ListVars and returned to the (DBGp) debugger. (DebugVars.ahk is already designed to display it.)
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: Type(object)

14 May 2017, 06:20

This is a great feature.
I see some potential flaws e.g. when checking if a enumerator is an enumerator object vs. custom enumerator but I think this can be smoothed out.
Recommends AHK Studio
lexikos
Posts: 9553
Joined: 30 Sep 2013, 04:07
Contact:

Re: Type(object)

14 May 2017, 16:44

What "flaws"?

Why would you check "if a enumerator is an enumerator object vs. custom enumerator"?

Type() is unsuited for type-checks, since it returns only one type name, not each type in the hierarchy or types it is convertible to. Besides, a custom enumerator does not need to have a class name or any kind of class hierarchy.
guest3456
Posts: 3454
Joined: 09 Oct 2013, 10:31

Re: Type(object)

14 May 2017, 17:15

lexikos wrote: Type() is unsuited for type-checks
Wait what? What is it used for then?

User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: Type(object)

14 May 2017, 19:49

Type() is unsuited for type-checks, since it returns only one type name, not each type in the hierarchy or types it is convertible to.
So it is unsuiteable for it's only use case? And even if it would be unfit people would use it anyways.
Besides, a custom enumerator does not need to have a class name or any kind of class hierarchy.
That's not what I meant. If you can use type to check if an object is a standard enumerator then it is going to be used to do exactly that.
That would create a break with custom enumerators since type would return something else for them.
Recommends AHK Studio
lexikos
Posts: 9553
Joined: 30 Sep 2013, 04:07
Contact:

Re: Type(object)

14 May 2017, 23:16

Tell me then, given nothing but a type name, how do you determine whether the type conforms to a particular pattern or is derived from some other type? You can't. To use it for any purpose other than debugging or checking the exact type of a value or object (not what I meant by "type-checks"), you need to follow certain patterns. For example, the standard enumerators do not all return one name, but there is a pattern. Anyone can easily stick to - or deviate from - that pattern.
nnnik wrote:That would create a break with custom enumerators since type would return something else for them.
If that's what you call the "flaw", I'm curious to know how you think it can be "smoothed out".

Creating enumerator classes which don't follow the pattern is what creates this break, not type().

There's a "break" between every class, since every class returns something else. It should be extremely obvious that checking the type name of an object won't account for similar types which have different names.
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: Type(object)

15 May 2017, 02:24

Of course there might always be more objects that "fit" an enumerator pattern. But this is mostly about new custom enumerators from _newEnum.
.
That's what I'm trying to prevent. The real issue here is that we now have to stick to another pattern that we didn't have to before. Creating additional problems for programmers shouldn't be the goal for new features. And as you said yourself so far Enumerators didn't have to follow anything other than having a method named next.
They don't even need a base class.

Fixing it could be easy by:
  • Allowing a function like setType ;-extra work for script writer +flexible
  • Automatically setType for values returned by _newEnum unless they have set another type ;+easy solution for most scripts -doesn't cover all cases
  • Make an Object that has a function in the next key count as an enumerator ;+easy solution for all enumerators -might make completely unrelated Objects seem like enumerators
However if it's only purpose is debugging then those problems won't appear at all.
Recommends AHK Studio
lexikos
Posts: 9553
Joined: 30 Sep 2013, 04:07
Contact:

Re: Type(object)

15 May 2017, 18:46

nnnik wrote:The real issue here is that we now have to stick to another pattern that we didn't have to before.
You are imagining things.

If you didn't have to stick to the pattern before, you don't have to stick to the pattern now. The only difference from before is that the names end with ".Enumerator" instead of just containing "Enum" (they are "Object::Enumerator", "ComEnum" and "ComArrayEnum", as I said), so any script (naively) trying to detect an enumerator type by name would be checking for a slightly different pattern.
Allowing a function like setType ;-extra work for script writer +flexible
How does that solve the problem? Who is supposed to be calling it? If you didn't create the class but already know it's an enumerator, you have no need to check if it is one. If you don't know it's an enumerator, you won't call setType(). If you created the class, you can name it correctly in the first place, without setType().
Make an Object that has a function in the next key count as an enumerator
This is up to whoever writes the code to check for enumerator objects. Of course, they can check for the existence of a Next method (if the object isn't built-in). It has nothing to do with type(). If type() returned "Enumerator" rather than the object's class name, there would need to be another function to retrieve the class name, and that function would have the same (imaginary) "flaws" as type().
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: Type(object)

16 May 2017, 06:25

If you didn't have to stick to the pattern before, you don't have to stick to the pattern now. The only difference from before is that the names end with ".Enumerator" instead of just containing "Enum" (they are "Object::Enumerator", "ComEnum" and "ComArrayEnum", as I said), so any script (naively) trying to detect an enumerator type by name would be checking for a slightly different pattern.
I don't remember using this in v1. I didn't see it in v2 yet either, though this might be because I missed it. And I think inStr( type( object ), "Enum" ) should still work.

Modularity towards me is following conventions. Conventions you select out of the mass of all conventions that make up your style. Conventions that you share with other people to make your modular scripts work for them.
inStr( type( object ), "Enum" ) would be such a convention. It would be a convention that just got added. You can't just add a convention without offering the ability to make old scripts compatible with it.

Code: Select all

If you didn't create the class but already know it's an enumerator, you have no need to check if it is one.
That is assuming I am creating a non-modular AutoHotkey script based on some other AutoHotkey script - I always create modular code and I always reuse old code.
If type() returned "Enumerator" rather than the object's class name, there would need to be another function to retrieve the class name, and that function would have the same (imaginary) "flaws" as type().
Type is not the same as class name. If type is already established as a convention there won't be any need for a second convention for doing the same thing as type. And why do you need a function that would do return Object.__Class ?

Don't get me wrong though I am not against the implementation of type as you have it now.
I just thought this was the start of a feature many of us requested since quite a while. The feature I'm talking about is some sort of typing system. Many people check for their own types in their own ways. ( e.g. AutoHotkeys equivalent of overloaded functions )
I just thought that this would be the opportunity to unite some of that code in a AutoHotkey wide convention. And type() certainly does fulfill some of the requirements needed for that feature.
However that is not it's intended usage and as such there are going to be complications. I don't think people will care though and use it that way anyways.
So what I'm asking for is either some way to prevent them from using it that way ( maybe something like #Debug and make it only work when this flag is set ). Or some way to combine the scripts that follow this convention and those who don't without having to rewrite entire scripts ( setType ).
Recommends AHK Studio
lexikos
Posts: 9553
Joined: 30 Sep 2013, 04:07
Contact:

Re: Type(object)

16 May 2017, 19:36

nnnik wrote:I don't remember using this in v1.
v1 doesn't have Type().
You can't just add a convention without offering the ability to make old scripts compatible with it.
What? v2 is not compatible with old scripts. I'm under no obligation to retain any kind of compatibility with scripts written for earlier alpha builds.
Type is not the same as class name.
Since when?
If type is already established as a convention there won't be any need for a second convention for doing the same thing as type.
What?
And why do you need a function that would do return Object.__Class ?
It wouldn't. __Class is only valid for custom objects. Not all custom objects necessarily support it. Type() never invokes a meta-function.
I just thought this was the start of a feature many of us requested since quite a while. The feature I'm talking about is some sort of typing system.
You were wrong. Clearly this was just about the type names returned by Type(), which already exists. Type() just returns one type name. That is all. It can't possibly fulfill all of your requirements. "Some sort of typing system" is what classes are for, hence type() returning class names.
So what I'm asking for is either some way to prevent them from using it that way ( maybe something like #Debug and make it only work when this flag is set ).
What? Why? Failing common sense and documentation, it's futile to try to stop people from doing stupid things.
... those who don't without having to rewrite entire scripts ( setType ).
Firstly, this is v2. Most v1 scripts will need heavy revision. Secondly, no one has to rewrite entire scripts to utilize type().
just me
Posts: 9423
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Type(object)

28 May 2017, 04:17

lexikos wrote:GuiText, GuiEdit, GuiButton, etc. (because several control types have additional methods).
I think this would be redundant after GuiControlObject.Type has been implemented. GuiControl should be sufficient for all controls.
lexikos wrote:Object.Enumerator (was Object::Enumerator)
ComObject.Enumerator (was ComEnum)
ComObjArray.Enumerator (was ComArrayEnum)
These are rather lengthy. I'd prefer
Enum
ComEnum
ComArrayEnum
lexikos
Posts: 9553
Joined: 30 Sep 2013, 04:07
Contact:

Re: Type(object)

28 May 2017, 21:30

It would be semantically incorrect to report the GUI control types as "GuiControl", when different control types have different methods available. They are effectively different classes. I'm fine with Type() returning just the fundamental type (Integer, String, Float or Object), or returning value type or object class, but I'd prefer it didn't return some half-arsed mix.

What's the need for short class names? Unlike user-defined classes, you don't instantiate them by name, you can't refer to the class itself as an object, and they can't have static members.

"Enum" is ambiguous and conflicts with possible future use for enumerated constants. The documentation uses the name "Enumerator".
just me
Posts: 9423
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Type(object)

29 May 2017, 03:14

lexikos wrote:... , when different control types have different methods available. They are effectively different classes.
You mean "effectively" in the sense of "in some extent"? I cannot find different GuiControl classes within the source code.
lexikos wrote:What's the need for short class names?

Code: Select all

If (Type(Object) = "ComObjArray.Enumerator")
; vs.
If (Type(Object) = "ComArrayEnum")
Less chances for misspelling.
lexikos
Posts: 9553
Joined: 30 Sep 2013, 04:07
Contact:

Re: Type(object)

29 May 2017, 21:28

I mean for all intents and purposes, according to what a class is. The structure of the C++ source code is completely irrelevant. Would you say that instances of class MyClass and class YourClass are exactly the same class because they're all instances of the C++ class Object? The same goes for all COM objects, even though IDispatch objects, Safe Arrays and others provide entirely different methods and properties. You're not writing in C++; you're writing in AutoHotkey.
_3D_
Posts: 277
Joined: 29 Jan 2014, 14:40

[suggest] Type(object)

27 Aug 2017, 07:16

AutoHotkey_2.0-a081-cad307c
edited to catch internal objects like File

Code: Select all

class Cls {
}
msgBox(Type(Cls))		; Class
msgBox(Type(new Cls))	; Cls
This way we can`t know is this Class instance or not. Why?

Code: Select all

class Integer {
}
msgBox(Type(Integer))		; Class
msgBox(Type(new Integer))	; Integer ???
Type(argument) return "String".

SUGGEST

Code: Select all

typeOf(this) {
	__type:= __name:= type(this)
	if isObject(this) {
		__type:= "Object"
		try if this.__Class && __name != (__type := "Class")
				throw
		catch 
			return __type "|" __name 
	} 
	return __type
}
This way first word in "String" will be TYPE and if "|" class name.

EXAMPLES

Code: Select all

msgBox(typeOf(1))		; Integer
msgBox(typeOf("1"))		; String
msgBox(typeOf(1.2))		; Float
msgBox(typeOf([]))		; Object
msgBox(typeOf({}))		; Object

class Integer {
}

msgBox(typeOf(Integer))		; Class
msgBox(typeOf(new Integer)) ; Class|Integer ; <<< VALID label name too

a:= {}

msgBox(typeOf(a))		; Object
msgBox(typeOf(new a))	; Object

msgBox(typeOf(FileOpen("test.txt", "rw"))) ; Object|File
AHKv2.0 alpha forever.

Return to “AutoHotkey Development”

Who is online

Users browsing this forum: No registered users and 35 guests