AHK v2: converting/optimizing scripts Topic is solved

Get help with using AutoHotkey (v2 or newer) and its commands and hotkeys
User avatar
vvhitevvizard
Posts: 454
Joined: 25 Nov 2018, 10:15
Location: Russia

Re: Problems with objects and legacy syntax

11 Dec 2018, 14:19

oif2003 wrote:
11 Dec 2018, 13:07
But then wouldn't your second example (even if it worked) be equivalent to normal get{....}, set{....}?
don't know about run-time speed improvements, but we obviously get 1 line instead of 6 repetitive ones. Even more, with fat arrows we get a portable code snippet (just an expression) and can include many of them in 1 line. :D I'm just an apologist of compact code-writing style.
AHK gives an error if I place the closing curve bracket on the same line:

Code: Select all

class obj{
	str[_s]{ ;deref string
		get{return(%(m:=StrSplit(_s,".")).RemoveAt(1)%[m*])} ;ERROR: "Not a valid property's getter/setter!"
	}
Last edited by vvhitevvizard on 11 Dec 2018, 14:40, edited 3 times in total.
oif2003
Posts: 214
Joined: 17 Oct 2018, 11:43
Contact:

Re: Problems with objects and legacy syntax

11 Dec 2018, 14:23

vvhitevvizard wrote:
11 Dec 2018, 13:48
edited:

Code: Select all

	n:=20000000
	t:=A_TickCount
	loop(n)
		ostr1(p*) => p.length() > 1 && (%(m:=StrSplit(p[1],".")).RemoveAt(1)%[m*]:=p[2]) || %(m:=StrSplit(p[1],".")).RemoveAt(1)%[m*]
	a1:=A_TickCount-t
Hey, I think you forgot to call the functions there
User avatar
vvhitevvizard
Posts: 454
Joined: 25 Nov 2018, 10:15
Location: Russia

Re: Problems with objects and legacy syntax

11 Dec 2018, 14:25

oif2003 wrote:
11 Dec 2018, 14:23
Hey, I think you forgot to call the functions there
Oh indeed! my bad :D

It should be:

Code: Select all

	t:=A_TickCount
	ostr3(p*) => p.length() > 1 ?  obj.str[p[1]] := p[2] : obj.str[p[1]]
	loop(n)
		ostr3("a1.test.key3", "new")
	a3:=A_TickCount-t
but 2 previous ostr1 and ostr2 give me an error. (ahk v2, last alpha build #100):

Code: Select all

ostr1(p*) => p.length() > 1 && (%(m:=StrSplit(p[1],".")).RemoveAt(1)%[m*]:=p[2]) || %(m:=StrSplit(p[1],".")).RemoveAt(1)%[m*]
error: "No object to invoke"
Did u mean ? : operator instead?
oif2003
Posts: 214
Joined: 17 Oct 2018, 11:43
Contact:

Re: Problems with objects and legacy syntax

11 Dec 2018, 14:56

vvhitevvizard wrote:
11 Dec 2018, 14:25
Seems to run fine for me... you sure you didn't use [] instead of () by accident?

Code: Select all

class a {
	class test {
		static key := 0
	}
}

ostr1(p*) => p.length() > 1 && (%(m:=StrSplit(p[1],".")).RemoveAt(1)%[m*]:=p[2]) || %(m:=StrSplit(p[1],".")).RemoveAt(1)%[m*]

t:=A_TickCount
n:=1000000
loop(n)
	ostr1("a.test.key", "new")
a3:=A_TickCount-t

msgbox(a3 " : " a.test.key)
User avatar
vvhitevvizard
Posts: 454
Joined: 25 Nov 2018, 10:15
Location: Russia

Re: Problems with objects and legacy syntax

11 Dec 2018, 15:14

oif2003 wrote:
11 Dec 2018, 14:56
Seems to run fine for me... you sure you didn't use [] instead of () by accident?
was my mistake - I re-set a1 accidentally. well, back to results: 1375|1343|1891 : new. set/get variant seems to be 39% as slow in my case.
corrected code
Last edited by vvhitevvizard on 11 Dec 2018, 15:17, edited 1 time in total.
oif2003
Posts: 214
Joined: 17 Oct 2018, 11:43
Contact:

Re: Problems with objects and legacy syntax

11 Dec 2018, 15:16

Result: 3375 | 2843 | 2704 (ms) for 1,000,000 runs of a.test.key++
They are all pretty close in terms of performance, so take your pick!

Code: Select all

; a.test.key
class a {
	class test {
		static key := 0
	}
}

; Test Case 1
ostr(p*) => p.length() > 1 ? (%(m:=StrSplit(p[1],".")).RemoveAt(1)%[m*]:=p[2]) : %(m:=StrSplit(p[1],".")).RemoveAt(1)%[m*]

; Test Case 2
class _deref {
	__New() {
		static initialize := new _deref()
		global deref := this
	}	
	__Set(s, value) {
		return %(m := StrSplit(s, ".")).RemoveAt(1)%[m*] := value
	}
	__Get(s) {
		return %(m := StrSplit(s, ".")).RemoveAt(1)%[m*] 
	}
}

; Test Case 3
class obj {
	str[s]{
		get {
			return(%(m := StrSplit(s, ".")).RemoveAt(1)%[m*])
		}
		set {
			%(m := StrSplit(s, ".")).RemoveAt(1)%[m*] := value
		}
	}
}

; Testing Case 1
t := A_TickCount
n := 1000000
loop(n)
	ostr("a.test.key", ostr("a.test.key") + 1)
a1 := A_TickCount - t

; Testing Case 2
t := A_TickCount
loop(n)
	deref["a.test.key"]++
a2 := A_TickCount - t

; Testing Case 3
t := A_TickCount
loop(n)
	obj.str["a.test.key"]++
a3 := A_TickCount - t

; Test Result
clipboard := a1 " | " a2 " | " a3
msgbox(clipboard)
User avatar
vvhitevvizard
Posts: 454
Joined: 25 Nov 2018, 10:15
Location: Russia

Re: Problems with objects and legacy syntax

11 Dec 2018, 15:21

oif2003 wrote:
11 Dec 2018, 15:16
Result: 3375 | 2843 | 2704 (ms) for 1,000,000 runs of a.test.key++
They are all pretty close in terms of performance, so take your pick!

Code: Select all

; Test Result
clipboard := a1 " | " a2 " | " a3  " : " a.test.key
msgbox(clipboard)
:thumbup: EXCELLENT!!! Result: 2250 | 2000 | 1875 : 3000000. last number proves that all the 3 methods work!
oif2003
Posts: 214
Joined: 17 Oct 2018, 11:43
Contact:

Re: Problems with objects and legacy syntax

11 Dec 2018, 15:24

Nice! and damn you with your fast pc! :D
User avatar
vvhitevvizard
Posts: 454
Joined: 25 Nov 2018, 10:15
Location: Russia

Re: Problems with objects and legacy syntax

11 Dec 2018, 15:32

oif2003 wrote:
11 Dec 2018, 15:24
Nice! and damn you with your fast pc! :D
Just overclocked and optimized IvyBridge (2011 year's CPU) and de-bloated Win 7 x64 SP1

btw, when I tried to fat-arrow __Set metafunction declaration, it didn't work :D

Code: Select all

	__New() {
		static _:=new _deref()
		global deref:=this
		this.__Set:=(_s,_v) =>%(m:=StrSplit(_s, ".")).RemoveAt(1)%[m*]:=_v ;ahk accepts the syntax but it doesn't change values at run time.
	}
it seems it doesn't register __Set this way:

Code: Select all

for k,v in _deref
	s.=k "=" Type(v) " " Format("at 0x{:p}", &v) "|"
msgbox(clipboard:=s)
output: __Class=String | __Get=Func | __New=Func
__Class=String at 0x000000000063F2D0|__Get=Func at 0x000000000064EAD0|__New=Func at 0x000000000064E218
User avatar
vvhitevvizard
Posts: 454
Joined: 25 Nov 2018, 10:15
Location: Russia

Re: Problems with objects and legacy syntax

11 Dec 2018, 16:25

bingo! I managed it. replaced this with _deref (this way it adds to the class.base properties/methods/keys) and added _ (just a placeholder for an argument b/c we don't use this in here) to arguments list:
_deref.__Set:=(_, _s,_v) =>%(m:=StrSplit(_s, ".")).RemoveAt(1)%[m*]:=_v
:D

output:
__Class=String at 0x000000000052F2D0|__Get=Func at 0x000000000053EB70|__New=Func at 0x000000000053E218|__Set=Func at 0x000000000053E630|

1

Code: Select all

class a{
	static test:={"key":0}
}

class _deref{
	__New() {
		static _:=new _deref()
		global deref:=this
		static _deref.__Set:=(_, _s,_v) =>%(m:=StrSplit(_s, ".")).RemoveAt(1)%[m*]:=_v
		static _deref.__Get:=(_, _s) =>%(m := StrSplit(_s, ".")).RemoveAt(1)%[m*]
	}
}

for k,v in _deref
	s.=k "=" Type(v) " " Format("at 0x{:p}", &v) "|"
deref["a.test.key"]++
	s.="`n`n" a.test.key
Last edited by vvhitevvizard on 11 Dec 2018, 16:59, edited 4 times in total.
User avatar
vvhitevvizard
Posts: 454
Joined: 25 Nov 2018, 10:15
Location: Russia

Re: Problems with objects and legacy syntax

11 Dec 2018, 16:46

when I use this as an object in __New():

Code: Select all

this.__Set:=(_, _s,_v) =>%(m:=StrSplit(_s, ".")).RemoveAt(1)%[m*]:=_v
...
for k,v in deref
	s.=k "=" Type(v) " " Format("at 0x{:p}", &v) "|"
msgbox(clipboard:=s)
it does add to deref __Set=Func at 0x000000000067E630

Code: Select all

for k,v in _deref
	s.=k "=" Type(v) " " Format("at 0x{:p}", &v) "|"
msgbox(clipboard:=s)
and _deref methods __Set=Func at 0x000000000061E630|__Class=String at 0x0000000000649BE0|__Get=Func at 0x000000000061EB70|__New=Func at 0x000000000061E218


but doesn't work with deref["a.test.key"]++ yet
Last edited by vvhitevvizard on 11 Dec 2018, 17:04, edited 1 time in total.
User avatar
vvhitevvizard
Posts: 454
Joined: 25 Nov 2018, 10:15
Location: Russia

Re: Problems with objects and legacy syntax

11 Dec 2018, 16:58

the code above with _deref instead of this didn't feel right, so I shrank it a bit again:

Code: Select all

class _deref{
	static __Set:=(_, _s,_v) =>%(m:=StrSplit(_s, ".")).RemoveAt(1)%[m*]:=_v
	static __Get:=(_, _s) =>%(m := StrSplit(_s, ".")).RemoveAt(1)%[m*]
	__New() {
		static _:=new _deref()
		global deref:=this
	}
}
it works.

BUT If I try to simplify it down to just 2 lines:

Code: Select all

class deref{
	static __Set:=(_, _s,_v) =>%(m:=StrSplit(_s, ".")).RemoveAt(1)%[m*]:=_v
	static __Get:=(_, _s) =>%(m := StrSplit(_s, ".")).RemoveAt(1)%[m*]
}
it doesn't work. it registers 2 metafunctions but doesn't change the value (output=0)
__Class=String at 0x000000000057F2A0|__Get=Func at 0x000000000058E850|__Set=Func at 0x000000000058E2D0|

0
oif2003
Posts: 214
Joined: 17 Oct 2018, 11:43
Contact:

Re: Problems with objects and legacy syntax

11 Dec 2018, 17:03

vvhitevvizard wrote:
11 Dec 2018, 16:58
Wow, nice!!
Haha, since no one is ever going to try and decipher this, we now have:

Code: Select all

_deref := {__Set:(_,s,v)=>%(m:=StrSplit(s,".")).RemoveAt(1)%[m*]:=v, __Get:(_,s)=>%(m:=StrSplit(s,".")).RemoveAt(1)%[m*]}, deref := new _deref()
As a side effect, I think now it's almost as fast as the obj.str version
Last edited by oif2003 on 11 Dec 2018, 17:23, edited 1 time in total.
User avatar
vvhitevvizard
Posts: 454
Joined: 25 Nov 2018, 10:15
Location: Russia

Re: Problems with objects and legacy syntax

11 Dec 2018, 17:19

quest to perfection is drawing near the end, my friend! =) but its still 2 globals (deref and _deref). 1 supernumerary global and 1 supernumerary line of code.
I hope someone to chime in and help us out to reduce the code even further
oif2003 wrote:
11 Dec 2018, 17:03
As a side effect, I think now it's almost as fast as the obj.str version
12 lines down to 4(5) :D it improves its loading time at least
Last edited by vvhitevvizard on 11 Dec 2018, 17:24, edited 3 times in total.
oif2003
Posts: 214
Joined: 17 Oct 2018, 11:43
Contact:

Re: Problems with objects and legacy syntax

11 Dec 2018, 17:23

Now one!

Code: Select all

deref := new {__Set:(_,s,v)=>%(m:=StrSplit(s,".")).RemoveAt(1)%[m*]:=v, __Get:(_,s)=>%(m:=StrSplit(s,".")).RemoveAt(1)%[m*]}
User avatar
vvhitevvizard
Posts: 454
Joined: 25 Nov 2018, 10:15
Location: Russia

Re: Problems with objects and legacy syntax

11 Dec 2018, 17:26

oif2003 wrote:
11 Dec 2018, 17:23
Now one!
:D 1 but actually a very long one - I would split in 2. and still 2 globals. can't we dispense with the class instantiation?

about runtime speed - as expected it didn't change b/c we didnt change in methods' logic since then: 2203 | 2000 | 1859 : 3000000
Last edited by vvhitevvizard on 11 Dec 2018, 17:30, edited 3 times in total.
oif2003
Posts: 214
Joined: 17 Oct 2018, 11:43
Contact:

Re: Problems with objects and legacy syntax  Topic is solved

11 Dec 2018, 17:29

I don't know. I'm happy with the result. At least there is no more _deref.

Comparing the length to fat arrow function, I think we've done quite well!

Code: Select all

ostr(p*) => p.length()>1 ? (%(m:=StrSplit(p[1],".")).RemoveAt(1)%[m*]:=p[2]) : %(m:=StrSplit(p[1],".")).RemoveAt(1)%[m*]

deref := new {__Set:(_,s,v)=>%(m:=StrSplit(s,".")).RemoveAt(1)%[m*]:=v, __Get:(_,s)=>%(m:=StrSplit(s,".")).RemoveAt(1)%[m*]}
User avatar
vvhitevvizard
Posts: 454
Joined: 25 Nov 2018, 10:15
Location: Russia

Re: Problems with objects and legacy syntax

11 Dec 2018, 17:32

wow! now u got rid of the 2nd global! :D And we got rid of static statements in the bargain - I didn't even pay any attention
Comparing the length to fat arrow function, I think we've done quite well!
yeah. deref[] variant is preferable imho, it feels just right and logic. tho a bit slower
oif2003
Posts: 214
Joined: 17 Oct 2018, 11:43
Contact:

Re: Problems with objects and legacy syntax

11 Dec 2018, 17:35

vvhitevvizard wrote:
11 Dec 2018, 17:32
yeah. deref[] variant is preferable imho, it feels just right and logic. tho a bit slower
Yeah, the fat arrow one is the slowest anyway. Kind of hard to beat obj.str version, god I hate that dot! At least we can do ++ with this version (unlike the fat arrow version). :D
User avatar
vvhitevvizard
Posts: 454
Joined: 25 Nov 2018, 10:15
Location: Russia

Re: Problems with objects and legacy syntax

11 Dec 2018, 17:37

oif2003 wrote:
11 Dec 2018, 17:35
Kind of hard to beat obj.str version, god I hate that dot!
I can't wait for lexikos to extend fat arrow support to property "half-methods" ;)
I guess (correct me if I'm wrong) metafunctions just don't work for prototype classes and objects created with {} thats why we need to instantiate it first. its not an issue for small classes with 1 task (1 property) but still doesn't feel right b/c we don't exploit inheritance and other goodies of OOP in the case but just a mere property emulation for the sake of code size reduction.
fat arrows for properties would be perfection!
At least we can do ++ with this version (unlike the fat arrow version). :D
yuppers! Actually the framework is quite functional for other tasks.

btw, with nested levelness increase, fat-arrow function method (aka Testing Case 1) starts slowing down unproportionally compared to deref[] method (aka Testing Case 2):

Code: Select all

class a{
	static b:={"c":{"key":0}}
}
2301 | 2046 | 1922 : 3000000
+4.5% | +2.3% | +3.4%

2.
From another topic: here is a version I ended up with for self-initializing prototype class with __Get, __Call, etc meta-functions functioning w/o instantiation.

Code: Select all

ClassN:={base:ClassN}
class ClassN{
	static __Call:=(_, _method, _args*) =>_args[1]
}
MsgBox(ClassN.a2("1st arg"))
I tested Class1.base:=Class1 as well but it seems to work only for the first assignment
Last edited by vvhitevvizard on 04 Jan 2019, 19:27, edited 14 times in total.

Return to “Ask for Help (v2)”

Who is online

Users browsing this forum: bj8tr, mikeyww, niCode, Smile_ and 33 guests