Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why doesn't AutoHotkey support default parameters in the middle of the parameter list?

In AutoHotkey, you can leave out arguments in the middle of a built-in function call as so:

MsgBox, 4,, Blah
MouseGetPos,,, MouseWin

You can also create functions with optional parameters à la C++:

Foobar(baz, blah="something")
{
  MsgBox baz=%baz%, blah=%blah%
}

However the docs say that when you create a function, you cannot have non-default parameters after a default parameter. Trying to do so will result in an interpreter error saying that the first non-default argument after a default argument requires a default.

Why? What’s wrong with calling it like so?

Foobar(baz, blah="something", blivet)
{
  MsgBox baz=%baz%, blah=%blah%, blivet=%blivet%
}

Foobar("cat",,"dog")

Is there a way to create functions with optional parameters in the middle?

like image 310
Synetech Avatar asked Oct 02 '12 05:10

Synetech


2 Answers

When you omit a parameter in a built-in command (not function), what you're really doing is passing an empty string. There are differences between these two cases:

  • Defining a function with an optional parameter followed by mandatory parameters.
  • Calling a command with an omitted optional parameter followed by optional parameters which have not been omitted.

With both MsgBox and MouseGetPos, all parameters are optional.

AutoHotkey 1.1 allows the following with user-defined functions:

Foobar(1,, 3)
Foobar(baz, blah="something", blivet="")
{
    MsgBox baz=%baz%, blah=%blah%, blivet=%blivet%
}

This is only possible when the parameter's default value is known (i.e. not when calling a function dynamically).


Allowing the middle parameter to be omitted

If you do not want to change the order of the parameters or make two of the three optional, you can do a bit of "juggling":

Foobar("baz", "blivet")
Foobar("baz", "blah", "blivet")
Foobar(baz, p2, p3="omitted")
{
    blah := p3="omitted" ? "default" : p2   ; optional
    blivet := p3="omitted" ? p2 : p3        ; required
    MsgBox baz=%baz%, blah=%blah%, blivet=%blivet%
}

This way, the function always requires at least two parameters, and you're effectively allowed to omit the parameter in the middle when calling the function. However, you need to reserve a (string or numeric) value to indicate the parameter has been omitted. This can be avoided with AutoHotkey 1.1 by using a variadic function:

Foobar("baz", "blivet")
Foobar("baz", "blah", "blivet")
Foobar(baz, p2, p3*)
{
    blah := p3.MaxIndex() ? p2 : "default"   ; optional
    blivet := p3.MaxIndex() ? p3[1] : p2     ; required
    MsgBox baz=%baz%, blah=%blah%, blivet=%blivet%
}

Alternatively, the function can be declared as Foobar(baz, p*) and you can base your conditionals on p.MaxIndex() (the number of additional parameters), but in that case, only the first parameter is mandatory.

like image 80
Lexikos Avatar answered Nov 16 '22 18:11

Lexikos


Two options... (workarounds...)

1. Put all the parameters with default values on the right...

Foobar(baz, blivet, blah="something")
{
  MsgBox baz=%baz%, blah=%blah%, blivet=%blivet%
}

Foobar("cat","dog")

2. Define an "empty" default value...

Foobar(baz, blah="something", blivet="")
{
  MsgBox baz=%baz%, blah=%blah%, blivet=%blivet%
}

Foobar("cat",,"dog")

I can't say why this is like this, but for now, there is no other way... (unless you modify autohotkey :P )
I guess that built-in functions don't work the same way.

like image 43
Joe DF Avatar answered Nov 16 '22 20:11

Joe DF