## How to use pattern matching to assign values to Subscript[f,x_]?

11

4

I want to define two subscripted functions Subscript[f,1] and Subscript[f,2]. To keep the assignments local, I would like to associate the definitions with f if possible. My current solution is to write the following.

f/:Subscript[f,1]:=Function[x,g[x]]
f/:Subscript[f,2]:=Function[x,h[x]]


The resulting definition is stored as an UpValue for f, which is acceptable for me. Is it possible to construct a similar definition using pattern matching? I am looking for an analog to the following pair of definitions.

f[x_]:=g[x] (*definition 1*)
f:=Function[x,g[x]] (*definition 2*)


In other words, I am currently using a definition akin to definition 2 above for my subscripted functions. Is it possible to write a definition analogous to definition 1 above?

Do you mean f /: Subscript[f[x_], 1] := g[x] ? Seems quite straight forward, so if that's your question you almost answered it yourself. – jVincent – 2012-08-16T20:03:56.030

2@jVincent, he doesn't mean that. He wants it for Subscript[f,1][x_] which would be too deep for an UpValue – Rojo – 2012-08-16T20:11:39.143

I don't know a neat solution to these things, but workarounds are possible. Check out if symbolising the subscript is good for you – Rojo – 2012-08-16T20:14:44.367

Rojo is correct; thank you for clarifying my intentions. – Carl Morris – 2012-08-29T14:49:54.480

6

You can do this with the Notation Package and its Symbolize function:

The definition is not attached to Subscript, but to pseudo-Symbol f1:

+1 I still think symbolising is the best workaround, if you don't need the underscript to be a pattern – Rojo – 2012-08-17T12:03:02.133

@Rojo I voted for yours too. (And jVincent's, if anyone's curious.) – Mr.Wizard – 2012-08-17T12:06:37.383

@Mr.Wizard 500 th answer ! Seems like you've got enough ideas to write a new (and necessarily concise) Mathematica book. +1 – Artes – 2012-08-17T12:07:58.707

@Artes Thanks! I hadn't noticed. I'm no writer; I still haven't made a blog post yet. – Mr.Wizard – 2012-08-17T12:11:59.560

This is probably the best answer for the situations that I can foresee. I admit that the workarounds using wrappers are quite enlightening (hence a +1 for each), but the situations that I would use this subscript notation are mostly in the context of small examples where it seems Symbolize offers the cleanest solution. – Carl Morris – 2012-08-29T14:48:33.063

10

As Rojo notes, defining f/: Subscript[f,1][x_] doesn't work as f is too deep in the expression, however you could define your function in two steps to avoid tying the definition to Subscript.

f /: Subscript[f, n_] := subs[f, n]
subs /: subs[f, n_][x_] := g[x]


This has the problem that Subscript[f,1] for instance will turn up in output as subs[f,1] rather then be nicely formated. You can however simply define that it should be formated like subscript and noone will be the wiser that it's actually a different wrapper:

MakeBoxes[subs[a_, n_], StandardForm] := MakeBoxes[Subscript[a, n], StandardForm]


1Nice patch +1. Of course the actual value of the output is subs, and it could eventually bite you. I wonder if its possible to work around that too, humm – Rojo – 2012-08-16T20:24:09.520

@Rojo I'm not sure how it would come back to bite me since Subscript is mostly just a formatting function, If you had code that acted different depending on the heads you could just define: subs /: Head[subs[__]] = Subscript in which case I think subs becomes a pretty good impostor Subscript. – jVincent – 2012-08-16T20:33:25.763

The patch you just suggested will only work for code that explicitly uses Head, which will be the minority. I mean, a reason I see for the OP to want the "pattern version" of the definition is because in a real application his definition many times won't match. This will leave you with some symbolic expression with subs inside that you see and think as Subscript and it will bite you if you ever use Cases or Replace trying to get those expressions – Rojo – 2012-08-16T20:38:07.397

An ideal solution would remain unevaluated when it doesn't match – Rojo – 2012-08-16T20:41:10.157

6

Slightly modifying @jVincent's idea so that if there's no match with your definition you go back to the Subscript

Module[{$guard = True, subs}, f /: Subscript[f, n_] /;$guard = subs[f, n];
subs[f, n_][sth_Integer] := g[sth];
subs[f, n_][sth_] := Block[{$guard = False}, Subscript[f, n][sth]] ]  Now Subscript[f, 1][2] Subscript[f, 1][2.5] // FullForm  g[2] Subscript[f,1][2.5] 0 Here is a different approach to creating a functionality similar to what Rojo does. I attach a single rule to Subscript: Subscript[x_, n_][args__] /; MatchQ[x,$subpat] :=
With[{eval = x[n][args]},
eval /; ! MatchQ[ eval, HoldPattern @ x[n][args] ]
]


Then I define functions that are controlled by this rule:

$subpat = HoldPattern[f | q]; f[1][x_] := x^2 f[2][x_] := Mod[x, 3] q[1][x_] := x + 7  We gain this behavior: $subpat controls the domain:

You can change \$subpat or the definitions for f, q`, etc. to "keep the assignments local" however you see fit.