Skip to main content
1 of 3
Mr.Wizard
  • 275.2k
  • 34
  • 606
  • 1.5k

My first answer explains that Mathematica's replacement rules perform destructuring.

This answer is intended to complement jVincent's method, which I see is appreciated. (This is not a bid for the bounty, which will automatically be awarded to jVincent's answer according to the rules, since the one giving the bounty has departed S.E.)

My aim is to provide Attributes for the pattern-based function. This requires that the head evaluate therefore SubValues may not be used. Here are two separate approaches.

Module

A direct approach is to automate the creation of a new DownValue function using Module.

SetAttributes[pFunc1, HoldAll] pFunc1[pattern_, body_, attrib_: {}] := Module[{pf}, SetAttributes[pf, attrib]; pf[pattern] := body; pf ] pFunc1[_[__, b_, c_], Binomial[b, c], HoldAllComplete][9 + 7 + 6 + 3] pFunc1[PatternSequence[_[__, b_, c_], x_], Binomial[b, c]/x, HoldAllComplete][9 + 7 + 6 + 3, 4] 
20 
5 

ReplaceAll

The first method creates a new symbol pf$xxx for each use which could be seen as undesirable. A method that does not is to imply embed a ReplaceAll operation in the body of Function like this:

SetAttributes[pFunc2, HoldAll] pFunc2[pattern_, body_, attrib_: {}] := Function[ Null, Unevaluated@{##} /. pattern :> body, attrib ] 

This method returns an actual Function expression rather than a pf$xxx symbol.
It also allows mixing Slot (#) and pattern references in body should that be desired.

It however does not return a unevaluated function expression when the arguments do not match the pattern. (Though one could add a {__} :> $Failed type of rule to /., if that is all that is desired.)

Mr.Wizard
  • 275.2k
  • 34
  • 606
  • 1.5k