Object.HasValue/Contains/KeyOf/FindValue

Discuss the future of the AutoHotkey language
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: Object.HasValue/Contains/KeyOf/FindValue

15 Apr 2017, 00:32

lexikos wrote:
nnnik wrote:I thought of that too. That still wouldn't eliminate the surrounding array.
Appending [1] would. ;)
And I would create a wrapper function around that would exactly do what I want:

Code: Select all

indexOf( obj, byref val )
{
	if isObject( keys := obj.hasValue( val, true, 1 ) )
		return keys.1
	Throw Exception( "Expected Object " . &obj . " to contain value " . disp( value ), A_ThisFunc, "Probably a bug go through the code that calls this" ) 
}
Only further adding to the overhead of my most used usecase.

But I was wrong with the fact that anybody is able to create fine tuned high-speed code with AutoHotkey.
It is not a fine tuned language - it is a bodge after all.
Recommends AHK Studio
just me
Posts: 9406
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Object.HasValue/Contains/KeyOf/FindValue

15 Apr 2017, 01:03

lexikos wrote:Perhaps the best approach is to always return boolean, ...
If you consider Object.HasValue() to be the counterpart of Object.Haskey() it's consistent. I believe that you intended to realize this solution right from the word go, didn't you?
nnnik wrote:It is not a fine tuned language - it is a bodge after all.
AutoHotkey is AutoHotkey, and this is one of the reasons for seeming to be somewhat quirky.
lexikos
Posts: 9494
Joined: 30 Sep 2013, 04:07
Contact:

Re: Object.HasValue/Contains/KeyOf/FindValue

15 Apr 2017, 02:39

just me wrote:I believe that you intended to realize this solution right from the word go, didn't you?
What are you trying to say? I wouldn't have wasted my time by posting if I'd made the decision already. Obviously I knew a boolean value would be consistent with HasKey(), but consistency isn't everything. It wouldn't even make sense for half of the method names in the topic title.
just me
Posts: 9406
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Object.HasValue/Contains/KeyOf/FindValue

15 Apr 2017, 02:53

Every answer in this thread is clearly requesting a solution which provides access to the key(s) in any way. I simply don't understand your deduction:
Perhaps the best approach is to always return boolean, and if there's demand for additional functionality, a parameter or method can be added later.
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: Object.HasValue/Contains/KeyOf/FindValue

15 Apr 2017, 03:19

His solution looks like MSDNs functions and a major amount of the code that we find across the AHK source.
If this is intended or not is questioneable - but I can definitively see lexikos as the one making this suggestion.
Recommends AHK Studio
User avatar
jNizM
Posts: 3183
Joined: 30 Sep 2013, 01:33
Contact:

Re: Object.HasValue/Contains/KeyOf/FindValue

16 Apr 2017, 05:39

[AHK] v2.0.5 | [WIN] 11 Pro (Version 22H2) | [GitHub] Profile
lexikos
Posts: 9494
Joined: 30 Sep 2013, 04:07
Contact:

Re: Object.HasValue/Contains/KeyOf/FindValue

16 Apr 2017, 07:35

just me wrote:Every answer in this thread is clearly requesting a solution which provides access to the key(s) in any way.
Please note the one and only question I asked in my first post:
If Arr.HasValue(Val) is implemented, should it always return a boolean value?
I did not promise to implement anything. I even said outright "if it is implemented".

I did not ask for reasons to return a key or not, and no one gave any. No one made any clear requests to have this capability, only suggestions and arguments about how it would be represented in the syntax, on the assumption that it would be added.

Nor did I promise to base my decisions on anyone else's opinion. I make use of experience, information and logic (though not to the exclusion of intuition), and sometimes my opinions are influenced by arguments made by others. The mere fact (or in this case, implication) that someone wants something (i.e. their opinion) means little to me, especially in the context of the Internet, where opinions abound and everyone is essentially anonymous. That is why I tend not to create polls.

Your refinement on HotKeyIt's idea seems preferable to any of the other suggestions, including my own. The method can provide more information, while limiting the cost to performance by making that extra information optional. The result is always pure boolean (in the sense of clearly indicating "yes" or "no" with no ambiguity, rather than the binary 0 or 1 sense), and there's no need for a ByRef parameter.

But one aspect in particular makes it valuable to me: it is compatible with bool := Object.HasValue(Value), so the extra functionality does not need to be implemented right now. I don't have to decide on specifics, develop and test it, document it or otherwise even think about it. I can just implement a subset of the method and move on. v2 is not about new features. (Let me remind you that I started out by saying this may be a replacement for if var in MatchList.) The project has grown way outside what I ever imagined before I started it, taken far longer than I wanted, and still isn't in a state suitable for actual use (in my opinion). Anything that helps to keep it from growing further out of scope is helpful to me.

As for "if there's demand", the "demand" implied by the interest shown in this thread, by four people, is not what I had in mind, nor did I mean to imply that there wasn't demand.
nnnik wrote:His solution looks like MSDNs functions and a major amount of the code that we find across the AHK source.
I'm sure that Object.HasValue(Value) looks like a lot of code from a lot of places. I don't see your point, and I get the feeling that your post is not intended to be helpful in any way.
User avatar
jNizM
Posts: 3183
Joined: 30 Sep 2013, 01:33
Contact:

Re: Object.HasValue/Contains/KeyOf/FindValue

16 Apr 2017, 09:32

Why not return FoundPos?

FoundPos := HasVal(Arr, Val)
FouncPos := Arr.HasVal(Val)
[AHK] v2.0.5 | [WIN] 11 Pro (Version 22H2) | [GitHub] Profile
guest3456
Posts: 3453
Joined: 09 Oct 2013, 10:31

Re: Object.HasValue/Contains/KeyOf/FindValue

16 Apr 2017, 11:00

jNizM wrote:Why not return FoundPos?

FoundPos := HasVal(Arr, Val)
FouncPos := Arr.HasVal(Val)
did you read the first post? or any replies?

just me
Posts: 9406
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Object.HasValue/Contains/KeyOf/FindValue

17 Apr 2017, 02:50

Hi lexikos,

thanks for your explanations.
...and still isn't in a state suitable for actual use (in my opinion).
I don't think so. When this forums were established I was hoping that we would switch to be the AHK v2 platform soon (leaving polyethene's 'AHK Basic' forums behind us). It didn't happen. But I tested v2 from time to time and never had real problems running my scripts. There are also some users running AHK_H v2 (which presumably is using the same code base) for some time successfully. For me, the last important outstanding decision was the GUI interface. It's done now. IMHO, it's much better than the v1 one and all my testing has been successful as yet. But it also implicates much work on the documentation.

V2 will never be "everybody's darling". IMHO, it's time to close v2 alpha, to create a complete v2 forum, and to release v2 beta. Due to my restricted English I cannot help with the textual part of the docs, but I'm willing to try to convert the code examples if you want me to do it (I tend to use functions whenever possible, so my code won't contain much 'command syntax' examples). Things like Object.HasValue() can be put on hold until the stable release v2.0.01.00 or be implemented during the beta state.
lexikos
Posts: 9494
Joined: 30 Sep 2013, 04:07
Contact:

Re: Object.HasValue/Contains/KeyOf/FindValue

17 Apr 2017, 18:58

Why I say it's not suitable for use relates not to the quality of code, performance, reliability or anything like that, but the stability of the feature set and syntax. (Although it might appear to be stable in that respect as well, that's mainly because of previous slow development and indecision on my part.) For instance, the next alpha release, not including these test builds, will break every script which uses Gui, Drive/Get or Control/Get. The reason these are test builds and not alpha releases is that I intend to get most of the changes I intend for the GUI API out of the way first. It won't be long, I think.
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: Object.HasValue/Contains/KeyOf/FindValue

18 Apr 2017, 05:29

lexikos wrote:I did not ask for reasons to return a key or not, and no one gave any. No one made any clear requests to have this capability, only suggestions and arguments about how it would be represented in the syntax, on the assumption that it would be added.
It always seemed logical to me that this would get added in some form as it is among the very basic capability of any langauge that uses objects.
lexikos wrote:Nor did I promise to base my decisions on anyone else's opinion. I make use of experience, information and logic (though not to the exclusion of intuition), and sometimes my opinions are influenced by arguments made by others. The mere fact (or in this case, implication) that someone wants something (i.e. their opinion) means little to me, especially in the context of the Internet, where opinions abound and everyone is essentially anonymous. That is why I tend not to create polls.
I wanted to
lexikos wrote:Your refinement on HotKeyIt's idea seems preferable to any of the other suggestions, including my own. The method can provide more information, while limiting the cost to performance by making that extra information optional. The result is always pure boolean (in the sense of clearly indicating "yes" or "no" with no ambiguity, rather than the binary 0 or 1 sense), and there's no need for a ByRef parameter.
And I think that HotkeyIts latest refinement is even more prefereable as in it improving performance.
lexikos wrote:
nnnik wrote:His solution looks like MSDNs functions and a major amount of the code that we find across the AHK source.
I'm sure that Object.HasValue(Value) looks like a lot of code from a lot of places. I don't see your point, and I get the feeling that your post is not intended to be helpful in any way.
There seems to be a part missing of that post. I think I was refering to Object.hasValue( value, byref key ). And towards me it looks like a lot of the dll functions in the WinAPI. The return an error code or a status message and output their extended info ( that is only valid if there is no error or bad status ) via a byref parameter.
We humans tend to recreate and reuse old patterns of already existing when we create new things. So it seems only logical to me that you would suggest something similar to the way WinAPI functions look.
I bet it also seemed pretty logical to you as the best solution - what probably created the impression of you being set on this solution.
Recommends AHK Studio
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: Object.HasValue/Contains/KeyOf/FindValue

21 Jan 2018, 12:30

PARAMETERS

- My current preferred solution based on earlier proposals:
0 = bool [default]
1 = first key name as an array
n = first n key names as an array
-1 = all key names as an array
s = first key name as a string [perhaps]
f = first key name as a string [perhaps]
c = count as a number [perhaps]

- Or potentially something like this, which returns an array of all matches by default.

Code: Select all

Object.GetKeys(Needle, Options, FirstKey, LastKey)
ObjGetKeys(Object, Needle, Options, FirstKey, LastKey)

;for comparison:
FoundPos := InStr(Haystack, Needle [, CaseSensitive = false, StartingPos = 1, Occurrence = 1])
FoundPos := RegExMatch(Haystack, NeedleRegEx [, OutputVar, StartingPosition = 1])
FoundPos := StrMatch(Haystack, Needle, Options) ;proposed
FoundPos := StrContains(Haystack, Needle, Options) ;proposed (equivalent to 'contains')
FoundPos := StrExact(Haystack, Needle, Options) ;proposed (equivalent to 'in')
- Other option possibilities (for an options parameter):
- case sensitive/case insensitive
- value is string/numeric
- should it recurse into all subkeys [probably best to omit this]
- handle contains/exact match/starts/ends/RegEx
- apply the search to key names instead of values
- return values instead of key names
- return matches as a string (specify separator)

- Other option possibilities (two parameters):
- first/last key to check

IN GENERAL

- The fact that HasKey exists might lead one to consider HasVal, but HasVal is too limited by itself, and immediately makes you think of GetKeys (Find/List/Match) (GetKeysThatHaveVal), so we immediately face questions reminiscent of InStr / 'StrMatch' / RegExMatch.
- I'm not normally too concerned that a function has all of the key features, because normally I can create a custom function. But with retrieving values from an object, custom functions could potentially be very slow/CPU intensive compared to built-in functions.
- Search functions have to be ambitious. Generally speaking they have to be super-functions, with a large number of options cf. the Sort command. They are usually the functions that pose the most questions when deliberating on the syntax. You have to try and get all the ideas for them out in the open as soon as possible, otherwise you create the wrong function, and you're stuck with it. And you get endless (sensible) wish list requests for additions.
- Here's a checklist of features such functions should probably have, that are relevant also when finding keys:
Improve InStr or IfInString - AutoHotkey Community
https://autohotkey.com/boards/viewtopic ... 79#p188879

- General points relating to functions that return arrays:
- There is a need to consider consistent syntax/recurring option parameters for functions that return arrays e.g. ControlGetList 'ControlGetItems', RegExMatch, WinGetList, WinGetControls, WinGetControlsHwnd. E.g. StrContains/StrExact/StrMatch functions that I have outlined in the link above.
- Should such functions have first result/delimited list strings as options. Delimited list strings as direct output might sound quirky, however, (a) StrJoin may(?) be slow for thousands of items versus the function appending as it goes, (b) searching an outputted string can be faster than searching an outputted array's values, (c) users commonly want to put a list of results on the clipboard.
- Before you use StrJoin/StrJoinReverse on an array, you need to identify a delimiter character. I had been wanting a function, 'StrUnused', to identify n characters not in any of an object's values (or not in any of the strings passed to it), to be used as delimiters/special delimiters for advanced parsing/temporary characters. A built-in StrUnused ('unused characters') function, that can handle arrays, could potentially be much faster/less CPU intensive than a custom StrUnused function. [EDIT:] Similarly I might want a way to check if a certain character, e.g. CR/LF, appears in any values. A special 'HasVal' search.
- [EDIT:] I've created a prototype ObjGetVals function here:
object get keys/values prototype function - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=6&t=43253
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
Flipeador
Posts: 1204
Joined: 15 Nov 2014, 21:31
Location: Argentina
Contact:

Re: Object.HasValue/Contains/KeyOf/FindValue

07 Apr 2018, 18:28

so... what happened with this?
Perhaps the best approach is to always return boolean, and if there's demand for additional functionality, a parameter or method can be added later.
+1 I agree. Although with CaseOrTypeSensitive included; this parameter should not be changed in the future (like InStr) so I do not see any problem.
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: Object.HasValue/Contains/KeyOf/FindValue

08 Apr 2018, 23:26

Initial proposal in OP:
Boolean := Object.HasValue(Value, CaseOrTypeSensitive, Key)

My proposal (essentially the same):
vBoolean := Object.HasValue(vValue, vOpt, vMatch) ;vMatch is first match as string ('all' mode off) (default)
vCount := Object.HasValue(vValue, vOpt, oMatch) ;oMatch is all matches as object ('all' mode on)

Note: the options in the prototype function could be expanded somewhat.

Prototype function:

Code: Select all

;;e.g.
;q::
;oArray := {k1:"a", k2:"b", k3:"c", k4:"a", k5:"a"}
;MsgBox, % JEE_ObjHasVal(oArray, "a", "", vMatch) ;1
;MsgBox, % vMatch ;k1
;MsgBox, % JEE_ObjHasVal(oArray, "a", "A", oMatch) ;3
;MsgBox, % oMatch.1 " " oMatch.2 " " oMatch.3 ;k1 k4 k5
;return

;returns boolean (or count if 'all' mode is on)
;options: A: 'all' mode on: oMatch will contain all matching keys as an object ('all' mode off: oMatch will contain the first matching key as a string)
;options: N: numeric comparison
;options: T: text comparison
JEE_ObjHasVal(oArray, vNeedle, vOpt:="", ByRef oMatch:="")
{
	oMatch := []
	vRetAll := InStr(vOpt, "A")
	if (InStr(vOpt, "N") && InStr(vOpt, "T"))
	|| !IsObject(oArray)
	{
		if !InStr(vOpt, "A")
			oMatch := ""
		return
	}
	if !InStr(vOpt, "N") && !InStr(vOpt, "T") ;general comparison
		for vKey, vValue in oArray
			if (vValue = vNeedle)
			{
				oMatch.Push(vKey)
				if !vRetAll
					break
			}
	if InStr(vOpt, "N") ;numeric comparison
		for vKey, vValue in oArray
			if (vValue+0 = vNeedle+0)
			{
				oMatch.Push(vKey)
				if !vRetAll
					break
			}
	if InStr(vOpt, "T") ;text comparison
		for vKey, vValue in oArray
			if (vValue = vNeedle "")
			{
				oMatch.Push(vKey)
				if !vRetAll
					break
			}
	if vRetAll
		return oMatch.Length()
	else
	{
		vCount := oMatch.Length()
		oMatch := vKey
		return vCount
	}
}
Last edited by jeeswg on 10 Apr 2018, 17:29, edited 2 times in total.
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: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: Object.HasValue/Contains/KeyOf/FindValue

09 Apr 2018, 00:15

I personally despise the use of options like this.
It also seems towards me that there is always a better solution than using ByRef e.g. if the search is unsuccessfull return "" if it is successfull return an array with keys that contains the value/values.
( in your function that would be just returning oMatch )
The only option we really need is a Search all flag. I think your T and N options are kinda redundant.
Since the user could just do the type conversion of the string mode completely by themselves and I dont see a reason why youd ever want to use the N mode at all.
I'd also rather prefer different functions for looking for only one value and for returning all values. ( rather than a flag make it a different function )
Recommends AHK Studio
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: Object.HasValue/Contains/KeyOf/FindValue

09 Apr 2018, 07:18

Here is what I would suggest

Code: Select all

;testArray := [ "abc", " def ", "ghi ", "jkl ", "mno ", "abc" ]
;Msgbox findValue( testArray, "mno " ).1 " is the index of the value `"mno `""
;Msgbox findValues( testArray, "abc" ).Length() " is the number of times the string `"abc `" exists inside the array"
;arr := findValues( testArray, "\s", ( needle, value ) =>( value ~= needle ) )
;Msgbox arr.length() " is the number of strings that contain any whitespace"
;Msgbox arr.1 " is the first index that contains whitespace `n`"" testArray[arr.1] "`" is it's value." 

findValue(oArray, vNeedle, compareFn := "")
{
	if (!IsObject(oArray))
		throw Exception( ".Contains expects an object as its first parameter" )
	if !compareFn {
		for vKey, vValue in oArray
			if (vValue = vNeedle) {
				oMatch := [ vKey ]
				break
			}
	} else {
		for vKey, vValue in oArray
			if (%compareFn%(vNeedle,vValue)) {
				oMatch := [ vKey ]
				break
			}
	}
	return oMatch	
}

findValues(oArray, vNeedle, compareFn := "")
{
	if (!IsObject(oArray))
		throw Exception( ".Contains expects an object as its first parameter" )
	oMatch := []
	if !compareFn {
		for vKey, vValue in oArray
			if (vValue = vNeedle)
				oMatch.Push( vKey )
	} else {
		for vKey, vValue in oArray
			if (%compareFn%(vNeedle,vValue))
				oMatch.Push( vKey )
	}
	if !oMatch.length()
		return
	return oMatch	
}
Recommends AHK Studio
User avatar
Flipeador
Posts: 1204
Joined: 15 Nov 2014, 21:31
Location: Argentina
Contact:

Re: Object.HasValue/Contains/KeyOf/FindValue

09 Apr 2018, 07:54

I like what nnnik suggests. This gives us more control over the search and we give more participation to =>. I imagine that findValue returns an Array to know if it found the key or not... But if the key is not found (findValue/findValues), it should return zero and not an empty string/array. I never liked the concept of empty string as FALSE.

Maybe it could be:
0/Arr := Object.HasValue(Needle [, CompareFN, Limit := 1]) // Limit := -1 no limit (like StrReplace)
We could say that "TRUE / FALSE", remains. :)
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: Object.HasValue/Contains/KeyOf/FindValue

09 Apr 2018, 07:58

Well I dont really care about which of the false values we use.
Using a limit parameter seems like a reasonable idea - especially if it is used by StrReplace.
Recommends AHK Studio
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: Object.HasValue/Contains/KeyOf/FindValue

09 Apr 2018, 14:23

- @nnnik: I like this idea of allowing a comparison function, instead of creating complex Sort/StrMatch/ObjMatch functions with lots of comparison options.
- However, I would want AutoHotkey to have a lot of these comparison functions built-in, so that there are standard comparison functions which everyone can use, instead of a free-for-all. E.g. case sensitive/numeric/string/stable, starts/ends/contains/in.
- A key question would be whether Sort/StrMatch/ObjMatch(/ObjHasValue), could make use of the same function. In which case ObjMatch(/ObjHasValue), would need an option: this is a match if the comparison function return value is positive/zero/negative/non-positive/non-zero/non-negative (e.g. options GEL or PZN).
- So, 'GE', if a value is greater than or equal to the needle, according to the comparison function, keep the value.
- Otherwise you have to duplicate equivalent functions, based on whether it's a sort, or a comparison, or greater-than/less-than etc.
Last edited by jeeswg on 09 Apr 2018, 14:40, edited 2 times in total.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA

Return to “AutoHotkey Development”

Who is online

Users browsing this forum: No registered users and 21 guests