Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

I am pretty new to string processing in Mathematica. But I'm having some problems in doing simple string template filling to my mind elegantly. For example when doing export for my answer here, one of my solutions so far is using:

cat = StringJoin @@ (ToString /@ {##}) &;
strvec = cat[#[[1]], " ", #[[2]], " ", #[[3]]] &;
StringJoin[Map[cat["AttributeBegin
        Translate ", strvec[#[[3]]], "
        Color ", strvec[#[[2]]], "
        Surface \"constant\"
        Sphere 0.1 -0.1  0.1 360.0
        Attribute \"light\" \"shadows\" \"on\"
        LightSource \"pointlight\" \"l", #[[1]], "\"
        \"intensity\" 1
        \"lightcolor\" [", strvec[#[[2]]], "]
    AttributeEnd
    Illuminate \"l", #[[1]], "\" 1

    "] &, {{1, Blue, {0, 0, -1}}, {1, Red, {3, 1.5, 1}}}]]

But what I would really like to do is have a separate the template string from the code so its easy to change without touching the rest of the code. Ideally id want something like this:

lightTemplate = "AttributeBegin
    Translate $trans$
    Color $color$
    Surface \"constant\"
    Sphere 0.1 -0.1  0.1 360.0
    Attribute \"light\" \"shadows\" \"on\"
    LightSource \"pointlight\" \"l$num$\"
    \"intensity\" 1
    \"lightcolor\" [ $color$ ]
 AttributeEnd
 Illuminate \"$num$\"
 "

Then somehow map my database to fill in values to $num$, $color$ etc... Like i would do in mostly any other high level language (python uses % or {} instead of $ but the idea is the same). I tried using StringFormat but that didn't work too well.

In a related note is there a nice way to turn something like:

RGBColor[1, 0, 0] 

to

"1 0 0"

share|improve this question
1  
I'm sorry, what is the question? About the note: ToString@Row[{##}, " "] & @@ RGBColor[1, 0, 0] –  Kuba Jun 26 at 10:24
    
@Kuba I updated the question a bit. What i want is a template thats strings because im going to write it on disk and pass to others but i would like to separate the templates form code so that they can be easily managed manually. Nearly all other languages that i work with have some kind of string templating mechanisms. –  joojaa Jun 26 at 10:35
    
Ok, and there should be a template and the list, no function between? –  Kuba Jun 26 at 10:42
    
@Kuba I dont really care if theres a function i just want to hide the copmplexity to variable so that its easier to change your mind later. Im just not really sure how to proceed form here. –  joojaa Jun 26 at 10:44

3 Answers 3

up vote 6 down vote accepted

Maybe:

lightTemplate = "AttributeBegin
      Translate `5` `6` `7`
      Color `2` `3` `4`
      Surface \"constant\"
      Sphere 0.1 -0.1  0.1 360.0
      Attribute \"light\" \"shadows\" \"on\"
      LightSource \"pointlight\" \"l$num$\"
      \"intensity\" 1
      \"lightcolor\" [ `2` `3` `4` ]
   AttributeEnd
   Illuminate \"`1`\"
   ";

conv = Composition[
  StringJoin,
  ToString[#, StandardForm] & /@ # &,
  StringForm[lightTemplate, ##] & @@@ # &,
  Map[Style[#, NumberMarks -> False] &, #, {2}] &,
  Flatten[List @@@ #] & /@ # &
  ];

conv[{{1, Blue, {0, 0, -1}}, {1, Red, {3, 1.5, 1}}}]

enter image description here

share|improve this answer
1  
Excellent, that's much better. Now all i need to do is understand whats going on but that's what the manual is for :) –  joojaa Jun 26 at 10:55
    
@joojaa I'm glad it helps. Feel free to ask if you face any problems. –  Kuba Jun 26 at 10:56
1  
@Kuba I agree. I don't consider this style the most powerful (in the sense that it does not really allow to introduce qualitatively more powerful abstractions), but it can be applied to the majority of tasks where Mathematica shines, and it is still considerably more expressive that the "usual" one where component functions are not singled out explicitly. –  Leonid Shifrin Jun 26 at 19:38
2  
@Leonid One general problem with Composition used to be that it unpacks packed arrays. r = RandomReal[1, 10000]; Composition[Developer`PackedArrayQ, # &][r] I see that this doesn't unpack now in the cloud, which is great news! The unpacking problem was the reason why I made a mental note never to use Composition (after having been bitten a few times). –  Szabolcs Jun 28 at 2:27
1  
Note to people trying the above unpacking demonstration: Identity is auto-removed by Composition, so it is necessary to use #& in this example. –  Szabolcs Jun 28 at 2:30
f[{a_, b_, c_}] :=
 "AttributeBegin
        Translate " <> #3 <> "
        Color " <> #2 <> "
        Surface \"constant\"
        Sphere 0.1 -0.1  0.1 360.0
        Attribute \"light\" \"shadows\" \"on\"
        LightSource \"pointlight\" \"l" <> #1 <> "\"
        \"intensity\" 1
        \"lightcolor\" [ " <> #2 <> " ]
     AttributeEnd
     Illuminate \"l" <> #1 <> "\"" & @@ {ToString@a, strvec[b], strvec[c]}
f[{1, Blue, {0, 0, -1}}]
f[{1, Red, {3, 1.5, 1}}]
share|improve this answer
    
Yes its better than mine. But despite the cryptic nature, cubas idea has the nice feature that the string is totally separate form the actualizing code, and its just one string. This means its much more trivial to change by any other end user and code shared between different templates. I need to meditate on the answers a bit before deciding. –  joojaa Jun 26 at 11:31

In version 10 (available now through the programming cloud) you can use StringTemplate.

StringTemplate allows using named placeholders, classical numbered placeholders, or even embedding code that uses placeholders. See the documentation for many advanced usage examples.

Basic usage demonstrating both named and numbered templates:

template = StringTemplate["`name` is `2` years old."];

template["name" -> "Annie", 19]
(* "Annie is 19 years old." *)
share|improve this answer
    
Yeah, thats good since at the moment it is a bit painfull to do these. –  joojaa Jun 26 at 14:07

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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