1
$\begingroup$

Is there a way to make the general replacement

foo[x,y,z]->fooxyz

so that I can treat the x_i as variables so that I will obtain foofgh from the following:

foo[f,g,h] /.{ foo[x,y,z]->fooxyz }

?

$\endgroup$
3
  • 1
    $\begingroup$ It isn't terribly difficult to accomplish this. But, rather than giving you the answer right away, let me just encourage you to think carefully about what you are really trying to accomplish here and whether forming symbols this way is actually a good idea. If you're certain you still want to do it, here's a hint: look up Symbol, ToString, and StringJoin. $\endgroup$ Jun 7, 2013 at 21:39
  • $\begingroup$ @OleksandrR - I am positive I want to do it! I did realize that that I can take ToString[x y z] and get xyz, which then I do ToExpression[%] and get a variable xyz (which is what I want). My problem is extracting the foo, x, y, and z from my original function...Thanks for the help so far. $\endgroup$
    – DJBunk
    Jun 7, 2013 at 21:44
  • $\begingroup$ For example ToString[{foo,x,y,z}] doesn't give me what I would expect, namely it is not that same thing as {ToString[foo],ToString[x],ToString[b],ToString[c]}. $\endgroup$
    – DJBunk
    Jun 7, 2013 at 21:49

3 Answers 3

7
$\begingroup$

As I alluded to in my comment, this would in many cases be a bad idea: I'm fully in agreement with @Rojo when he warns not to make a mess of your data representation just because of how you want it to display. That said, perhaps there are legitimate reasons for doing this in some situations. You can accomplish it as follows:

foo[f, g, h] /. h_[args__] :> ToString[Row[{h, args}], StandardForm]
(* "foofgh" *)

It even works if you enter e.g. f^2 as an argument.

If you want a symbol rather than a string as the result, you have to be more careful about what can appear as a head or an argument. The following should perform adequately:

foo[f, g, h] /. h_Symbol[args__Symbol] :> Symbol[StringJoin @@ SymbolName /@ {h, args}]
(* foofgh *)

Aside: try the first of these examples, and then type any character either inside or after the resulting string. The resulting box expression is not properly formed and an internal self-test error (MathEditCells2|c|1384) appears in the messages window. This seems to be a bug in the front end, and it's been there since at least version 7.

$\endgroup$
0
1
$\begingroup$

Just for future users I will post my own workaround I just found (with everyones help!)

fabc := foo

f[a, b, c] /. {f[X_, Y_, Z_] -> {f, X, Y, Z}};
v = %;
{ToString[v[[1]]], ToString[v[[2]]], ToString[v[[3]]], ToString[v[[4]]]};
StringJoin[%];
ToExpression[%] 

output:= foo
$\endgroup$
1
$\begingroup$

Here we make a pattern to match all characters, except digits, for which Symbol[char] complains.

invalidCharacters = Alternatives @@ 
   Select[CharacterRange[FromCharacterCode[0], FromCharacterCode[2^16 - 1]],
     ! DigitQ[#] && Quiet@Check[Symbol[#]; False, True] &];

Presumably the function name will not start with a digit, since it cannot, so we won't worry about checking:

Symbol @ StringReplace[foo[f, g, h] // ToString, invalid -> ""]
Symbol @ StringReplace[f4d[2 + \[Angle]A, $b, 3.3] // ToString, invalidCharacters -> ""]
foofgh
f4d2\[Angle]A$b33

Caveat: This doesn't take care of all problems, but it should work for the usual sorts of things. For instance, inspecting the output of Symbol["x" <> FromCharacterCode[25]] reveals RowBox[{"x", "\.19"}]], which is interpreted as Times[\.19, x]. But Symbol[FromCharacterCode[25] <> "x"] creates a single symbol with the name "\.19x". I cannot imagine anyone wanting to use "\.19", which is nonprinting, except to make sure no one could ever figure out what the code was doing, including oneself. :)

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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