Функции вызова по строке - PullRequest
       8

Функции вызова по строке

0 голосов
/ 14 февраля 2019

Есть ли способ вызвать процедуру по ее имени в строковой переменной в Ada, как это делает Python с:

def _ssh(hostname, port):
    pass
def _telnet(hostname, port):
    pass 
def _mosh(hostname, port):
    pass
protocols = {
    'ssh': _ssh,
    'mosh': _mosh,
    'telnet': _telnet
}
# call your function by string
hostname = 'localhost'
port = '22'
protocol = 'ssh'
result = protocols[protocol](hostname, port)

Ответы [ 3 ]

0 голосов
/ 15 февраля 2019

Ну, это немного работы, так как у вас нет удобных сокращений для создания карт (или словарей).Это делает работу:

with Ada.Containers.Indefinite_Ordered_Maps;
with Ada.Text_IO; use Ada.Text_IO;

procedure Alubio is

Нам нужен указатель на подпрограмму, чтобы создать экземпляр Map

   type Handler is access procedure (Hostname : String; Port : Integer);

Карта от строки до указателя на подпрограмму.Он должен быть «неопределенным», потому что тип String является неопределенным (не фиксированного размера), и его нужно «упорядочивать», потому что мы не хотим беспокоиться об объявлении хеш-функций и т. Д.

   package Maps is new Ada.Containers.Indefinite_Ordered_Maps
     (Key_Type     => String,
      Element_Type => Handler);

Мне нравится объявлять подпрограммы перед их определением, но здесь это не является строго обязательным

   procedure Ssh (Hostname : String; Port : Integer);
   procedure Mosh (Hostname : String; Port : Integer);
   procedure Telnet (Hostname : String; Port : Integer);

Карта

   Map : Maps.Map;

Демонстрационные подпрограммы

   procedure Ssh (Hostname : String; Port : Integer) is
   begin
      Put_Line ("ssh, " & Hostname & Port'Image);
   end Ssh;

   procedure Mosh (Hostname : String; Port : Integer) is
   begin
      Put_Line ("mosh, " & Hostname & Port'Image);
   end Mosh;

   procedure Telnet (Hostname : String; Port : Integer) is
   begin
      Put_Line ("telnet, " & Hostname & Port'Image);
   end Telnet;

begin

НастройкаКарта

   Map.Insert ("ssh", Ssh'Access);
   Map.Insert ("mosh", Mosh'Access);
   Map.Insert ("telnet", Telnet'Access);

Вызов подпрограмм через Карту.Не совсем уверенный, зачем нужен .all (разыменование указателя на подпрограмму), вы часто этого не делаете: здесь, без него, компилятор говорит «недопустимый вызов процедуры или ввода», указывая на Map.

   Map ("ssh").all ("s", 1);
   Map ("mosh").all ("m", 2);
   Map ("telnet").all ("t", 3);

end Alubio;

Выход:

$ ./alubio 
ssh, s 1
mosh, m 2
telnet, t 3
0 голосов
/ 15 февраля 2019

Простым способом является использование перечислимого типа и оператора case.

type Protocol is (ssh, mosh, telnet);

, затем с переменной given_protocol : Protocol:

case given_protocol is
  when ssh    => Ssh (Hostname, Port);
  when mosh   => Mosh (Hostname, Port);
  when telnet => Telnet (Hostname, Port);
end case;

Это позволяет избежать типов доступа и отображений.

Вы получаете given_protocol из строки, используя атрибут 'Value: given_protocol := Protocol'Value (given_string).

0 голосов
/ 14 февраля 2019

Насколько я знаю, это невозможно, так как Ada не хранит функции и процедуры в хэш-карте, как это делает Python.Вы по-прежнему можете предоставить функцию, принимающую строку в качестве аргумента и возвращающую доступ к функции, которую вы можете вызвать позже, но я не уверен, что вы пытаетесь это сделать.

...