Function Repository Resource:

FirstMatchingValue

Source Notebook

Evaluate expressions in turn until a given form is returned

Contributed by: Sjoerd Smit

ResourceFunction["FirstMatchingValue"][{expr1,expr2,},pattern]

evaluates expri in turn, returning the first result that matches pattern.

ResourceFunction["FirstMatchingValue"][{expr1,expr2,},patternrhs]

gives the value of rhs corresponding to the first value to match pattern.

ResourceFunction["FirstMatchingValue"][{expr1,expr2,},pattern,default]

gives default if no value matching pattern is found.

ResourceFunction["FirstMatchingValue"][expr,pattern,default, levelspec]

finds only objects that appear on levels specified by levelspec.

Details and Options

ResourceFunction["FirstMatchingValue"] works much like FirstCase but evaluates the listed expressions one-by-one and stops as soon as a matching results is found.
ResourceFunction["FirstMatchingValue"] has the HoldAll attribute and only evaluates default if no match was found.
ResourceFunction["FirstMatchingValue"] uses standard level specifications:
nlevels 1 through n
Infinitylevels 1 through Infinity
{n}level n only
{n1,n2}levels n1 through n2
The default value for levelspec in ResourceFunction["FirstMatchingValue"] is {1}.
ResourceFunction["FirstMatchingValue"] has the same options as FirstCase.

Examples

Basic Examples (2) 

Find the first integer in a list without evaluating the following elements:

In[1]:=
ResourceFunction[
 "FirstMatchingValue"][{Print["before"], 10, Print["after"]}, _Integer]
Out[1]=

Expressions with side effects are evaluated once to check the returned value:

In[2]:=
x = 2;
{x,
 ResourceFunction[
  "FirstMatchingValue"][{a, 2, ++x, 1 + 3, 5}, _Integer?OddQ],
 x}
Out[2]=

Scope (5) 

If no match is found, Missing["NotFound"] is returned:

In[3]:=
ResourceFunction["FirstMatchingValue"][{1, 2, 3}, _String]
Out[3]=

The third argument can be used to specify the backup expression that should be evaluated if no match is found. This expression is only evaluated if necessary:

In[4]:=
ResourceFunction["FirstMatchingValue"][{1, 2, 3}, _String, Echo["Hello"]]
Out[4]=
In[5]:=
ResourceFunction["FirstMatchingValue"][{1, "2", 3}, _String, Echo["Hello"]]
Out[5]=

FirstMatchingValue supports replacement rules on the matching element:

In[6]:=
ResourceFunction["FirstMatchingValue"][{a, 5/2, 6, 7, 8}, i_Integer :> Framed[i]]
Out[6]=

Condition (/;) can be used to check additional constraints on the obtained value:

In[7]:=
ResourceFunction["FirstMatchingValue"][{a, 5/2, 6, 7, 8},
 i_Integer :> With[{
    j = 2 i + 3
    },
   Framed[i] /; PrimeQ[j]
   ]
 ]
Out[7]=

FirstMatchingValue supports standard level specifications:

In[8]:=
ResourceFunction["FirstMatchingValue"][
     f[ g[ Echo[ a ], Echo[ 5/2 ] ], g[ Echo[ 1 + 1 ], Echo[ 7 ], Echo[ 8 ] ] ],
     i_Integer :> Framed[i],
     Missing[],
     {2}
 ]
Out[8]=

Properties and Relations (2) 

When given an explicit list of elements, FirstMatchingValue returns the same element as FirstCase:

In[9]:=
FirstCase[{a, 5/2, 6, 7, 8}, elem_ /; MatchQ[elem, _Integer]]
Out[9]=
In[10]:=
ResourceFunction["FirstMatchingValue"][{a, 5/2, 6, 7, 8}, _Integer]
Out[10]=

Unlike FirstCase, FirstMatchingValue does not evaluate any more expressions after a match has been found:

In[11]:=
FirstCase[{Echo[a], Echo[5/2], Echo[6], Echo[7], Echo[8]}, _Integer]
Out[11]=
In[12]:=
ResourceFunction[
 "FirstMatchingValue"][{Echo[a], Echo[5/2], Echo[6], Echo[7], Echo[8]}, _Integer]
Out[12]=

Applications (1) 

If you have a value that is expensive to compute and therefore worth storing for later use, FirstMatchingValue can be used to check various locations where the result could be stored and return the first successful lookup. The second evaluation of the following code will be much faster than the first:

In[13]:=
expensiveFunction[] := (Pause[5]; 1);
myValue = ResourceFunction["FirstMatchingValue"][{
   myValue,
   LocalSymbol["myValue"],
   Import["myValue.m"],
   expensiveFunction[]
   },
  _Integer
  ]
Out[14]=

Possible Issues (2) 

Because FirstMatchingValue is HoldAll, it does not work with symbols that have been defined as a List:

In[15]:=
list = {a, b, c, 5, 6, 7};
ResourceFunction["FirstMatchingValue"][list, _Integer]
Out[16]=

Evaluate overrules the hold attribute to recover the behavior of FirstCase:

In[17]:=
ResourceFunction["FirstMatchingValue"][Evaluate@list, _Integer]
Out[17]=

Publisher

Sjoerd Smit

Version History

  • 1.0.0 – 17 February 2020

Related Resources

License Information