I run into this problem a lot whenever I'm generating some text. I'll be making what amounts to a sequence of strings being appended, and do something like this:
(apply string-append (list "<p><a href=\"" somewhere "\">" something "</a></p>")) Compared to un-parsing a representation of a document tree every single time, simplifying document production down to a bunch of string concatenations is pretty efficient. The problem happens when I introduce conditionals, like this: (list "<p id=\"navigation\">" (if prev (list "<a href=\"" prev "\">Prev</a>") '()) (if next (list "<a href=\"" next "\">Next</a>") '()) "</p>") Now I no longer have a sequence of strings, but instead a nested list of strings. Then I usually call (apply string-append (flatten list-of-strings)) and don't worry about it, but it'd be even cooler if I could proactively flatten it. (if prev (if next (list "<p id=\"navigation\">" "<a href=\"" prev "\">Prev</a>" "<a href=\"" next "\">next</a>" "</p>") (list "<p id=\"navigation\">" "<a href=\"" prev "\">Prev</a>" "</p>")) (if next (list "<p id=\"navigation\">" "<a href=\"" next "\">next</a>" "</p>") (list "<p id=\"navigation\">" "</p>"))) Obviously that's horrible code, since I don't want to type the surrounding stuff for every possible logic pathway in my code. But it'd be relatively simple to concatenate whatever the result is! I guess what I'm asking is how would I take code like this: (list "<p id=\"navigation\">" (splicing-if prev (splicing-list "<a href=\"" prev "\">Prev</a>") nada) (splicing-if next (splicing-list "<a href=\"" next "\">Next</a>") nada) "</p>") ...and have the result inherently be a flat list of strings? Not a complex tree that I then have to walk with (flatten), but genuinely just a list of strings? Something with (reset) and (shift) maybe? Something with (and-let)? To make this happen, would I have to instrument the conditionals like (if)? Would I have to instrument the (list) forms that they result in? Obviously if my conditionals produce simple strings it's easy: (list "things: " (if thing1 thing1 "") (if (and thing1 thing2) " and " "") (if thing2 thing2 "")) Even that is kind of cludgy though, because the "" fallthrough results in lists like (list "things: " thing1 "" "") instead of the ideal: (list "things: " thing1) One possible solution is to use mutable variables and shared state. (ugh) (write "<p id=\"navigation\">") (when prev (write "<a href=\"") (write prev) (write "\">Prev</a>")) (when next (write "<a href=\"") (write next) (write "\">Next</a>")) (write "</p>") Another thing I've tried is concatenations of concatenations: (apply string-append "<p id=\"navigation\">" (if prev (string-append "<a href=\"" prev "\">Prev</a>") "") (if next (string-append "<a href=\"" next "\">Next</a>") "") "</p>") That of course scatters fallthrough "" strings in the calculation, and since it calls string-append multiple times, the implementation can't exactly allocate the result all at once, and must spend more time fooling around with memory. Creating strings, only to destroy them as soon as they've been appended to the larger string. But there's no way I've ever been able to figure to produce generated text that is just a flat list of strings, if I ever want to have conditional decisions about what to go in that list. -- You received this message because you are subscribed to the Google Groups "Racket Users" group. To unsubscribe from this group and stop receiving emails from it, send an email to racket-users+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.