On 12/16/13 1:45 PM, Walter Bright wrote:
On 12/16/2013 12:38 PM, Andrei Alexandrescu wrote:
bool between(T, U1, U2)(T v, U1 lo, U2 hi)
{
     return v >= lo && v <= hi;
}

You'd need 4 such functions, < <, < <=, <= <, <= <=, and it just seems
like trivia.

The behavior is taken from SQL where it's closed both ends.

uint among(T, Us...)(T v, Us vals)
{
     foreach (i, U; Us)
     {
         if (v == vals[i]) return i + 1;
     }
     return 0;
}

This has O(n) behavior, which might be unexpected for the user.

It's O(1) because the data size is in the source text. There's no variable n.

There's quite a bit of evidence in support of among (not as much for between) in the source code of Facebook's cpplint, soon to be open sourced. Here are some relevant quotes:

bool atBuiltinType(R)(R it) {
return it.front.type_.among(tk!"double", tk!"float", tk!"int", tk!"short", tk!"unsigned", tk!"long", tk!"signed", tk!"void", tk!"bool", tk!"wchar_t",
      tk!"char") != 0;
}
...
string[] readQualifiedIdentifier(R)(ref R it) {
  string[] result;
  for (; it.front.type_.among(tk!"identifier", tk!"::"); it.popFront) {
    if (it.front.type_ == tk!"identifier") {
      result ~= it.front.value_;
    }
  }
  return result;
}
...
    if (it.front.type_.among(tk!"class", tk!"struct", tk!"union")) {
      result += callback(it, v);
    }
...
    if (it.front.type_.among(tk!"namespace", tk!"class", tk!"struct",
            tk!"union", tk!"{")) {
      auto term = it.find!(x => x.type_ == tk!"{");
      if (term.empty) {
        break;
      }
      it = skipBlock(term);
      continue;
    }
...
    if (v[i .. $].atSequence(tk!"#", tk!"if")
        || (v[i .. $].atSequence(tk!"#", tk!"identifier")
            && v[i + 1].value_.among("ifndef", "ifdef"))) {
      ++openIf;
    } else if (v[i .. $].atSequence(tk!"#", tk!"identifier")
        && v[i + 1].value_ == "endif") {
      ++i; // hop over the else
      --openIf;
    }
...
      auto term = it.find!((t) => t.type_.among(tk!":", tk!"{"));
...
static bool endsClass(CppLexer.TokenType2 tkt) {
  return tkt.among(tk!"\0", tk!"{", tk!";") != 0;
}
...
static bool isAccessSpecifier(CppLexer.TokenType2 tkt) {
  return tkt.among(tk!"private", tk!"public", tk!"protected") != 0;
}
...
      while (i.front.type_.among(tk!"*", tk!"const", tk!"volatile")) {
        i.popFront;
      }

I invite you all to contemplate redoing all these and more from first principles.


Andrei

Reply via email to