Предпочтительный способ построения струн в 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 года.

Другие вопросы по тегам