Page 1 of 1

obj.HasKey() fails for all keys if a key called HasKey exists

Posted: 12 May 2017, 06:16
by jeeswg
[Moderator's note: Topic moved from Bug Reports.]

It seems that if a key called HasKey is added to an array, the HasKey method no longer works. Is this documented anywhere?

Of course I could create separate variables for handling situations where I would like a key with name HasKey, however, my main concern was whether there were any other unlikely key names that could cause issues with common object-related tasks. Thanks.

(It may seem an unlikely scenario, however, I have a spellchecker in AHK, that adds any words that have already been spellchecked, to an array, and it should be able to handle any word. Plus I do run spellchecks on AHK code, e.g. to retrieve variable names and non-words, or to spellcheck posts that contain AHK code.)

Code: Select all

q::
obj := {}
obj.a := "A"
MsgBox, % obj.HasKey("a") ;HasKey works
obj.HasKey := "HK"
MsgBox, % obj.HasKey("a") ;HasKey no longer works, always gives blanks
MsgBox, % obj.HasKey("HasKey")
MsgBox, % obj.a " " obj.HasKey ;it is still possible to retrieve values

;if the key 'HasKey' is deleted, then HasKey works again
obj.Delete("HasKey")
MsgBox, % obj.HasKey("a")
MsgBox, % obj.HasKey("HasKey")
obj := ""
return
==================================================

Btw for testing purposes what are the special AHK method names, have I missed any?

from https://autohotkey.com/docs/objects/Object.htm
_NewEnum,Clone,Delete,GetAddress,GetCapacity,HasKey,InsertAt,Length,MaxIndex,MinIndex,Pop,Push,RemoveAt,SetCapacity
also: __Call,__Delete,__Get,__New,__Set,base,Next
also+: __Class,__Init
deprecated: Insert,Remove

note: ObjXXX functions where XXX is not in list above: ObjAddRef,ObjBindMethod,Object,ObjNewEnum,ObjRawSet,ObjRelease
note: there is no standard 'Count' method

[EDIT:] A few items added to the list, thanks nnnik.

Re: obj.HasKey() fails if a key called HasKey exists

Posted: 12 May 2017, 07:24
by Helgef
You might be interested in custom objects.

Cheers.

Re: obj.HasKey() fails for all keys if a key called HasKey exists

Posted: 12 May 2017, 07:53
by nnnik
You have missed __New and __Delete as well as base

Re: obj.HasKey() fails for all keys if a key called HasKey exists

Posted: 12 May 2017, 22:31
by lexikos
This is not a bug and is not specific to built-in methods in any way. An object cannot have both a key-value pair and a method with the same name/key, by nature of how members are inherited from a base object. JavaScript and Lua work a little differently, but have the same limitation.

It is also explicitly documented:
Although built-in method names such as "Length" can be used as keys, storing a value will prevent the corresponding method from being called (unless that value is a reference to the appropriate function, such as ObjLength).
Source: Objects
Is this documented anywhere?
If you have to ask, Bug Reports is the wrong forum to post in.

Re: obj.HasKey() fails for all keys if a key called HasKey exists

Posted: 13 May 2017, 03:16
by jeeswg
[EDIT: For the record:
- I said 'Is this documented anywhere?', after spending some time trying to think up a way to suggest that the devs might not be at fault. I wasn't ecstatic to have those words used against me. C'est la vie.
- Only if you were already familiar with object classes, would you expect that keys/methods couldn't share a name. For example, in AHK it's OK to have variables/functions with the same name.
- Although I can use workarounds for myself, I would love such a class, if feasible, because I would find it pretty useful, and it would be very newbie-friendly, and wouldn't require long explanations or caveats. It would fit the AHK way.
- What belongs in Bug Reports isn't defined anywhere. Based on the posts I saw there, including 6 posts by me, my post was suitable. The post was moved. C'est la vie again.]

Thank you for your response. I really appreciate your detailed answers on my questions and questions by other people.

I think that the desire for a class that can handle any key is quite a reasonable one, perhaps a custom class can be made that can handle any key, and perhaps it would need '2 objects within 1 class'.

I did some tests on the Scripting.Dictionary object, if anyone can find any similar issues with this class I would be interested.

Code: Select all

;Dictionary Object
;https://msdn.microsoft.com/en-us/library/x4k5wbx4(v=vs.84).aspx

q::
oArray := ComObjCreate("Scripting.Dictionary")
oArray.item("MyKey") := "MK"
oArray.item("Exists") := "E"
oArray.item("item") := "i"
oArray.item("Item") := "I"
MsgBox, % oArray.Exists("MyKey") ;-1
MsgBox, % oArray.Exists("Exists") ;-1
MsgBox, % oArray.Exists("item") ;-1
MsgBox, % oArray.Exists("KeyThatDoesNotExist") ;0
MsgBox, % oArray.item("MyKey") ;MK
MsgBox, % oArray.item("Exists") ;E
MsgBox, % oArray.item("item") ;i
MsgBox, % oArray.item("Item") ;I
oArray := ""
return
Re. Bug Reports, is it not true that using your style of argumentation I could argue that something that behaves like a bug, or that departs from reasonable expectations or existing models (breaks the principle of least astonishment) can be considered a bug, and would be a bug even it were documented, and that something that can be considered a bug is eligible for Bug Reports?

Re: obj.HasKey() fails for all keys if a key called HasKey exists

Posted: 13 May 2017, 03:37
by jeeswg
It appears that a workaround is to use ObjHasKey(obj, key) instead of obj.HasKey(key).

Re: obj.HasKey() fails for all keys if a key called HasKey exists

Posted: 13 May 2017, 17:29
by lexikos
perhaps a custom class can be made that can handle any key
I think I already have, but I haven't a clue how to find it. [Edit: BArray is probably the one I was thinking of. It's just a proof of concept, though. You would need to implement the other methods, the way I've implemented HasKey.]

It is not necessary to use a COM object; just don't store values directly in the object which you're calling methods on. Everything can be redirected through meta-methods (and normal methods for HasKey, etc.).
jeeswg wrote:is it not true that using your style of argumentation [...]
I'll rephrase. If there's uncertainty about whether something is a bug and not a documented feature, don't post in Bug Reports. Get confirmation first. If you have to ask whether it's documented, you're obviously uncertain. If it's definitely a documented feature and you want it changed, post in Wish List.

I'm not going to argue over the semantics of "bug" or "bug report". It's irrelevant and would be a waste of my time, which is what I'm trying to avoid by guiding users to post in Ask for Help before Bug Reports.