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?

Carl Morris

Posted 2012-08-16T19:52:00.020

Reputation: 445

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

Answers

6

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

Mathematica graphics

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

Mathematica graphics

Mr.Wizard

Posted 2012-08-16T19:52:00.020

Reputation: 259 163

+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] 

jVincent

Posted 2012-08-16T19:52:00.020

Reputation: 14 423

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`]

Rojo

Posted 2012-08-16T19:52:00.020

Reputation: 40 993

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:

Mathematica graphics

$subpat controls the domain:

Mathematica graphics

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

Mr.Wizard

Posted 2012-08-16T19:52:00.020

Reputation: 259 163