Предпочтительный способ построения струн в D
Каков предпочтительный способ построения строк относительно атрибутов функции @safe
, pure
а также nothrow
а во время компиляции и во время выполнения функции родительских функций?
Должны ли мы использовать, например,
format("Variable x=%s should equal %s", x, x_)
или же
"Variable x=" ~to!string(x)~ " should equal " ~to!string(x_)
Я считаю format
версия легче для глаз, но лучше ли она в других отношениях?
Может быть небольшое снижение производительности во время компиляции, потому что строки формата и его аргументы должны быть CTFEed правильно?
2 ответа
Первая версия, как правило, лучше. Нет существенной разницы в производительности компиляции (если есть, forrmat не ctfe), и format() на самом деле должна работать лучше.
Двоичный файл "foo" ~ "bar" часто удивительно дорог, потому что он выделяет промежуточные результаты, которые затем должен очистить сборщик мусора.
На версии dmd, которая у меня есть, ни одна из версий не компилируется как безопасная, а не чистая. Я думаю, что они исправили это в Phobos Git, но я не уверен. Несмотря на это, сейчас ни один из них на самом деле не работает, и нет простого обходного пути, кроме реализации собственной функции, если только она не предназначена только для отладки.
Чистое требование смягчено в операторах отладки, и вы можете обернуть небезопасные функции в @system и добавить функции в try/catch для получения этих атрибутов.
Таким образом, это будет на самом деле скомпилировать:
// trusted gets around safe
@trusted pure nothrow string myformat(T...)(in string fmt, in T t) {
import std.string;
// debug gets around the pure requirement
debug try // try gets around nothrow
return format(fmt, t);
catch(Exception e) { }
return null;
}
@safe nothrow pure void main() {
import std.conv;
string s = myformat("test %s", 10);
assert(0, s); // the assert message shows up
}
скомпилировать с ключом -debug: dmd test.d -debug
Так что это не лучшее решение, но до тех пор, пока не будут освобождены функции фобоса с надлежащими атрибутами, или если вы хотите написать свои собственные функции format() или to() (на самом деле не так сложно, вы можете сделать int в строку в < 10 строк) наверное лучшее что ты можешь сделать.
Как говорит принятый ответ, предпочитают format!
и предпочитают передавать строку формата в качестве аргумента шаблона:
#!/usr/bin/env rdmd
module test;
import std.format; // or std.string, which publicly imports std.format
import std.stdio;
void main()
{
writeln(format("%s%s","run-time error 'Orphan format specifier'"));
writeln(format!"%s%s"("compile-time error 'Orphan format specifier'"));
}
Он доступен с версии DMD 2.074.0, выпущенной в апреле 2017 года.