objects: define succinctly, retrieve dynamically

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

objects: define succinctly, retrieve dynamically

23 Jun 2017, 08:52

I'm looking for ways to define 'oArray.a.b.c := 3' as succinctly as possible.

I have a way to refer to an object and its key dynamically, which I mention in case anyone has any alternative ideas. I might use it in a custom Deref function. Cheers.

Code: Select all

q:: ;succinctly define/dynamically retrieve objects/keys

;one-liner definitions for 'oArray.a.b.c := 3'
oArray := {}, oArray["a","b","c"] := 3 ;can these be combined? (best so far)
MsgBox, % oArray.a.b.c

oArray := {"a":1}
MsgBox, % oArray.a
oArray := {"a":{"b":2}}
MsgBox, % oArray.a.b
oArray := {"a":{"b":{"c":3}}} ;short but unintuitive
MsgBox, % oArray.a.b.c

vObj := "oArray", vKey := "a.b.c"
%vObj% := {}, %vObj%[StrSplit(vKey, ".")*] := 3 ;dynamic and intuitive
MsgBox, % oArray.a.b.c

;retrieve object key's value dynamically (for possible use with a custom Deref function)
vObj := "oArray", vKey := "a.b.c"
MsgBox, % %vObj%[StrSplit(vKey, ".")*]
return
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
kon
Posts: 1756
Joined: 29 Sep 2013, 17:11

Re: objects: define succinctly, retrieve dynamically

23 Jun 2017, 10:18

jeeswg wrote:

Code: Select all

oArray := {}, oArray["a","b","c"] := 3 ;can these be combined? (best so far)

Code: Select all

(oArray := {})["a","b","c"] := 3
It's not much shorter, and maybe slightly less readable.
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: objects: define succinctly, retrieve dynamically

23 Jun 2017, 12:07

Omg cheers, very cool, nicely done. Hidden in plain sight.

Code: Select all

q::
(oArray := {})["a","b","c"] := 3
MsgBox, % oArray.a.b.c
return
@kon: Thanks for that.
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
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: objects: define succinctly, retrieve dynamically

23 Jun 2017, 12:26

I wanted a Deref function, that could handle objects with dot notation as well as variables, and I managed to make one. I was unsure what to do about literal percent signs, but then eventually I realised I could just have a variable that dereferenced to a percent sign.

Unfortunately the function is making use of a few variables, that I've given unlikely names to avoid any clashes.

Code: Select all

q:: ;dereference this
var := 10
vPS := "%"
(obj:={})["a","b","c"] := 20
MsgBox, % JEE_Deref("%var%%vPS% of %obj.a.b.c%")
return

;==================================================

JEE_Deref(vDerefText)
{
	global
	local vDerefOutput, vDerefPos, vDerefObj, vDerefKey
	vDerefOutput := ""
	Loop, Parse, vDerefText, % "%"
		if (A_Index & 1)
			vDerefOutput .= A_LoopField
		else if !(vDerefPos := InStr(A_LoopField, "."))
			vDerefOutput .= %A_LoopField%
		else
		{
			vDerefObj := SubStr(A_LoopField, 1, vDerefPos-1)
			vDerefKey := SubStr(A_LoopField, vDerefPos+1)
			vDerefOutput .= %vDerefObj%[StrSplit(vDerefKey, ".")*]
		}
	return vDerefOutput
}
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: objects: define succinctly, retrieve dynamically

23 Jun 2017, 15:41

Hi.
If you have an array of keys, a, you can use it to define (and assign) keys of another array, b, like this,

Code: Select all

b[a*]:=1
Your deref function will not work for local variables.

Cheers
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: objects: define succinctly, retrieve dynamically

23 Jun 2017, 15:55

Haha in a reversal of some posts where I've provided answers, I'm thinking 'err, examples please?' Anyhow I did some tests, I think I've got what you meant.

Code: Select all

q:: ;'if no-one objects'
a := ["d","e","f"]
b := {}
b[a*]:=1
MsgBox, % b.d.e.f

c := {1:"d",2:"e",3:"f"}
b := {}
b[c*]:=1
MsgBox, % b.d.e.f
return
==================================================

Yes I had said somewhere else, that the Deref function could only handle global variables and not variables local to a function, and that I was fine with that. Cheers though, it was worth pointing it out again here.

Re: v2.0-a079-be5df98 - Loop statements - AutoHotkey Community
https://autohotkey.com/boards/viewtopic ... 49#p153249

I'm not sure if there is any way around that, but that also ... does that mean that any AutoHotkey functions/commands that can handle variables local to functions, have special abilities that custom functions don't have.

==================================================

Btw something silly:

Code: Select all

q:: ;ErrorLevel as an object
ErrorLevel := {}
ErrorLevel.a := "A"
ErrorLevel.b := "B"
MsgBox, % ErrorLevel.a " " ErrorLevel.b
return
I thought that ErrorLevel might work as an object, and it did. Actually what prompted me to try this, was the idea that ErrorLevel could be used as a method of last resort for certain problems.

==================================================

Btw in reference to a one-liner in a post above. Nicely 'konceived'.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: objects: define succinctly, retrieve dynamically

23 Jun 2017, 17:32

Your example is what I meant.
Interesting observation regarding ErrorLevel, maybe it can be useful,

Code: Select all

; Unpolished
warnErrorLevel()
ErrorLevel:=1
f()
f(){
	warnErrorLevel()
	ErrorLevel:=1
}
return

warnErrorLevel(info:=""){
	if (info="")
		return ErrorLevel := new info:={__Delete:func("warnErrorLevel").bind([Exception("",-1).line ,Exception("",-2).what])}
	else
		Msgbox, % "ErrorLevel changed somewhere after line: " info.1 (info.2!=-2?" in " info.2 : "")
	return
}
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: objects: define succinctly, retrieve dynamically

28 Jun 2017, 19:28

I've come up with a variant Deref function, all the 'variables' are derived from an object, passed to a function. It would not suffer from issues to do with local v. global. Also, I thought that a 'variable' '%%' might be dereferenced to a percent sign.

I want to eliminate continuation sections from all of my scripts, because they are awkward for parsing and conversion to AHK v2 etc. At the same time, I may want some of my continuation sections to use command style variables within expressions, as some of them currently do.

(However in principle, I'm not against continuation sections at all, and I would like to see a 'verbatim' 'command' for one-line 'continuation sections', to work much like the current continuation sections do now, for storing text verbatim (or semi-verbatim, its workings based on an options parameter). It could look similar to a command, although it would be a bit like the curly brackets array notation ('obj := {}') ... unique.)

[EDIT:] (Continuation sections are very useful for temporary and single-purpose small scripts, especially for pasting in a list of CRLF-delimited items verbatim.)

Code: Select all

q:: ;continuation section alternative
;e.g.
vText = ;continuation section
(Join`r`n
a
b
c
)
MsgBox, % vText
;to
vText := ""
. "a" "`r`n"
. "b" "`r`n"
. "c"
MsgBox, % vText
return
==================================================

Code: Select all

;q:: ;dereference, and continuation section alternatives
oArray := {vDir:"C:\MyDir", vNameNoExt:"New Text Document", vNum:3, vExt:".txt"}
vPath := "%vDir%\%vNameNoExt% (%vNum%)%vExt%"
MsgBox, % JEE_Deref2(vPath, oArray)

vDir:="C:\MyDir", vNameNoExt:="New Text Document", vNum:=3, vExt:=".txt"
vPath := vDir "\" vNameNoExt " (" vNum ")" vExt
MsgBox, % JEE_Deref2(vPath, oArray)

vPath := A_AhkPath
SplitPath, vPath, vName, vDir, vExt, vNameNoExt, vDrive
vList := "Path,Name,Dir,Ext,NameNoExt,Drive"
oArray := {}
Loop, Parse, vList, % ","
	oArray["v" A_LoopField] := v%A_LoopField%
vText := ""
. "path: %vPath%`r`n"
. "name: %vName%`r`n"
. "dir: %vDir%`r`n"
. "ext: %vExt%`r`n"
. "name no ext: %vNameNoExt%`r`n"
. "drive: %vDrive%"
MsgBox, % JEE_Deref2(vText, oArray)

vText := ""
. "path: " vPath "`r`n"
. "name: " vName "`r`n"
. "dir: " vDir "`r`n"
. "ext: " vExt "`r`n"
. "name no ext: " vNameNoExt "`r`n"
. "drive: " vDrive
MsgBox, % vText

a := 10, b := 20
vText := a "% of " b
MsgBox, % vText

vText := "%a%%% of %b%"
oArray := {a:10,b:20}
MsgBox, % JEE_Deref2(vText, oArray)

vText := "%a%%PS% of %b%"
oArray := {a:10,b:20,ps:"%"}
MsgBox, % JEE_Deref2(vText, oArray)
return

;==================================================

JEE_Deref2(vText, oArray)
{
	vOutput := ""
	VarSetCapacity(vOutput, StrLen(vText)*2)
	Loop, Parse, vText, % "%"
		if (A_Index & 1)
			vOutput .= A_LoopField
		else if (A_LoopField = "")
			vOutput .= "%"
		else
			vOutput .= oArray[StrSplit(A_LoopField, ".")*]
	return vOutput
}
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
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: objects: define succinctly, retrieve dynamically

30 Jun 2017, 14:57

I like this notation trick, it's quite good for copying (cloning) and editing an existing array:

Code: Select all

q:: ;objects - copy and edit an existing array
oArray1 := ["a","b","c"]
(oArray2:=oArray1.Clone())[3] := "d"
(oArray3:=oArray1.Clone()).3 := "e"
Loop, 3
{
	vOutput := ""
	for vKey, vValue in oArray%A_Index%
		vOutput .= vKey " " vValue "`r`n"
	MsgBox, % vOutput
}
oArray1 := oArray2 := oArray3 := ""
return
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 “Ask for Help (v1)”

Who is online

Users browsing this forum: dunnerca, wilkster and 124 guests