7
$\begingroup$

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"

$\endgroup$
4
  • 1
    $\begingroup$ I'm sorry, what is the question? About the note: ToString@Row[{##}, " "] & @@ RGBColor[1, 0, 0] $\endgroup$
    – Kuba
    Commented Jun 26, 2014 at 10:24
  • $\begingroup$ @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. $\endgroup$
    – joojaa
    Commented Jun 26, 2014 at 10:35
  • $\begingroup$ Ok, and there should be a template and the list, no function between? $\endgroup$
    – Kuba
    Commented Jun 26, 2014 at 10:42
  • $\begingroup$ @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. $\endgroup$
    – joojaa
    Commented Jun 26, 2014 at 10:44

3 Answers 3

7
$\begingroup$

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

$\endgroup$
10
  • 1
    $\begingroup$ Excellent, that's much better. Now all i need to do is understand whats going on but that's what the manual is for :) $\endgroup$
    – joojaa
    Commented Jun 26, 2014 at 10:55
  • $\begingroup$ @joojaa I'm glad it helps. Feel free to ask if you face any problems. $\endgroup$
    – Kuba
    Commented Jun 26, 2014 at 10:56
  • 1
    $\begingroup$ @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. $\endgroup$ Commented Jun 26, 2014 at 19:38
  • 2
    $\begingroup$ @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). $\endgroup$
    – Szabolcs
    Commented Jun 28, 2014 at 2:27
  • 2
    $\begingroup$ Note to people trying the above unpacking demonstration: Identity is auto-removed by Composition, so it is necessary to use #& in this example. $\endgroup$
    – Szabolcs
    Commented Jun 28, 2014 at 2:30
3
$\begingroup$
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}}]
$\endgroup$
1
  • $\begingroup$ 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. $\endgroup$
    – joojaa
    Commented Jun 26, 2014 at 11:31
3
$\begingroup$

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." *)
$\endgroup$
1
  • $\begingroup$ Yeah, thats good since at the moment it is a bit painfull to do these. $\endgroup$
    – joojaa
    Commented Jun 26, 2014 at 14:07

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.