You can write a pure function whose application to an argument not matching the pattern you specified is returned unevaluated, using a trick with Defer
and #0
:
(If[MatchQ[_Integer][#1], #1 (#1 - 1), Evaluate[Defer][#0][#1]] &)[5]
(* 20 *)
(If[MatchQ[_Integer][#1], #1 (#1 - 1), Evaluate[Defer][#0][#1]] &)[x]
(* (If[MatchQ[_Integer][#1], #1 (#1 - 1), Evaluate[Defer][#0][#1]] &)[x] *)
(If[MatchQ[_Integer][#1], #1 (#1 - 1), Evaluate[Defer][#0][#1]] &)[1.5 + 2.7]
(* (If[MatchQ[_Integer][#1], #1 (#1 - 1), Evaluate[Defer][#0][#1]] &)[4.2] *)
FullForm[%]
(* Defer[Function[If[MatchQ[Blank[Integer]][Slot[1]],
Times[Slot[1], Plus[Slot[1], -1]],
Evaluate[Defer][Slot[0][Slot[1]]]]][0.1`]] *)
As you can see, there is a head Defer
(invisible in the standard form) that is automatically stripped if you edit or copy the output and use it as a new input. If you edit the argument to be an integer (as required by the pattern) and evaluate the expression, it will evaluate to an integer, otherwise it will return unevaluated again.
Alternatively, you can construct a pure function that explicitly wraps its application into Hold
if it is to stay unevaluated. Or you can use HoldForm
that has the same effect as Hold
, but it is not displayed in the standard form (although, unlike Defer
, it is not stripped automatically if the output is edited or copied). Both Hold
and HoldForm
can be explicitly unwrapped using ReleaseHold
:
(If[MatchQ[_Integer][#1], #1 (#1 - 1), Hold[#0[#1]]] &)[x]
(* Hold[(If[MatchQ[_Integer][#1], #1 (#1 - 1), Hold[#0[#1]]] &)[x]] *)
ReleaseHold[%]
(* evaluates to the same held result again *)
ReleaseHold[% /. x -> 5] (* substitute 5 as an argument before releasing hold *)
(* 20 *)
Or, you can use Inactivate
instead, whose effect can be reversed by Activate
:
(If[MatchQ[_Integer][#1], #1 (#1 - 1), Inactivate[#0][#1]] &)[x]
(* The result is displayed in the standard form as
(If[MatchQ[_Integer][#1], #1 × (#1 + -1), Inactivate[#0][#1]] &)[x]
with inactive symbols tan-colored, which is actually
Inactive[Function][
Inactive[If][Inactive[MatchQ][_Integer][#1],
Inactive[Times][#1, Inactive[Plus][#1, -1]],
Inactive[Inactivate][#0][#1]]][x] *)
Activate[%]
(* evaluates to the same inactive result *)
Activate[% /. x -> 5] (* substitute 5 as an argument before activating *)
(* 20 *)