2

I want a toString method that replaces each occurrence of f[x_].

obj1ToString[x_] := StringRiffle[x, ""];
obj2ToString[y_] := ToString[y /. f[x_] :> "(" <> obj1ToString@x <> ")"];

obj2ToString[g@f[{1, 2, 3}]] (* "g[(123)]" ) obj2ToString[f[{1, 2, 3}] &] ( "(<>obj1ToString[{1, 2, 3}]<>) & " *)

As you can see, it doesn't work in all contexts. How do I fix this?

J. M.'s missing motivation
  • 124,525
  • 11
  • 401
  • 574
H.v.M.
  • 1,093
  • 5
  • 12

1 Answers1

2

Edit

As @CarlWoll points out, the original solution is unstable - easily breaking for some arguments of f. The better solution is to do something like

toString[y_]:= ToString[y /. f[x_]:> With[{eval="("<>StringRiffle[x,""]
     <> ")"},eval /; True]];

which is based on this thread here: Replacement inside held expression

Original

Just turn your whole expression into a string then do your replacement.

toString[y_] := StringReplace[ToString[y],"f[" ~~ Shortest[x__] ~~ "]" :> 
    "(" <> StringRiffle[ToExpression@x, ""] <> ")"];
bRost03
  • 2,072
  • 8
  • 14
  • 2
    In general, I recommend avoiding approaches that convert to strings and then use string manipulation functions. In particular, using single argument ToString is very bad, consider toString[f[{1/2}]]. Your replacement also has issue, e.g., toString[f[{g[x]}]. Finally, approaches using ToExpression can be scary if the function can be applied to arbitrary content. – Carl Woll Jun 30 '21 at 20:16
  • @CarlWoll, all fair points. Given the OP's definition of obj1ToString using StringRiffle it is clear they expect the argument of f to always be a List of symbols. Given what's written, it's unclear what behavior they even want from something like toString[f[{g[x]}] (although it's safe to assume $Failed isn't it). I suppose I should have waited for their clarification before shooting off this ugly hack of an answer. I agree it's dangerous as written. When OP clarifies what they're looking for I'll improve the answer. – bRost03 Jun 30 '21 at 20:33