7
$\begingroup$

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

$\endgroup$
  • 11
    $\begingroup$ "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. $\endgroup$ – rm -rf Oct 2 '15 at 4:28
  • 3
    $\begingroup$ 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 $\endgroup$ – Dr. belisarius Oct 2 '15 at 4:30
  • 3
    $\begingroup$ You have demonstrated that you know the correct method for doing what you are interested in doing. Leave it at that and move on. $\endgroup$ – m_goldberg Oct 2 '15 at 4:44
  • 3
    $\begingroup$ Use Format[f[n_][x_]] := Subscript[f, n][x]; to "prettify" the display. $\endgroup$ – Bob Hanlon Oct 2 '15 at 5:52
  • 2
    $\begingroup$ @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. $\endgroup$ – LLlAMnYP Oct 2 '15 at 6:31
16
$\begingroup$

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....

$\endgroup$
  • 4
    $\begingroup$ +1 for showing us $NewSymbol $\endgroup$ – LLlAMnYP Oct 2 '15 at 6:31
  • $\begingroup$ +1 for showing us "agathokakological" :^) $\endgroup$ – Mr.Wizard Jul 20 '16 at 22:00
12
$\begingroup$

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.

$\endgroup$
6
$\begingroup$

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

$\endgroup$
3
$\begingroup$

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]

$\endgroup$
2
$\begingroup$

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

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.