ObjCount() or ObjLength() or ObjLen()

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

Re: ObjCount() or ObjLength() or ObjLen()

31 Jul 2014, 00:57

Enumerating over a custom range can be done already, hiding the details away in a class. For example,

Code: Select all

array := ["a", "b", "c", "d", "e"]
object := {a:1,b:2,c:3,d:4,e:5}

s := ""
for k,v in Range(array, 2, 4)  ; Integers 2 to 4
	s .= k "=" v "`n"

s .= "`n"
for k,v in Range(object, "", "c")  ; Strings up to "c"
	s .= k "=" v "`n"

MsgBox % s


class EnumRange {
	__new(obj, min, max) {
		this.obj := obj
		this.min := min
		this.max := max
	}
	_NewEnum() {
		if this.enm {
			; ... code to clone and reset goes here ...
		}
		return this
	}
	Next(ByRef a, ByRef b) {
		if !this.enm {
			this.enm := ObjNewEnum(this.obj)
			loop
				r := this.enm.Next(a, b)
			until !r || a >= this.min
		}
		else
			r := this.enm.Next(a, b)
		return r && a <= this.max
	}
}

Range(obj, min, max) {	; Optional function for readability.
	return new EnumRange(obj, min, max)
}
It's not very fast, though.
lexikos
Posts: 9690
Joined: 30 Sep 2013, 04:07
Contact:

Re: ObjCount() or ObjLength() or ObjLen()

31 Jul 2014, 01:12

How long is an array?

If you want to know, you can measure it.
HotKeyIt
Posts: 2364
Joined: 29 Sep 2013, 18:35
Contact:

Re: ObjCount() or ObjLength() or ObjLen()

31 Jul 2014, 05:02

lexikos wrote:
HotKeyIt wrote:By accident I found that Object.Length() is already superfluous and can be simply reproduced with Object.Push() so I would suggest to remove it completely.
Loop % array.Push()? No thanks. We do not want to make things more obscure and confusing.
In that case Object.Push() can be be used for _Length internally so ResultType Object::_Length can be removed.

Code: Select all

ResultType Object::CallBuiltin(LPCTSTR aName, ExprTokenType &aResultToken, ExprTokenType *aParam[], int aParamCount)
{
...
	case 'L':
		if (!_tcsicmp(aName, _T("Length")))
			return _Push(aResultToken, NULL, 0);
		break;
...
}
lexikos wrote:
I would suggest using Object.Clone([min,max]) to filter the array.
I thought about that when I added Clone, but it didn't seem worth the added code size. There would also be no natural way to specify object keys (the concept of range doesn't really apply). Clone([],"") is not natural/intuitive.
Yes there is no natural/intuitive way to specify objects so we could leave them unsupported (they are not used as keys very often anyway), so they would be copied only when Object.Clone() is used.
In my view Object.Clone(,"") for integers and Object.Clone("",) for strings looks quite acceptable and would be very useful.
lexikos wrote:
So instead using Loop Object.Length() we would use for k,v in Object.Clone(,[])
So instead of just looping, we have to create an empty array, then clone our array, then create an enumerator object and call its Next method once for each iteration. No thank you.
You are right, in most cases we would use Loop Object.Length() but there are cases where you want to loop string keys only where currently an If needs to be used in for-loop to filter interger keys.
Addtionally obj:={2:"val1",4:"val2",test:"val3"} cannot be enumerated with Loop Object.Length() but for k,v in Object.Clone(,"") would be able to.
HotKeyIt
Posts: 2364
Joined: 29 Sep 2013, 18:35
Contact:

Re: ObjCount() or ObjLength() or ObjLen()

31 Jul 2014, 10:15

I tried to implement Object.Clone([min,max]) in AutoHotkey_H v2 if anyone wants to try, seems to work good so far:

Code: Select all

obj:={1:1,2:2,5:5,test:"test",ahk:"ahk",var:"var"}
for k,v in obj.Clone(,"") ; only integer keys
  out1.=k "=" v "`n"
MsgBox % out1
for k,v in obj.Clone("") ; only string keys
  out2.=k "=" v "`n"
MsgBox % out2
for k,v in obj.Clone("t","x") ; only string keys from t - x
  out3.=k "=" v "`n"
MsgBox % out3
just me
Posts: 9574
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: ObjCount() or ObjLength() or ObjLen()

31 Jul 2014, 12:07

Code: Select all

Dummy1 := {0: True, Str: "True"}
Dummy2 := {Str: "True"}
MsgBox, 0, Object.Length, % "Dummy1: " . Dummy1.Length . " - Dummy2: " . Dummy2.Length
I know: Why would you be using it at all in that context?
lexikos
Posts: 9690
Joined: 30 Sep 2013, 04:07
Contact:

Re: ObjCount() or ObjLength() or ObjLen()

31 Jul 2014, 16:41

Please, if you have a suggestion, make a suggestion. Don't just post code.

All arrays begin at index 1, as I said. That array begins at 1 and ends at 0, therefore has -1 length. It makes sense in a twisted sort of way.

I can't see how it might be useful, so perhaps Length should ignore indices <= 0. That could be the difference between Push (returning the last index it inserted at) and Length. Either that or Push will also ignore indices <= 0 and just start at 1.
just me
Posts: 9574
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: ObjCount() or ObjLength() or ObjLen()

02 Aug 2014, 05:59

What I wanted to demonstrate is that the result for both objects is 0.
---------------------------
Object.Length 2.0-a049-ea663d0
---------------------------
Dummy1: 0 - Dummy2: 0
---------------------------
OK
---------------------------
lexikos
Posts: 9690
Joined: 30 Sep 2013, 04:07
Contact:

Re: ObjCount() or ObjLength() or ObjLen()

03 Aug 2014, 03:43

Thank you for pointing that out. I posted in haste without testing your code, and should have said "therefore has 0 length". However, you still haven't made a suggestion. What you've demonstrated is merely that the code produces the result that I originally intended.

-1 is the result you would get for {-1: something}. This was also intended.
just me
Posts: 9574
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: ObjCount() or ObjLength() or ObjLen()

03 Aug 2014, 04:28

Object.MaxIndex() has been changed to Object.Length() (or Object.Length) and now returns 0 if there are no integer keys, to make it easier to use.
IMO, the result of MaxIndex() which returned "" in this case, is more consistent.
lexikos
Posts: 9690
Joined: 30 Sep 2013, 04:07
Contact:

Re: ObjCount() or ObjLength() or ObjLen()

03 Aug 2014, 05:28

Consistent with what?

What is Length() less consistent with?

Returning an integer every time is more consistent than returning an integer most of the time.
just me
Posts: 9574
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: ObjCount() or ObjLength() or ObjLen()

03 Aug 2014, 06:59

lexikos wrote:Consistent with what?
Consistent with ... if there are no integer keys.

In my example, Dummy2 doesn't have any integer key, and Dummy1 has just one key 0. ....Length returns 0 in both cases. Same result for different cases, do you call that consistent? If no integer keys exist, then also no array exists which can have a property like Length.
lexikos
Posts: 9690
Joined: 30 Sep 2013, 04:07
Contact:

Re: ObjCount() or ObjLength() or ObjLen()

03 Aug 2014, 21:36

They aren't different cases. The length is measured from 1 to the end of the array. Neither array has any elements in that range, so 0 is the appropriate result. (But negative results are not appropriate.)

If no integer keys exist, the array is empty and therefore has 0 length.

How can the length of something be ""? That's not consistent with length measured any other way, or StrLen.
guest3456
Posts: 3469
Joined: 09 Oct 2013, 10:31

Re: ObjCount() or ObjLength() or ObjLen()

03 Aug 2014, 22:35

Why couldn't MaxIndex just return 0 for no integer keys? That probably would lessen the confusion

lexikos
Posts: 9690
Joined: 30 Sep 2013, 04:07
Contact:

Re: ObjCount() or ObjLength() or ObjLen()

03 Aug 2014, 22:55

Because there is no maximum index; not even 0. {-1:foo}.MaxIndex() would still return -1. The semantics are different, but Length has the behaviour you're describing.
guest3456
Posts: 3469
Joined: 09 Oct 2013, 10:31

Re: ObjCount() or ObjLength() or ObjLen()

03 Aug 2014, 23:44

lexikos wrote: Maybe those usages are so rare that it should fall on the user to implement their own solution/counting method, while we keep the API at minimal size (i.e. just Count, no Length or Min/MaxIndex).
I'm gonna bow out of this, but I think I'm gonna have to agree with the above.

For sparse arrays like ["val1",,"val3"], how would a missing key ever occur? If the user is correctly using the new array methods Push/Pop/InsertAt/RemoveAt, then this shouldn't ever happen, right? And if it did, and they messed up and lost a key, and then somehow needed to rely on a .Length property, that would be a design flaw imo, similar to trying to find the maximum window handle with the .Length property.

Perhaps I just don't see the use case for .Length. I guess people are meant to do Loop, % array.Length(), but I'm not sure why they wouldn't use for.

edit/
just thought of a reason, ha, to fix missing keys. But not sure why else

Code: Select all

array := ["one",, "three"]

loop, % array.length()
{
   if ! array[A_Index]
      array[A_Index] := "not missing anymore"
}

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

Re: ObjCount() or ObjLength() or ObjLen()

04 Aug 2014, 04:54

I didn't realise as yet, that each object contains an array, which is empty if no integer keys exist. But because Length is related to that array more than to the object itself, I suggest to call it ArrayLength.

Anyhow, as long as we have no explicit object type for AHK standard arrays (1-based fully-populated), I'd prefer to keep MinIndex() and MaxIndex() and add a Count property/method.
lexikos
Posts: 9690
Joined: 30 Sep 2013, 04:07
Contact:

Re: ObjCount() or ObjLength() or ObjLen()

04 Aug 2014, 21:37

guest3456 wrote:For sparse arrays like ["val1",,"val3"], how would a missing key ever occur?
Like that. That array is missing the "2" key. For a variadic function call, this would allow the second parameter to get its default value.
And if it did, and they messed up and lost a key, [...] that would be a design flaw imo,
If they messed up, obviously that would be a design flaw. I don't care about that case. There are reasons to intentionally use a Sparse Array, such as for variadic calls or to conserve memory. Aside from [x,,y], one would make an array sparse by assigning (or not assigning) to specific keys with x[index] := y, or by using x.Remove(index) instead of x.RemoveAt(index).
Perhaps I just don't see the use case for .Length. I guess people are meant to do Loop, % array.Length(), but I'm not sure why they wouldn't use for.
for has more overhead, and doesn't always fit the script's logic (but sometimes it's a better fit). Sometimes we want to start at a certain index, for instance. There could be any number of reasons to want the length of an array that don't involve enumerating all its elements. It all depends on what the array is being used for, and the programmer's thought process.

Return to “AutoHotkey Development”

Who is online

Users browsing this forum: Marium0505 and 24 guests