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?
|