7

Is it possible to define a class of indefinitely many functions f1, f2, f3, ... such that f1[x] becomes x + 1, f2[x] becomes x + 2, f3[x] becomes x + 3 and so on.

I want f25[100] to produce 125, and f255555555[333] to produce 255555888.

I am aware of the following: If I define

f[n_][x_] := n + x 

then f[1][x] becomes x + 1, f[2][x] becomes x + 2 and so on. But, f[1] is longer and looks messier than f1.

I want my functions names to be f1, f2, f3, ... not f[1], f[2], f[3] ....

Karsten7
  • 27,448
  • 5
  • 73
  • 134
imida k
  • 4,285
  • 9
  • 17
  • 11
    "But, f[1] is longer and looks messier than f1." — This is absolutely a terrible justification for doing this and I really hope beginners reading this don't get into such a habit. Not worth wasting time to save 2 characters, IMO. – rm -rf Oct 02 '15 at 04:28
  • 3
    Are you interested only in integers or also in Rationals, Reals and Complexes?. A symbolic extension would be also a nice touch. Something like fail[x] becoming x + ail – Dr. belisarius Oct 02 '15 at 04:30
  • 3
    You have demonstrated that you know the correct method for doing what you are interested in doing. Leave it at that and move on. – m_goldberg Oct 02 '15 at 04:44
  • 3
    Use Format[f[n_][x_]] := Subscript[f, n][x]; to "prettify" the display. – Bob Hanlon Oct 02 '15 at 05:52
  • 2
    @TheToad I agree, it's bad for most intents and purposes, but personally I'd also sometimes like to do something similar. The problem with f[1] over f1 is that f1 is a symbol, while f[1] is a DownValue of the symbol f. One can do f1[[3]]=c but not f[1][[3]]=c. +1 to the Q, I've learned about $NewSymbol today thanks to it. – LLlAMnYP Oct 02 '15 at 06:31
  • 1
    Me be relavant http://mathematica.stackexchange.com/q/94294/10397 – rhermans Oct 02 '15 at 07:21

5 Answers5

16

Agree with other answers, this is a bad idea (why, precisely do you want to do this?), but in the spirit of encouraging unmaintainable write-once read-never code, here's my entry into the freak show:

$NewSymbol = If[StringMatchQ[#, "f" ~~ NumberString], 
                ToExpression[# <> "[x_]=x+" <> StringDrop[#, 1]]] &;

Remove["f*"];

f123[10] + f15[2]

(* 150 *)

All sorts of agathokakological connotations and incantations within.

In the words of the G-Man, "Prepare for unforeseen consequences" with any of the answers....

ciao
  • 25,774
  • 2
  • 58
  • 139
12

Just to be clear, I think this is a terrible idea but nevertheless, a question has been posed for which there is a simple answer:

ClearAll@fn
SetAttributes[fn, HoldAll]
fn[h_[x_]] /; StringMatchQ[SymbolName@h, "f" ~~ DigitCharacter ..] := 
     First@StringCases[SymbolName@h, 
                       "f" ~~ d : DigitCharacter .. :> x + ToExpression@d]
fn[x___] := x

$Pre = fn

Now f1234[5678] will behave as you wanted.

Extending this to handle cases when f1234 already has an existing definition or replacing f1234[x] anywhere within an expression is left as an exercise.

rm -rf
  • 88,781
  • 21
  • 293
  • 472
6

In the interest of illustrating why what you've requested might be a bad idea, here's the simplest way I can think of to achieve your goal (there may be a better way):

Do[(ToExpression["f" <> ToString[#]][x_] := x + #) &@ic, {ic, 1, 5}]
?f1
?f5

output

It's much messier than the two characters you'd like to save and harder to index programatically, so I'd stick to f[n][x].

IPoiler
  • 1,230
  • 9
  • 15
3

You can get the desired look using the Notation Package.

<< Notation`

Notation[ParsedBoxWrapper[RowBox[{"f", " ", RowBox[{"n_", "[", "x_", "]"}]}]] 
  \[DoubleLongRightArrow] 
  ParsedBoxWrapper[RowBox[{RowBox[{"f", "[", "n_", "]"}], "[", "x_", "]"}]]]

which is displayed as

fnx

when the Notation Palette is used to create the second part of the above code and \[InvisibleSpace] (or EscisEsc) is used between f and n_.

With

f[n_][x_] := x + n

now

f 25[100]

or

f\[InvisibleSpace]25[100]

will both result in
125
while the last input is displayed as

f25[100]

Karsten7
  • 27,448
  • 5
  • 73
  • 134
2

As others have said, this is a bad idea. However, if you only care about the appearance of f, then you could so something like this:

f // ClearAll;

intF = RowBox[ { RowBox[ { "f", "[", #1, "]" } ], "[", #2, "]" } ] &;
dspF = RowBox[ { "f", #1, "[", #2, "]" } ] &;

f /: MakeBoxes[ f[ n_ ][ x_ ], form_ ] :=
  With[ { ns = ToString @ n, xs = ToString @ x, if = intF, df = dspF },
      TemplateBox[ { ns, xs }, "f",
          InterpretationFunction :> if,
          DisplayFunction :> df
      ]
  ];

All this really does is change the appearance of f[n][x]. So now you get results that look like this:

enter image description here

However, it could get tedious to copy and paste the boxed version whenever you want your input to be displayed this way. As an alternative (which I think looks nicer too), you can use SubscriptBox instead:

f // ClearAll;

intF = RowBox[ { "f", "[", #1, "]" } ] &;
dspF = SubscriptBox[ "f", #1 ] &;

f /: Subscript[ f, n_ ] := f @ n;

f /: MakeBoxes[ f[ n_ ], form_ ] :=
  With[ { ns = ToString @ n, if = intF, df = dspF },
      TemplateBox[ { ns }, "f",
          InterpretationFunction :> if,
          DisplayFunction :> df
      ]
  ];

enter image description here

rhennigan
  • 1,783
  • 10
  • 19