Function Repository Resource:

NameValuePattern (1.0.0) current version: 1.0.1 »

Source Notebook

Define a pattern expression for matching optional arguments with defaults

Contributed by: Nik Murzin

ResourceFunction["NameValuePattern"][a1_,a2_,,an_,b1_:def1,b2_:def2,,bn_:defn]

makes a pattern for required arguments a1,a2,,an and optional arguments b1,b2,,bnwith corresponding defaults defi.

Details

ResourceFunction["NameValuePattern"] matches a sequence of required arguments followed by optional arguments.
Absent optional arguments bind to their default values.
Required arguments are ordered, optional arguments are orderless.
Optional arguments may be specified either with Optional, Rule or RuleDelayed
Python users may recognize this pattern as *args and **kwargs.

Examples

Basic Examples (2) 

Construct a name-value pattern with one required argument and two optional ones:

In[1]:=
ResourceFunction["NameValuePattern"][a_, b_ : "B", c_ : "C"]
Out[1]=

Use NameValuePattern as any other pattern with functions like MatchQ or Replace:

In[2]:=
MatchQ[{1, "c" -> 3, "b" -> 2}, {ResourceFunction["NameValuePattern"][a_, b_ : "B", c_ : "C"]}]
Out[2]=
In[3]:=
Replace[{1, "c" -> 3, "b" -> 2}, {ResourceFunction["NameValuePattern"][a_, b_ : "B", c_ : "C"]} :> {a, b, c}]
Out[3]=

Scope (6) 

Use head patterns:

In[4]:=
Replace[{"b" -> 2., "a" -> 1}, {ResourceFunction["NameValuePattern"][a_Integer : 1, b_Real : "B"]} :> {a, b}]
Out[4]=

Arguments with no default values bind to Sequence[]:

In[5]:=
Replace[{1}, {ResourceFunction["NameValuePattern"][a_, b_., c_ : "C"]} :> HoldComplete[a, b, c]]
Out[5]=

Rule can be used instead of Optional (:) to specify optional arguments:

In[6]:=
Replace[{"b" -> 2, "a" -> 1}, {ResourceFunction["NameValuePattern"][a_, b_ -> "B"]} :> {a, b}]
Out[6]=

RuleDelayed can be used to delay default values:

In[7]:=
Replace[{"b" :> 1 + 1}, {ResourceFunction["NameValuePattern"][a_ :> Echo["A"], b_ : "B"]} :> Hold[a, b]]
Out[7]=

NameValuePattern matches the longest sequence:

In[8]:=
Replace[{"b" -> 2, "a" -> 1, "b" -> 3}, {ResourceFunction["NameValuePattern"][a_, b_ -> "B"], opts___} :> {a, b, opts}]
Out[8]=

Bind to NameValuePattern as a sequence of arguments:

In[9]:=
Replace[{1, "c" -> 3, "b" -> 2, "k" -> 5}, {nvp : ResourceFunction["NameValuePattern"][a_, b_ : "B", c_ : "C"], opts___} :> {{nvp}, a, b, c, {opts}}]
Out[9]=

Applications (1) 

Define a function with flexible control over its arguments:

In[10]:=
compute[ResourceFunction["NameValuePattern"][x_, y_., f_ : Plus]] := f[x, y]
In[11]:=
compute[1]
Out[11]=
In[12]:=
compute[1, 2]
Out[12]=
In[13]:=
compute[2, 3, Power]
Out[13]=
In[14]:=
compute[4, "f" -> Factorial]
Out[14]=
In[15]:=
compute["f" -> Times, "x" -> 2, "y" -> 5]
Out[15]=

Properties and Relations (3) 

NameValuePattern can be used as an alternative to OptionsPattern:

In[16]:=
f[x_, OptionsPattern["a" -> 1]] := {x, OptionValue["a"]}
In[17]:=
f[7]
Out[17]=
In[18]:=
f[7, "a" -> 13]
Out[18]=
In[19]:=
g[ResourceFunction["NameValuePattern"][x_, a_ : 1]] := {x, a}
In[20]:=
g[7]
Out[20]=
In[21]:=
g[7, "a" -> 13]
Out[21]=

But it also allows specifying required arguments by name and in any order:

In[22]:=
g["a" -> 13, "x" -> 7]
Out[22]=

It can also be used at any depth:

In[23]:=
Replace[{{{"a" -> 13, "x" -> 7}}}, {{{ResourceFunction["NameValuePattern"][x_, a_ : 1]}}} :> {x, a}]
Out[23]=

Possible Issues (3) 

If an argument is a rule with its left-hand-side not being a valid name then it's considered as a literal rule:

In[24]:=
Replace[{1, "d" -> 4, "c" -> 3}, {ResourceFunction["NameValuePattern"][a_, b_ : "B", c_ : "C"]} :> {a, b, c}]
Out[24]=

If an unnamed argument is provided after a named argument then rules can also be interpreted literally:

In[25]:=
Replace[{1, "c" -> 3, 123}, {ResourceFunction["NameValuePattern"][a_, b_ : "B", c_ : "C"]} :> Hold[a, b, c]]
Out[25]=
In[26]:=
Replace[{1, "c" -> 3, "d" -> 2}, {ResourceFunction["NameValuePattern"][a_, b_ : "B", c_ : "C"]} :> Hold[a, b, c]]
Out[26]=

If multiple values are given for the same name, then it's not a valid match:

In[27]:=
MatchQ[{1, "c" -> 2, "c" -> 3}, {ResourceFunction["NameValuePattern"][a_, b_ : "B", c_ : "C"]}]
Out[27]=
In[28]:=
MatchQ[{1, "a" -> 2, "c" -> 3}, {ResourceFunction["NameValuePattern"][a_, b_ : "B", c_ : "C"]}]
Out[28]=

Neat Examples (1) 

All of the expressions here match the same pattern with bindings of symbols to their corresponding defaults:

In[29]:=
With[{lhs = HoldForm@{ResourceFunction["NameValuePattern"][a_, b_., c_ -> "C", d_ -> "D"]}, rhs = {a, b, c, d}},
 Grid[{#, Replace[
       #,
       ReleaseHold@lhs :> rhs
       ]} & /@ {{1, 2, 3, 4}, {1}, {1, 2}, {1, "d" -> 40}, {1, 2, "c" -> 30}, {2, 1, "c" -> 30}, {1, 2, "d" -> 40}, {1, 2, "d" -> 40, "c" -> 30}, {1, "d" -> 40, "b" -> 20}, {"d" -> 40, "a" -> 10, "b" -> 20}} // Prepend[{lhs, rhs}], Alignment -> Left, Dividers -> {{False, True}, {False, True}}]
 ]
Out[29]=

Requirements

Wolfram Language 13.0 (December 2021) or above

Version History

  • 1.0.1 – 12 September 2023
  • 1.0.0 – 30 August 2023

Related Resources

License Information