2

I have a problem using optional arguments before an OptionsPattern:

Options[f] = {"Opt" -> None};
f[x_, y_:Automatic, OptionsPattern[]] := {x, y, OptionValue["Opt"]}
f[1, "Opt"->"wrong"] (* returns {1, "Opt" -> "wrong", None} *)

As you can see, mma assigns y the option rule, not Automatic!

What is the fix here?

This might be a known bug, as I remember encountering this type of thing before, or maybe I just forgot how to handle it?

M.R.
  • 31,425
  • 8
  • 90
  • 281
  • Duplicate of https://mathematica.stackexchange.com/questions/1567/how-to-avoid-collision-between-optional-arguments-and-options ? – Anton.Sakovich Feb 24 '20 at 13:22

1 Answers1

6

Make the pattern explicitly not match:

Options[f] = {"Opt" -> None};
f[x_, y : Except[_?OptionQ] : Automatic, OptionsPattern[]] := {x, y, OptionValue["Opt"]}
f[1, "Opt" -> "wrong"]

I have to say, though, mixing both optional args and Options has always felt wrong to me. In my mind, optional arguments are the lazy-person's Options (although it is nice that they can do the pattern matching up front). Is there any reason not to make y an option?

b3m2a1
  • 46,870
  • 3
  • 92
  • 239
  • The only real problem with mixing options and optional arguments is when the optional argument might be a Rule, so I try to avoid that. I do view options as generally distinct from arguments with default values. Options should be for parameters that rarely need changed, and things that are tangential to what you are really doing. Arguments are more central to the task at hand. – Jason B. Feb 24 '20 at 15:53
  • 1
    @JasonB. I'd say that the determining what is tangential and what is central to the task at hand is a pretty subjective call. So much so that I often find myself rewriting an interface to take only Options and required arguments after initially writing it to take optional args. For the most part I find myself wishing I had just made things options from the get-go. – b3m2a1 Feb 24 '20 at 16:02
  • Obviously it's subjective, but I still think it's a meaningful distinction. – Jason B. Feb 24 '20 at 16:23