質問

D String MixInsに慣れていないあなたのために、それらは基本的にコンパイル時のエバルです。コンパイル時間文字列(リテラルまたはテンプレートがメタプログラミングまたはコンパイルするかどうか)を取り、コードとしてコンパイルすることができます。単純な文字列リテラルを使用している場合は、基本的にコンパイラ自動コピー貼り付けです。

因子の他の方法を非常に適していない単純なコードの再利用の手段として、文字列のString Mixinsを使用するための盗難者と考えますか?一方では、基本的にはコンパイラ自動化されたリテラルコピーアンドペーストで、インスタンスで混在すると、互いに関係がないことを意味します。 String MixIn内のシンボルがスコープ内のシンボルに衝突した場合、悪いことが起こります(ただし、コンパイル時にはコンパイル時は実行時には)。たとえば、範囲内の変数が特定の規則に従って名前が付けられた場合に限られている場合に限り、機能の途中に文字列を混合することができるという点で比較的非構造化されています。ミックスインはまた、外側のスコープがフィットするにつれて使用できる変数を宣言することもできます。

のコピーアンドペーストはコンパイラであるため、ソースレベルでのコードのコードには単一の時点があり、変更する必要がある場合は変更する必要があります。一箇所、そしてすべてが同期しています。 String MixInsはまた、他の方法で因数を与え、そうでなければ手動でカットアンドペーストされる可能性が非常に高い可能性があるであろうコードの再利用を非常に単純化します。

正しい解決策はありません

他のヒント

あなたが提起したすべての批判は本当です。

関係なく、手動複合乳液よりも優れています。

実際には、私のツールライブラリ、文字列テーブルの展開で似たものが似たものを持っています。パストレーサの動的値実装からのコード例:

  T to(T)() {
    static if (!is(T == Scope)) {
      T value;
      if (flatType == FlatType.ScopeValue) value = sr.value().to!(T);
    }
    const string Table = `
                 | bool          | int         | string               | float   | Scope
      -----------+---------------+-------------+----------------------+---------+----------
      Boolean    | b             | b           | b?q{true}p:q{false}p | ø       | ø
      Integer    | i != 0        | i           | Format(i)            | i       | ø
      String     | s == q{true}p | atoi(s)     | s                    | atof(s) | ø
      Float      | ø             | cast(int) f | Format(f)            | f       | ø
      ScopeRef   | !!sr          | ø           | (sr?sr.fqn:q{(null:r)}p) | ø   | sr
      ScopeValue | value         | value       | value                | value   | sr`;
    mixin(ctTableUnrollColMajor(Table,
      `static if (is(T == $COL))
        switch (flatType) {
          $BODY
          default: throw new Exception(Format("Invalid type: ", flatType));
        }
      else `,
      `case FlatType.$ROW:
        static if (q{$CELL}p == "ø")
          throw new Exception(q{Cannot convert $ROW to $COL: }p~to!(string)~q{! }p);
        else return $CELL;
      `
    ).litstring_expand() ~ `static assert(false, "Unsupported type: "~T.stringof); `);
  }
.

ストリングミックスインシンズなしであるネストされたIFSとケースステートメントをどのようなものであるかを見て、すべての醜さは下部に集中し、実際のの振る舞いが集中しています。/ EM>機能の概要は一目で読みやすいです。

While other, more elegant solutions may be better to use if you can, string mixins can be extremely useful. They allow for both code re-use and code generation. They're checked at compile time. The code that results is exactly the same as if you'de written it yourself by hand, so it's not any less safe than if you had written it yourself by hand.

The problem with string mixins is that they're harder to control than hand-written code in the sense that it's not physically laid out in your source in the same manner with line numbers clearly traceable to errors, and it may be harder to debug. For instance, take hello world with a string mixin:

import std.stdio;

void main()
{
    mixin(hello());
}

string hello()
{
    return "
    writeln(\"hello world\");
";
}

If we were to remove the semicolon after writeln(), then the error we got would be

d.d(7): found 'EOF' when expecting ';' following statement

The mixin is done on line 5. Line 7 is a blank line. So, the line number is of limited usefulness here. Now, this mixin is short enough that we could have put it on a single line and gotten it to say that the error was on the same line as the mixin, but with more complicated mixins, that obviously won't work. So, by using a string mixin, your ability to figure out where an error is is impaired. If the code is generated using CTFE, then it would become that much more difficult to figure out exactly what the code even looks like in order to figure out what's wrong with it. It's a lot like figuring out what code a C-style macro turns into, except that it could be worse because they could be generated rather than a direct replacement. However, they don't replace except where you explicitly tell them to, so they're much safer than C-style macros.

String mixins are totally safe, and there's nothing particularly wrong with them, but they do make maintenance harder in some ways. The corresponding hand-written code would be easier to debug. However, string mixins are powerful enough that they can do a lot of code generation for you and save you a lot of maintainence costs in that sense, and they allow you to re-use code, which can be a big maintanence gain as well.

So, whether using a string mixin is a good idea in a particular situation depends on that situation. I don't see anything particularly wrong with them, and I certainly wouldn't call them an anti-pattern, but there are both pros and cons to using them such that whether they're a good idea depends on what you're doing. In many cases, there are more elegant, cleaner solutions which would be better. In others, they're exactly what the doctor ordered.

Personally, I think that they're fantastic if you're looking to generate code, saving yourself the effort of having to write that code by hand, and possibly making it easier to generate correct code for a variety of situations and avoiding risking creating new bugs like you might have had you written it yourself in each of those places where you used the mixin. It also is one of the ways to just outright re-use code without having to worry about the cost of a function call or issues with the limits of single-inheritance or anything else that makes code re-use by calling functions or inheritance harder. You're simply copying and pasting the code into each place in a manner which makes it so that if you change the code, the changes will be properly pasted everywhere without you having to worry about tracking them all down like if you had hand copy and pasted.

So, use string mixins where appropriate, and it's probably best not to use them if they're not needed, but there's nothing really wrong with using them.

String mixin is like goto: it should be avoided where ever possible and should be used wherever required.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top