Question

I have the following problem.

In the input consol I can input a string, and the system will take action based on such.

So if I input add_2_with_2, it will give me a 4, if I input sqrt_4 it will give me 2, etc. Generally, you will do this with a switch / case command, but the problem is, then I need a condition for each case. So if i want to ADITTIONALLY input cube_2, then I have to write a case for this.

However, I would like to do the same without having to explicitly write a case each time I insert a new command. So forexample, if in input "FUNCTION_1", then the program should look in a specific place, in a specific forlder / file, find out if the function is defined, and execute it. If not defined in the file / folder, then it should throw AN EXCEPTION. If I additionally want to input "FUNCTION_2", then i will define the function in the same file or folder (whatever is possible with D) and then let the original program to automatically search and execute.

Can this be done in D?

(sorry for stupid question and bad English)

Was it helpful?

Solution

Yes, you can, there's a few ways you can do it.

1) You can call functions from inside the one program, and automatically find/map them using compile time reflection.

I did this in my terminal emulator's utility program. See the source to see how I did it: https://github.com/adamdruppe/terminal-emulator/blob/master/utility.d

To use it for your own purpose, you can remove the version() statements, change the module name, and write your own functions.

2) You can also look for a script in a directory and run them that way. Use std.process and std.file to find a file and run it.

OTHER TIPS

As it happens, I just did something like this:

https://github.com/schancel/gameserver/blob/master/source/client/messaging.d

Code isn't the prettiest, but it uses reflections to insert the extra case statements.

What I believe you are looking for is generally called in the literature as the Command Pattern. In heavily OO languages this pattern typically involves creating bunch of classes that implement a common, simple Command interface which has a single execute() method. In D however, you have delegates and can probably avoid generating potentially hundred small classes for this purpose.

Here is one of the possible D alternatives, using lambda expressions ( http://dlang.org/expression.html#Lambda ):

module command2;

import std.stdio;
import std.conv;
import std.array;

// 2 = binary operation
alias int delegate(int arg1, int arg2) Command2; 

// Global AA to hold all commands
Command2[string] commands;

// WARNING: assumes perfect string as input!!
void execute(string arg) {
    auto pieces = split(arg);
    int first = to!int(pieces[1]);
    int second = to!int(pieces[2]);
    Command2 cmd = commands[pieces[0]];

    int result = cmd(first, second); // notice we do not need a big switch here
    writeln(arg, " --> ", result);
} // execute() function

void main(string[] args) {
    commands["add"] = (int a, int b) => a + b;
    commands["sub"] = (int a, int b) => a - b;
    commands["sqrt"] = (int a, int b) => a * a; // second parameter ignored
    // ... add more commands (or better call them operations) here...

    execute("add 2 2");
    execute("sqrt 4 0"); // had to have 0 here because execute assumes perfect imput
} // main() function

Here is the source code to fork and play with: http://dpaste.dzfl.pl/41d72036

I will write the OO version when I find more time...

Regarding the execution of a script/application in some directory... It is merely a matter of writing a function which takes parameters, and calls the std.process.execute(). A very quick example how to extend the code above:

// WARNING: no error checking, etc!
int factoriel(int arg, int ignored) {
    auto p = std.process.execute(["./funcs/factoriel", to!string(arg)]);
    return to!int(p.output);
} // factoriel() function

...
// in main()
commands["fact"] = toDelegate(&factoriel);
...
execute("fact 6 0"); // again, we add 0 because we do not know how to do unary operations, yet. :)
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top