Как вы можете хранить (доступ) целочисленные операторы в Аде?

В Аде контекст может определить, что «+» — это не строка, а целочисленный оператор, как в выражении: "+"(5,2). Вопрос в том, как мне сохранить этот оператор в переменной? Я хочу передать этот целочисленный оператор или какой-либо другой как бинарную функцию, принимающую два целых числа и возвращающую целое число. В приведенном ниже коде я сделал явную функцию, которая просто вызывает оператор, который я могу использовать в качестве обходного пути. Есть ли способ избежать этой оболочки и напрямую передать (доступ) оператору Integer «+»?

with Ada.Text_IO; use Ada.Text_IO;

procedure operator is

  type binary_int_operator is access function(lhs : Integer; rhs : Integer) return Integer;

  --plus : binary_int_operator := Integer."+"'Access;
  --plus : binary_int_operator := Integer'Access("+");
  --plus : binary_int_operator := Integer'"+";
  --plus : binary_int_operator := "+";

  function plus(lhs : Integer; rhs : Integer) return Integer is
  begin
    return lhs + rhs;
  end plus;

begin
  Put_Line(Integer'Image("+"(5, 12)));
end operator;

Закомментированные объявления показывают некоторые сделанные мной попытки, которые не компилируются.

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
5
0
226
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Боюсь, вы не можете этого сделать. Подпрограмма "+" для Integer определена в пакете Standard [АРМ А.1 (17)] и, следовательно, встроена [ААРМ А.1 (2.а)]. Не допускается ссылка на встроенную подпрограмму [АРМ 3.10.2 (32.3)]. Таким образом, компиляция программы

procedure Main is

   type Binary_Int_Operator is
     access function (lhs : Integer; rhs : Integer) return Integer;

   Plus : Binary_Int_Operator := Standard."+"'Access;

begin
   null;
end Main;

урожаи

6:34 prefix of "Access" attribute cannot be intrinsic

Единственный обходной путь — использование косвенного обращения. Эта программа компилирует

with Ada.Text_IO;         use Ada.Text_IO;
with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;

procedure Main_Alt is

   type Operation is
     access function (Lhs, Rhs : Integer) return Integer;


   --  Sticking to "+" and "-" instead of names like Add or Subtract
   --  to demonstrate that you can reference operator subprograms
   --  (using the Access attribute) as long as they're not intrinsic.

   function "+" (Lhs, Rhs : Integer) return Integer is
     (Standard."+" (Lhs, Rhs));

   function "-" (Lhs, Rhs : Integer) return Integer is
     (Standard."-" (Lhs, Rhs));


   procedure Calc_And_Show (Lhs, Rhs : Integer; Op : Operation) is
   begin
      Put (Op (lhs, rhs));
      New_Line;
   end Calc_And_Show;

begin
   Calc_And_Show (5, 3, "+"'Access); 
   Calc_And_Show (5, 3, "-"'Access);
end Main_Alt;

и урожаи (как и ожидалось)

$ ./main_alt
          8
          2

Да, я тоже пробовал :-), но переименование подпрограммы, в конце концов, просто получение представления об исходной подпрограмме. Все свойства (включая внутреннее соглашение о вызовах) наследуются [ARM 8.5.4(7)].

DeeDee 15.06.2019 13:21

Я бы предложил рассмотреть другой подход с использованием дженериков. Как правило, я думаю, что вы получаете более простой интерфейс для звонка, чем вы get пытается передать доступ к параметрам подпрограммы. (т.е. не нужно передавать операцию для каждого вызова).

Используя дженерики, вам вообще не нужно использовать «Доступ», и вы могу передаете встроенные функции, такие как целое число «+», в качестве формальных универсальных параметров.

with Ada.Text_IO;         use Ada.Text_IO;
with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;

procedure Main is

   generic
      with function Op (L, R : Integer) return Integer;
   procedure Calc_And_Show (Lhs, Rhs : Integer);

   procedure Calc_And_Show (Lhs, Rhs : Integer) is
   begin
      Put (Op (lhs, rhs));
      New_Line;
   end Calc_And_Show;

   procedure Calc_And_Show_Plus is new Calc_And_Show (Op => "+");
   procedure Calc_And_Show_Minus is new Calc_And_Show (Op => "-");

begin
   Calc_And_Show_Plus  (5, 3); 
   Calc_And_Show_Minus (5, 3);   
end Main;

Могут быть причины, по которым вы захотите использовать вместо этого параметры доступа, например, если вы хотите, чтобы Calc_And_Show можно было вызывать из других языков, таких как C, или если вы находитесь на вложенном уровне кода и все, что вы передали на свой вложенный уровень является доступом к значению подпрограммы. Но я думаю, что в целом рекомендуется использовать дженерики или, по крайней мере, рассматривать этот вариант в качестве первого предпочтения, если у вас нет веских причин не делать этого.

Аккуратный ответ, показывающий дженерики Ады. К сожалению, в этом случае это действительно не отвечает на вопрос, как и другой ответ: «нет, вы не можете». В моем случае мне нужно выбрать операцию во время выполнения, поэтому даже с этими универсальными функциями между ними мне понадобится оператор case, который передает полностью указанные универсальные функции, поэтому мне все равно нужно будет передать доступ к функции.

TamaMcGlinn 23.06.2019 22:18

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