between and among: worth Phobosization?

Andrei Alexandrescu SeeWebsiteForEmail at erdani.org
Mon Dec 16 14:10:52 PST 2013


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



More information about the Digitalmars-d mailing list