Making a real Enumerator instance Topic is solved

Get help with using AutoHotkey (v2 or newer) and its commands and hotkeys
sirksel
Posts: 224
Joined: 12 Nov 2013, 23:48

Making a real Enumerator instance

Post by sirksel » 15 Nov 2020, 20:16

As I've been extending the array class (as well as map and other classes) with DefineProp/DefineMethod to contain certain utility properties/methods, I've written some that return enumerators. For example, I've done things like this in array:

Code: Select all

enmr   ;reverse enumerator of (key,val) or (val) based on arity
  => (t:=this,  c:=this.length + 1,  (byref k, byref v:='`vna') 
    => --c>0 ? ((v=='`vna' ? k:=t[c] : (k:=c, v:=t[c])),  1) : (k:=v:='',  0))
It works fine. However, this really returns a Closure that can function as an enumerator, but it's not itself of the Enumerator type. I'd actually like to add some utility properties/methods that apply to all Enumerators via DefineProp/DefineMethod on the Enumerator prototype -- which I already know how to do.

Before I can do that though, I need to adjust the code in all my custom enumerators in various places (like the one above), to actually be of the built-in Enumerator type. Is there a simple way to do that? (I tried assigning to .base, but that didn't work for me, maybe because it changed the underlying type too much. I originally thought it might work since both Closure and Enumerator were subclasses of Func.)

swagfag
Posts: 6222
Joined: 11 Jan 2017, 17:59

Re: Making a real Enumerator instance  Topic is solved

Post by swagfag » 17 Nov 2020, 22:42

I tried assigning to .base, but that didn't work for me
to tell u what was wrong, id have to see the code
maybe because it changed the underlying type too much
no
thought it might work since both Closure and Enumerator were subclasses of Func.
thats kinda irrelevant, it would have worked regardless of the relationships between the objects
there is currently(a122) no convenient built-in ahk way of subclassing from Enumerators, which means ull have to do the subclassing urself manually at runtime every time such an object is required(unless u believe all Funcs, BoundFuncs, Closures and possibly other custom objects share Enumerator traits, in which case knock urself out and subclass once at the very start of the script):
  1. obtain a reference to the built-in Enumerator prototype somehow and keep it around somewhere
  2. insert said prototype wherever u see fit in ur object's prototype chain
eg, an instance of Closure is a Closure -> is a Func -> is an Object -> is an Any
an Enumerator prototype is a Func -> is an Object -> is an Any
u can replace the closure's Func prototype with the Enumerator prototype. the new chain then looks like this:
an instance of Closure is a Closure -> is an Enumerator -> is a Func -> is an Object -> is an Any

Code: Select all

global enumeratorPrototype := [].__Enum().Base

...

	enmr[] {
		get {
			t := this
			c := this.length + 1

			closure := (byref k, byref v:='`vna') => --c>0 ? ((v=='`vna' ? k:=t[c] : (k:=c, v:=t[c])),  1) : (k:=v:='',  0)
			
			closure.Base.Base := enumeratorPrototype
			
			return closure
		}
	}

Post Reply

Return to “Ask for Help (v2)”