Переключатель cas Альтернатива в D
У меня следующая проблема.
В консоль ввода я могу ввести строку, и система будет действовать исходя из этого.
Так что, если я введу add_2_with_2, это даст мне 4, если я введу sqrt_4, это даст мне 2 и т. Д. Обычно, вы будете делать это с помощью команды switch / case, но проблема в том, что мне нужно условие для каждого дело. Так что, если я хочу ДОПОЛНИТЕЛЬНО ввести cube_2, то я должен написать случай для этого.
Тем не менее, я хотел бы сделать то же самое без необходимости явно писать регистр каждый раз, когда я вставляю новую команду. Так, например, если во вводе "FUNCTION_1", то программа должна искать в определенном месте, в определенном файле forlder /, определить, определена ли функция, и выполнить ее. Если он не определен в файле / папке, он должен выдать ИСКЛЮЧЕНИЕ. Если я дополнительно хочу ввести "FUNCTION_2", то я определю функцию в том же файле или папке (что возможно с помощью D), а затем разрешу исходной программе автоматический поиск и выполнение.
Можно ли это сделать в D?
(извините за глупый вопрос и плохой английский)
3 ответа
Да, вы можете, есть несколько способов сделать это.
1) Вы можете вызывать функции из одной программы и автоматически находить / отображать их, используя отражение времени компиляции.
Я сделал это в служебной программе эмулятора терминала. Посмотрите источник, чтобы увидеть, как я это сделал: https://github.com/adamdruppe/terminal-emulator/blob/master/utility.d
Чтобы использовать его в своих целях, вы можете удалить операторы version(), изменить имя модуля и написать свои собственные функции.
2) Вы также можете найти скрипт в каталоге и запустить его таким образом. Используйте std.process и std.file, чтобы найти файл и запустить его.
Как это случилось, я просто сделал что-то вроде этого:
https://github.com/schancel/gameserver/blob/master/source/client/messaging.d
Код не самый красивый, но он использует отражения для вставки дополнительных операторов case.
То, что вы ищете, обычно называется в литературе как образец командования. В языках с высокой степенью OO этот шаблон обычно включает создание группы классов, которые реализуют общий простой интерфейс Command, который имеет один execute()
метод. Однако в D у вас есть делегаты, и вы, вероятно, можете избежать создания потенциально сотен небольших классов для этой цели.
Вот одна из возможных альтернатив D, использующих лямбда-выражения ( http://dlang.org/expression.html):
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
Вот исходный код для разветвления и игры: http://dpaste.dzfl.pl/41d72036
Я напишу ОО версию, когда найду больше времени...
Что касается выполнения скрипта / приложения в некотором каталоге... Это просто вопрос написания функции, которая принимает параметры и вызывает std.process.execute()
, Очень быстрый пример того, как расширить код выше:
// 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. :)