nnnik wrote: ↑15 Nov 2018, 10:01
Function objects often do have a base object.
Function objects are all objects returned by
Func(). All other objects implement the "Callable" interface.
They are therefore callables not function objects. Function objects don't have a base object they have a function that handles all acceses.
so that things produced by Func(Name) and the Bind(Args*) method would have the same interface
No it isn't - I checked the source code myself. Bind wraps around any callable. Not every callable exposes the information necessary to provide the same interface as function objects.
If we want to make the interfaces the same we either have to limit bind on function objects (and the newly created boundFunc objects which would be the same) and remove all other objects.
Or we would have to remove features from function objects. Beither is an option in v1 since those are breaking changes.
ObjGetBase(Object) for all objects
What should ObjectGetBase return for COMObjects? What would ObjSetBase do with COMObjects?
What kind of base Object would a function object return?
Something you have to know about all AHK objects is that not every Object may be a build in AHK Object but each and every single Object in AHK is a COM Object.
What you suggest would require a complete rewrite of the source to invert the dependency. It would also remove some COM features that are documented.
Therefore it is not possible to introduce these features in v1.
Most programming languages
do use common superclasses to determine the type of a value, if you try to compare its type instead of just use the same members on it. I would be okay with that in a programming language designed with a coherent type hierarchy. This does not describe the situation with AutoHotkey. I hope it will, someday, soon.
Dynamically type checked programming languages with a coherent type hierarchy rarely
make it necessary to determine the type of a value. Depending on polymorphism is preferred. The same interface provides the same functionality for all types (if it is Fooable it will have the Foo method), so you do not need to even worry whether the member will exist. If the interface does not exist, you must have been passed an unusable value, as opposed to having been passed a value with an incompatible but equivalent interface that you could have used if only you had recognized it (e.g. I get the length of an array with
ObjLength(Array) or
Array.Length(), but I get the length of a string with
StrLen(Str). This is why comparing the type and dispatching to the right code is
necessary in AutoHotkey.). They also usually report all errors in a helpful way. This does not describe the situation with AutoHotkey. I hope it will, someday, soon.
I am not sure what you checked in the source code, but I will defer to you on that. I have attempted to read it several times and was scared away by the comments and structure. I believe you when you say that not all equivalent constructs preserve the same information. I
do not believe it is impossible to preserve the same information for all equivalent objects constructed by AutoHotkey. In short, I believe you that it is broken, but I do not believe that is a valid reason to not fix it. If the AutoHotkey source does not cause something to be exposed that should be exposed, it should be changed to expose that thing. Other programming languages (e.g. Smalltalk, Python, etc.) manage to keep track of the same information, most of the time (e.g. Python cannot refer you to the Python source code for built-in constructs written in C), for both their built-in and user-defined constructs. I do not have these problems in other programming languages.
For example,
MinParams and
MaxParams are not provided on BoundFunc objects. BoundFunc objects are normally produced by calling the
Bind(Args*) method on a function object produced via
Func(FunctionName), which
does contain this information, or from
ObjBindMethod(Obj, Method, Args*), which either operates on a built-in type that
could contain this information or a user-defined type which
does contain this information. Preserving this information and performing subtraction is not impossible.
It is definitely possible to make the
Bind(Args*) method reliably return a function object with a
Bind(Args*) method. I know because I have already written code that does that, and I did not even need to alter the AutoHotkey interpreter. I just wrap function objects in a sanity preserving class that behaves like a function object.
If COM objects, other than the ones AutoHotkey exposes, do not expose the necessary information, that might be a valid excuse to not provide it
for external COM objects, only. It might also be a good reason to have external COM objects under a separate part of the type hierarchy in v2 so that we can recognize "that is an external COM object, so I should not try to ____ it". I am skeptical that this is the case. PowerShell is
extremely good at interrogating COM objects. For example, it can reliably enumerate their members, including returning information about their parameters. PowerShell is open source, so if the developers are enamored enough with COM to try to fit everything into its mold, they could look at its source to see how the magic is made.
I would expect ObjGetBase and ObjSetBase to return or set (respectively) the default base object for COM objects and function objects. Whatever member could not be found on the COM object or function object would be handled, if it was defined, by the default base object, at least when used from AutoHotkey (I would not expect external code to recognize it on the COM object). The default base object already works this way, with these limitations, for strings (including numbers).
I am surprised to hear that every object in AutoHotkey is a COM object. AutoHotkey's Objects do not act like Scripting.Dictionary and AutoHotkey Arrays do not act like SAFEARRAY. This also seems like a poor excuse
for inconsistency. If anything, working with COM objects should be seamless in AutoHotkey, while in reality it is much easier in PowerShell than AutoHotkey. I am sure the developers can expose everything as a COM object, and they can also
choose what is to be exposed. They should be able to make what they expose consistent and avoid conflation. For example, iterating over a COM SAFEARRAY should put the array's values in the Value variable,
not the Index variable, like it currently does.