Вызов функций по строке

Есть ли способ вызвать процедуру по ее имени в переменной String в Аде, как это делает 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)
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
0
140
3

Ответы 3

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

Это верное решение, как и решение Саймона. Но это не совместимо с моей реальной проблемой вызова защищенной процедуры из типа доступа внутри другой защищенной процедуры в том же объекте.

Alubio 15.02.2019 10:01

Хорошо, я понимаю, но это не было указано в вашем первоначальном вопросе.

Frédéric Praca 15.02.2019 11:45

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

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

Это был мой первый подход. Я вызываю процедуру в защищенном объекте, используя тип защищенной процедуры доступа, хранящийся на карте. Но я делаю этот вызов внутри другой процедуры в том же защищенном объекте и получаю программную ошибку во время выполнения. Я подозреваю, что здесь есть ограничение блокировки, но я не могу этого понять. Я знаю, что это другой вопрос. Я пытаюсь найти другой подход, такой как сохранение строки вместо типа доступа.

Alubio 15.02.2019 09:56

Возможно, если бы вы показали нам свой код (как вы действительно должны это сделать на SO), мы могли бы помочь лучше. Или рассказал нам о своей реальной проблеме... звучит так, как будто вы уже знали, что я показал, поэтому я зря тратил время, что не побуждает меня смотреть глубже. Тем не менее, может ли быть так, что компилятор не может сказать, что фактическая вызываемая процедура фактически находится в том же PO?

Simon Wright 15.02.2019 12:35

Возможно, вы нарушаете 9.5.1 15 RM, что вызывает Program_Error: внешний вызов защищенной подпрограммы (или внешней очереди) с тем же целевым объектом, что и у защищенного действия?

Jere 15.02.2019 12:58

Я открою еще один вопрос о вызове защищенных процедур с использованием типов доступа, так как это другой вопрос/тема. В этом вопросе я хочу знать только разные способы вызова процедуры, используя ее имя в String. Вы внесли свой вклад с одним совершенно правильным решением. Может быть, есть еще.

Alubio 15.02.2019 12:58

Простой способ — использовать перечисляемый тип и оператор 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).

Еще одно хорошее решение. Знаете ли вы какую-нибудь библиотеку для создания простых интерфейсов командной строки, таких как маршрутизаторы Cisco?

Alubio 18.02.2019 10:11

Другие вопросы по теме