Passing "unset" param to called function??

Get help with using AutoHotkey (v2 or newer) and its commands and hotkeys
Lorien
Posts: 33
Joined: 10 Dec 2019, 11:16

Passing "unset" param to called function??

Post by Lorien » 01 Oct 2021, 10:25

So, Unset can be used to detect if a parameter has been omitted... but how do I pass an omitted parameter to a function/method call? I'm fearing the answer is lots of IFs to route to the correct of 8 permutations of set/unset parameters.

Code: Select all

Notify.Add("hello world")

class NotifyWindow {
	__New(message := Unset, title := Unset, options := Unset) {...}
}
class Notify {
	static Add(message := Unset, title := Unset, options := Unset) {
		oWin := NotifyWindow(message, title, options)				;;; <----- Error: title has not been assigned a value
		...
	}
	...
}	

Lorien
Posts: 33
Joined: 10 Dec 2019, 11:16

Re: Passing "unset" param to called function??

Post by Lorien » 01 Oct 2021, 12:53

I don't particularly like it, because IsSet is no longer useful in NotifyWindow.__New, but this works.

Code: Select all

		oWin := NotifyWindow((IsSet(message)? message :""), (IsSet(title)? title :""), (IsSet(options)? options :{}))

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

Re: Passing "unset" param to called function??

Post by swagfag » 02 Oct 2021, 08:32

there are ways to propagate it, but there are no clean ways

Code: Select all

#Requires AutoHotkey v2.0-beta.1

Notify.Add("hello world")

class NotifyWindow {
	__New(message := Unset, title := Unset, options := Unset) {
		MsgBox(
			'IsSet(message)`t' IsSet(message) '`n' ; 1
			'IsSet(title)`t' IsSet(title) '`n'     ; 0
			'IsSet(options)`t' IsSet(options) '`n' ; 0
		)
	}
}
class Notify {
	static Add(message := Unset, title := Unset, options := Unset) {
		Args := []
		Args.Length := 3

		if IsSet(message)
			Args[1] := message
		
		if IsSet(title)
			Args[2] := title
		
		if IsSet(options)
			Args[3] := options
		
		oWin := NotifyWindow(Args*)
	}
}
viewtopic.php?p=337442#p337442
viewtopic.php?f=82&t=81627

iseahound
Posts: 1444
Joined: 13 Aug 2016, 21:04
Contact:

Re: Passing "unset" param to called function??

Post by iseahound » 04 Oct 2021, 21:49

Unfortunately there needs to be a null / unset type of sorts.

sirksel
Posts: 222
Joined: 12 Nov 2013, 23:48

Re: Passing "unset" param to called function??

Post by sirksel » 05 Oct 2021, 08:24

You've probably already thought of this, but I just use a global quasi-constant called na as a null sentry for unspecified parameters. swagfag referenced my earlier posts, but I've refined things a bit since then, especially with some of the recent additions to AHK (e.g., variadic varrefs). I'll try to state the null sentry approach more cleanly here...

This sentry can be propagated at will, but the approach does have some limitations. Ideally it would point to a singleton object that would never occur as a valid value. However, since default values must be primitives, I just set the global na := '`vna', since the vertical tab '`v' would rarely be present in any strings I use. So in defining defaults, I must use the string literal:

Code: Select all

static Add(message := '`vna', title := '`vna', options := '`vna') {
  oWin := NotifyWindow(message, title, options)
}
Then I can propagate it as needed, and can use the global na form (for readability and ease of typing) wherever it's finally used:

Code: Select all

class NotifyWindow {
  __New(message := '`vna', title := '`vna', options := '`vna') {
    (message == na ? (message := '') :0)
    (title == na ? (title := '') :0)
    (options == na ? (options := {}) :0)
  }
}
This pattern comes up so often that I use a function to set defaults (which is much simpler now with AHK having the ability to handle variadic varrefs):

Code: Select all

setdefaults(pairs*) {        ;parses variadic for varref,default pairs
  loop (pairs.length//2)
    if %pairs[a_index*2-1]% == na
      %pairs[a_index*2-1]% := pairs[a_index*2]
}
Then, the consuming function looks a little prettier. However, this only works well with simple defaults that entail no side effects or expensive computations. Unlike the prior approach, there is no short circuit. All defaults are evaluated when setdefaults is called. In this example, it's maybe not the best, unless you have a global "constant" empty object that isn't recreated on each call (assuming your function won't be modifying that empty object):

Code: Select all

na := '`vna',  empty := {}    ;somewhere in your global defs

class NotifyWindow {
  __New(message := '`vna', title := '`vna', options := '`vna') {
    setdefaults(message,'' , title,'' , options,empty)
  }
}
N.B. Since there are no true constants in AHK, I've occasionally experienced self-inflicted errors related to the global na or empty value being altered accidentally. Caveat emptor. Anyhow, hope that's maybe helpful in some way.

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

Re: Passing "unset" param to called function??

Post by lexikos » 01 Jul 2022, 20:53

v2.0-beta.6 allows this:

Code: Select all

class Notify {
	static Add(message?, title?, options?) {
		oWin := NotifyWindow(message?, title?, options?)
		...
	}
	...
}	

Post Reply

Return to “Ask for Help (v2)”