String Interpolation

Arafel er.krali at gmail.com
Fri Oct 27 14:16:01 UTC 2023


On 27/10/23 14:49, jmh530 wrote:
> I tried to think of when I just want a string after doing interpolation 
> (as opposed to writing immediately somehow) and struggled a bit.

I, on the other hand, do it constantly, especially when dealing with 
external libraries / systems.

Here is the first short and almost self-contained real-world example 
that I found having a quick look at my code. Just see how I construct 
and use `mailOrder` and `input`:

```d

/* This is another function in my small utility library.
  * Spawns a process, eventually remotely, with the given command line 
and standard input, returning a tuple with the status code, the captured 
stdout and the captured stderr.
  */
auto pipeProcess(string command, string stdin, string host = null, 
string remoteLauncher = "ssh");

bool sendEmail(string toAddr, string fromAddr, string fromName, string 
subject, string body, bool dryRun = false) {
     string mailOrder = "sendmail -f" ~ fromAddr ~ " -F\"" ~ fromName ~ 
"\" " ~ toAddr;
     string input = "To: " ~ toAddr ~ "\nSubject: " ~ subject ~ "\n" ~ body;

     try {
         if (!dryRun) {
             auto mailExec = pipeProcess(mailOrder, input);
             if (mailExec.status != 0) {
                 error("Error sending mail order: ", 
mailOrder,"\nstdin\n-----\n", input,
                         "stdout\n------\n", mailExec.output,
                         "\nstderr\n------\n", mailExec.error);
                 return false;
             }
         } else {
             warning("DRY RUN: not sending message:", mailOrder,"\n", 
input);
         }
     } catch (Exception e) {
         error(e);
         return false;
     }
     return true;
}
```

It would be fun, because `error` and `warning` would take interpolated 
strings directly, but I would need to add `.text` to construct 
`mailOrder` and `input`. Not confusing at all.

And please let's not start into why I call sendmail, why I don't use an 
existing mail library, or why I don't implement a SMTP client myself. 
Any of these solutions could probably be made to work, but would take 
longer and wouldn't be as simple, flexible, and adapted to **my** needs 
as this. Also, this already exists and works.

I also don't care about the glaring command injection possibility here, 
because this code has no user interaction whatsoever with all the inputs 
controlled by me. Also, how exactly would making me add `.text` prevent 
the injection?

Now you will tell me, I could rewrite pipeProcess to accept interpolated 
strings **as well**. But even if I only consider the first two 
parameters that I'm using in this example, I'd need four overloads: one 
taking both strings, one taking both interpolated strings, and one for 
each of the parameters as interpolated string. Less than optimal.

Well, or do some template parameter wizardry which I'm not exactly keen 
on. How would that work with default parameters, by the way?

Heck, anyway, what about the last two parameters? Who knows if I will 
ever want to do:

```d
remoteLauncher = "ssh -l " ~ userName ~ " -i " ~ identityFile;
```

Should my `pipeProcess` also accept interpolated strings there? How many 
overloads do I need now?


More information about the Digitalmars-d mailing list