# Type safety and scoping in OptionsPattern arguments

I am new to OptionsPattern. Consider

ClearAll[rf, n];
rf[x1_, OptionsPattern[{n -> 100}]] := Module[{N},
N = OptionValue@n;
Print@{x1, OptionValue@n};
]
rf[99, n -> "typeViolator!"]
(*{99,typeViolator!}*)


A simple function r'f is defined with an option nof default value 100. n is meant to be an int.

1. As seen in the example, during invocation, n can be set to any type. How to ensure type safety while defining OptionsPattern? (something like n_Integer?)

2. One had to ClearAll[n] before using it within OptionsPattern. Is there a way to avoid this i.e some better way to writing OptionsPattern without worrying about pre-definitions of its args?

3. Note that my module speciically makes available n, as N. (Yes, it hides the in-built function N, but assume that in the present scenario, variable names like N,D,I etc are necessary within the module and don't lead to code conflicts). I was forced to do this as using

rf[...,OptionsPattern[N->100,...]]:=Module[{N},
^                     ^
|                     |
1                     2
OptionValue@N

]


causes collision between the shown positions 1 and 2 rendering OptionValue@N  useless. Also note that re-writing OptionsPattern@N within the module every time isn't feasible.
How does one define an OptionsPattern resembling OptionsPattern[{N_Integer->4,D_Integer->4}] while keeping all this and the above questions in mind ?

All clarifications are appreciated.

• f[x_, opts: OptionsPattern[]] /; checkOpts[opts] := Module[..]? f[x_, opts: OptionsPattern[]] := With[{optvals = processOpts[opts]}, Module[..] /; FreeQ[optvals, \$Failed]]? (Here, processOpts might construct an association of option values, so that optvals@n would yield the value.) Dec 18 '20 at 22:53

Consider this alternative that more easily enforces type on n using two alternative definitions, the first one with the integer type, the second "default" one when n is not an integer, essentially similar to an error handler. You could also omit the second one and rf would simply not evaluate when there is a type mismatch.

ClearAll[rf, n];
rf[x1_, n_Integer: 100] := {x1, n}
rf[x1_, n_] := "mismatched option type!"


Let's try explicit values for both parameters:

rf[3, 2]                  (* Out: {3, 2} *)


Now let's use the default value for n:

rf[3]                     (* Out: {3, 100} *)


And finally a mismatch:

rf[99, "typeViolator!"]   (* Out: "mismatched option type!" *)
`
• this doesn't help...though thanks for illustrating overloading. The problem is I am using 10's of function arguments and really do want to redefine most into Options. Writing multiple overloaded forms for these many arguments isn't really practical Dec 18 '20 at 20:33
• @lineage I understand. However, as far as I know you may be forced to explicitly type-check those option values within your implementation function. Automated "type-checking" would be the main advantage of the multiple-definition approach. Dec 18 '20 at 21:20