In the final recipe of the previous chapter on reflection, we built a command-line function caller that did a linear search through all the available functions to find the right one for the command. Here, we'll revisit that concept and generate more efficient code.
Let's execute the following steps to build a lookup table:
switch
statement.__traits
, you can write the case
statements inside the foreach
loop.mixin
expression to add it to your switch
statement.switch
statement.All the preceding steps are mentioned in the following code:
void callFunction(string functionName) { s: switch(functionName) { default: assert(0); // can add defaults or cases outside the loop foreach(methodName; __traits(allMembers, mixin(__MODULE__))) { case methodName: // implement the call break s; // break the switch specifically to clarify intent inside loop } } }
If you want a custom hash function, you can use CTFE by calling regular hash functions in the case
statements: int hash(string s) { … } switch(hash(s)) { case hash("foo"): /* … */ break; case hash("bar"): /* … */ }
. Ensure that your hash is well-distributed, because switch
will not handle collisions automatically.
When a switch
statement is compiled, all possible case values are known to the compiler, allowing it to generate more efficient code than a plain list. All the possible string cases are sorted by length and by content at compile time. This list is sent to a runtime function which performs a binary search to find the case that handles a given input value.
We can often take advantage of these optimizations by creating a switch
statement and populating the cases with compile-time foreach
loops. The code is pretty straightforward.
Another strategy to make lookup tables is with compile-time function evaluation. CTFE is often used with enums, but it also works with static immutable arrays to create data tables. To do this, write a function that calculates the data and returns a table. Then, use that function to initialize the table. It is important that you mark the table static immutable
to ensure it is only initialized once, at compile time, and can be shared across all threads implicitly.
18.188.190.175