classic simple functions: Swap / Assign / Sign

Propose new features and changes
User avatar
jeeswg
Posts: 6844
Joined: 19 Dec 2016, 01:58
Location: UK

classic simple functions: Swap / Assign / Sign

09 May 2019, 09:55

- Swap (or VarSwap) / Assign / Sign.
- [EDIT:] And further functions here ranked by usefulness:
https://autohotkey.com/boards/viewtopic.php?f=13&t=64405&p=277017#p277017

- If built-in, you would probably use them, otherwise, you would use more verbose or cryptic code.
- They add clarity and elegance to scripts, and are more instructive, regarding intention, than the alternatives. Cf. the advantages brought by the Min/Max functions.
- (I view potential StrCount/StrRept functions as having similar advantages.)

- Swap: avoid using a temporary variable when swapping variables, simpler.
- Avoid time spent double-checking the code.
- (Perhaps also: ObjSwap (or ObjSwapKeys).)

- Assign (lower priority): saves writing out long variable names twice.
- Assign could also be used to write directly to A_ variables, making various SetXXX commands redundant. (Or are those A_ variables going to become writable in AHK v1 at some point?)

- Sign: avoid cryptic (n > 0) - (n < 0) or using a ternary operator.
- Simplifies longer expressions that check the sign.
- (An alternative to Sign(Num) would be NumCompare(Num, 0).)

- Some example code:

Code: Select all

q:: ;swap values
var1 := "a", var2 := "b"
Swap(var1, var2)
MsgBox, % var1 " " var2

oArray := ["a", "b"]
ObjSwap(oArray, 1, 2)
MsgBox, % oArray.1 " " oArray.2
return

Swap(ByRef var1, ByRef var2)
{
	temp := var1
	var1 := var2
	var2 := temp
}

ObjSwap(obj, key1, key2)
{
	temp := obj[key1]
	obj[key1] := obj[key2]
	obj[key2] := temp
}

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

w:: ;assign
var := "old value"
MsgBox, % var
old := Assign(var, "new value")
MsgBox, % var " " old
return

Assign(ByRef var, value)
{
	temp := var
	var := value
	return temp
}

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

e:: ;sign
MsgBox, % Sign(-123) " " Sign(0) " " Sign(123)
return

Sign(num)
{
	return (num > 0) ? 1 : (num < 0) ? -1 : 0
	;return (num > 0) - (num < 0)
}

;==================================================
Last edited by jeeswg on 25 Jul 2019, 19:44, edited 4 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
kczx3
Posts: 921
Joined: 06 Oct 2015, 21:39

Re: Swap / ObjSwap / Assign / Sign

10 May 2019, 18:54

Can't say I've ever had a need for any of these.
User avatar
jeeswg
Posts: 6844
Joined: 19 Dec 2016, 01:58
Location: UK

Re: Swap / ObjSwap / Assign / Sign

10 May 2019, 19:33

- I've essentially completed my Wish List 2.0.
- These, and IsNum/Num, in another thread, are the functions I am 50/50 on.

- Swaps are common in mathematical/sort algorithms.
- I'd rather use some kind of Swap function, than 3 assignments.
- One use is for start/end points, to make sure one variable contains the smaller number, e.g. in date functions.

- Sign is a built-in function in Excel for example. And is a counterpart to Abs.
- It is also in the JavaScript Math object.
Math - JavaScript | MDN
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math
- It's useful in relation to direction i.e. increments/decrements, handling signs e.g. with Mod, and functionality re. Floor/Round/Ceil.
- It's useful in date functions, to increment/decrement dates.
- It's used in the erf function, in relation to the gamma function (related to the cdf function and the normal distribution):
Error function - Wikipedia
https://en.wikipedia.org/wiki/Error_function
- I would be interested to hear of any other potential uses.

- I wouldn't mind too much if Assign wasn't implemented, since varcopy := var, var := "new value" is arguably more explicit than varcopy := Assign(var, "new value").
- However, (a) if A_ variables are not to be made writable in AHK v1, i.e. A_XXX := "new value", this would be a good alternative, (b) it might be useful in expressions, it's just that, since we haven't had it, people haven't thought to use it.
- There's different ways an Assign function could be implemented. Here's the AutoIt version:
Function Assign
https://www.autoitscript.com/autoit3/docs/functions/Assign.htm
Last edited by jeeswg on 13 Jun 2019, 01:28, edited 1 time 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
jeeswg
Posts: 6844
Joined: 19 Dec 2016, 01:58
Location: UK

Re: Swap / ObjSwap / Assign / Sign

12 May 2019, 23:31

In general, it's good when there is a one-to-one mapping between the idea and the code. Versus logic that is lower-level than how you thought it.

Here is a Swap function and two further convenience gains:

E.g. swap variables:

Code: Select all

;more intuitive:
Swap(var1, var2)

;less intuitive (3 assignments):
temp := var1, var1 := var2, var2 := temp
E.g. a Range function:

Code: Select all

;more intuitive:
for _, vValue in Range(-10, 10, 0.5)

;less intuitive (low-level workaround):
Loop, 41
	vValue := -10+(A_Index-1)*0.5
E.g. easily increment/decrement object values:
(Although a way to change the default value, from a blank string to 0, would be a better solution.)

Code: Select all

;more intuitive (method):
oArray := new ClassSetDefaultValue
oArray.SetDefaultValue(0)
oArray.key++
MsgBox, % oArray.key

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

;more intuitive (function):
oArray := new ClassSetDefaultValue
ObjSetDefaultValue(oArray, 0)
oArray.key++
MsgBox, % oArray.key

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

;also intuitive:
oArray := {}
ObjInc(oArray, "key")
MsgBox, % oArray.key

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

;less intuitive:
oArray := {}
vKey := "key"
if !oArray.HasKey(vKey)
	oArray[vKey] := 1
else
	oArray[vKey]++
MsgBox, % oArray.key

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

ObjSetDefaultValue(obj, default)
{
	obj.SetDefaultValue(default)
}

class ClassSetDefaultValue
{
	__New(default)
	{
		this.default := _default
	}
	__Get()
	{
		return this._default
	}
	SetDefaultValue(default)
	{
		this._default := default
	}
}

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

ObjInc(oArray, vKey)
{
	if !oArray.HasKey(vKey)
		oArray[vKey] := 1
	else
		oArray[vKey]++
}

ObjDec(oArray, vKey)
{
	if !oArray.HasKey(vKey)
		oArray[vKey] := -1
	else
		oArray[vKey]--
}

;==================================================
It's so common to increment/decrement keys, that it should be easier than a four-liner. Like Swap, it's not super-difficult to recreate the logic every time you need it, but it does require a reasonable/notable amount of thinking and checking time, and the repeated use of variable names that vary each time (limiting the utility of hotstrings in this case).
Last edited by jeeswg on 13 Jun 2019, 13:50, edited 3 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
jeeswg
Posts: 6844
Joined: 19 Dec 2016, 01:58
Location: UK

Re: Swap / ObjSwap / Assign / Sign

14 May 2019, 04:48

VARXXX FUNCTION SUITE
- I was thinking of a potential 'suite' of VarXXX functions: VarExist, VarGetName, VarSet(/Assign), VarSwap.
- Some other possible VarXXX functions are mentioned here:
VarSetCapacity - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=37&t=64493

ASSIGN TO ALLOW WRITABLE A_ VARIABLES
- Since I was informed here, that AHK v1 is unlikely to have writable A_ variables. E.g. A_StringCaseSense := 1.
A_ variables - Page 2 - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=37&t=41870&p=276824#p276824
- I thought a good two-way compatible workaround would be to have an Assign/VarSet function.
- In my version below, you have to pass A_ variables as strings, but, if it was built-in, or if there were a VarGetName function, you could pass them directly.
- Note: VarExist/VarSwap functions would accept variables directly (and would possibly accept variable names as strings also).

Code: Select all

q:: ;test Assign
vText := "value 1"
MsgBox, % vText
vTextOld := Assign(vText, "value 2")
MsgBox, % vTextOld "`r`n" vText

MsgBox, % A_StringCaseSense
vSCS := Assign("A_StringCaseSense", "On")
MsgBox, % vSCS "`r`n" A_StringCaseSense
return

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

;note: accepts normal variables ByRef
;note: accepts A_ variables as strings
Assign(ByRef vVar, vValue)
{
	local
	static vAllowMainWindow := !A_IsCompiled ;close approximation to A_AllowMainWindow

	;handle normal variables:
	if IsByRef(vVar)
	{
		vTemp := vVar
		vVar := vValue
		return vTemp
	}
	else if !(SubStr(vVar, 1, 2) = "A_")
		return

	;not handled:
	;A_Args (object)
	;A_IconFile (set by TraySetIcon)
	;A_IconNumber (set by TraySetIcon)
	;A_Index
	;A_TrayMenu (object)

	;partially handled:
	;A_AllowMainWindow (can set but cannot get)

	;handle A_ variables:
	if (vVar = "A_AllowMainWindow")
	{
		vRet := vAllowMainWindow
		if A_IsCompiled
			vAllowMainWindow := vValue
	}
	else
		vRet := %vVar%

	if (vVar = "A_AllowMainWindow")
		Menu, Tray, % vValue ? "MainWindow" : "NoMainWindow"
	else if (vVar = "A_ControlDelay")
		SetControlDelay, % vValue
	else if (vVar = "A_CoordModeCaret")
	|| (vVar = "A_CoordModeMenu")
	|| (vVar = "A_CoordModeMouse")
	|| (vVar = "A_CoordModePixel")
	|| (vVar = "A_CoordModeToolTip")
		CoordMode, % SubStr(vVar, 12), % vValue
	else if (vVar = "A_DefaultMouseSpeed")
		SetDefaultMouseSpeed, % vValue
	else if (vVar = "A_DetectHiddenText")
		DetectHiddenText, % vValue
	else if (vVar = "A_DetectHiddenWindows")
		DetectHiddenWindows, % vValue
	else if (vVar = "A_FileEncoding")
		FileEncoding, % vValue
	else if (vVar = "A_IconHidden")
		Menu, Tray, % vValue ? "NoIcon" : "Icon"
	else if (vVar = "A_IconTip")
		Menu, Tray, Tip, % vValue
	else if (vVar = "A_IsCritical")
		Critical, % vValue
	else if (vVar = "A_KeyDelay")
		SetKeyDelay, % vValue
	else if (vVar = "A_KeyDelayPlay")
		SetKeyDelay, % vValue,, Play
	else if (vVar = "A_KeyDuration")
		SetKeyDelay,, % vValue
	else if (vVar = "A_KeyDurationPlay")
		SetKeyDelay,, % vValue, Play
	else if (vVar = "A_LastError")
		DllCall("kernel32\SetLastError", "UInt",vValue)
	else if (vVar = "A_ListLines")
		ListLines, % vValue
	else if (vVar = "A_MouseDelay")
		SetMouseDelay, % vValue
	else if (vVar = "A_MouseDelayPlay")
		SetMouseDelay, % vValue, Play
	else if (vVar = "A_RegView")
		SetRegView, % vValue
	else if (vVar = "A_SendLevel")
		SendLevel, % vValue
	else if (vVar = "A_SendMode")
		SendMode, % vValue
	else if (vVar = "A_StoreCapsLockMode")
		SetStoreCapsLockMode, % vValue
	else if (vVar = "A_StringCaseSense")
		StringCaseSense, % vValue
	else if (vVar = "A_TitleMatchMode")
	|| (vVar = "A_TitleMatchModeSpeed")
		SetTitleMatchMode, % vValue
	else if (vVar = "A_WinDelay")
		SetWinDelay, % vValue
	else if (vVar = "A_WorkingDir")
		SetWorkingDir, % vValue
	return vRet
}

;==================================================
Last edited by jeeswg on 13 Jun 2019, 01:46, edited 1 time 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
jeeswg
Posts: 6844
Joined: 19 Dec 2016, 01:58
Location: UK

Re: Swap / ObjSwap / Assign / Sign

15 May 2019, 03:38

SUMMARY

Summary of classic convenience functionality mentioned:
And sureness for inclusion.

From thread title:
Swap(/VarSwap) [100%]
ObjSwap(/ObjSwapKeys/ObjSwapValues) [50%]
Assign(/VarSet) [50%, the key point is: writable A_ variables or *some* function to assign A_ variables]
Sign [related: NumCompare] [100%]

Also mentioned:
IsNum (is float/is integer/is string that looks numeric) [100%] [repeated '(var is "number")' seems too verbose]
Num (to number) [50%]
ObjSetDefaultValue [or another name, or: ObjDec/ObjInc] [100%, by *some* means]
Range [100%]
StrCount [100%]
StrRept [100%]
VarExist(/IsVar) [100%]
VarGetName [100%]

Also:
VarIsInit(/IsInit) [100%]
C++: AHK source code: VarIsInit - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=75&t=65308

Also, 'FUNCTIONS (SIMPLE WORKHORSE FUNCTIONS)' (Base64Get/Base64Put/HexGet/HexPut, Between/FloorMod/Pow, NoOp, StrJoin):
Wish List 2.0 - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=13&t=36789

Further, StrSetCapacity/StrSetSize:
VarSetCapacity - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=37&t=64493
Last edited by jeeswg on 26 Jul 2019, 10:13, edited 1 time 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
jeeswg
Posts: 6844
Joined: 19 Dec 2016, 01:58
Location: UK

Re: classic simple functions: Swap / Assign / Sign

13 Jun 2019, 14:02

ASSIGN: CYCLE VALUES
Here are some nice examples for Assign and ObjAssign:

Code: Select all

q:: ;cycle values via Assign/ObjAssign
v1 := "a", v2 := "b", v3 := "c", v4 := "d", v5 := "e"
Loop, 11
{
	MsgBox, % Format("{} {} {} {} {}", v1, v2, v3, v4, v5)
	Assign(v5, Assign(v4, Assign(v3, Assign(v2, Assign(v1, v5)))))
}

MsgBox

o := ["a", "b", "c", "d", "e"]
Loop, 11
{
	MsgBox, % Format("{} {} {} {} {}", o*)
	ObjAssign(o, 5, ObjAssign(o, 4, ObjAssign(o, 3, ObjAssign(o, 2, ObjAssign(o, 1, o.5)))))
}
return

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

w:: ;swap object key values via ObjAssign
obj1 := {}
obj2 := {}

obj1.key1 := "1"
obj2.key2 := "2"
MsgBox, % obj1.key1 " " obj2.key2 ;1 2
ObjAssign(obj1, "key1", ObjAssign(obj2, "key2", obj1.key1))
MsgBox, % obj1.key1 " " obj2.key2 ;2 1

obj1.key1 := "1"
obj2.key2 := "2"
MsgBox, % obj1.key1 " " obj2.key2 ;1 2
temp := obj1.key1, obj1.key1 := obj2.key2, obj2.key2 := temp
MsgBox, % obj1.key1 " " obj2.key2 ;2 1
return

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

Assign(ByRef var, value)
{
	local temp
	temp := var
	var := value
	return temp
}

ObjAssign(obj, key, value)
{
	local temp
	temp := obj[key]
	obj[key] := value
	return temp
}

;==================================================
Note: I've revised/expanded earlier posts.
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: 6844
Joined: 19 Dec 2016, 01:58
Location: UK

Re: classic simple functions: Swap / Assign / Sign

25 Jul 2019, 19:32

A lot of interest in 'ObjSetDefaultValue':

python - Dictionaries and default values - Stack Overflow
https://stackoverflow.com/questions/9358983/dictionaries-and-default-values

python - Why dict.get(key) instead of dict[key]? - Stack Overflow
https://stackoverflow.com/questions/11041405/why-dict-getkey-instead-of-dictkey
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 “Wish List”

Who is online

Users browsing this forum: No registered users and 7 guests