Как вы можете хранить (доступ к) операторы Integer в Аде? - PullRequest
5 голосов
/ 13 июня 2019

В Ada контекст может определить, что «+» - это не строка, а целочисленный оператор, как в выражении: "+"(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;

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

Ответы [ 2 ]

8 голосов
/ 13 июня 2019

Боюсь, ты не сможешь этого сделать.Подпрограмма "+" для Integer определена в пакете Standard [ ARM A.1 (17) ] и, следовательно, присуща [ AARM A.1 (2.a) ].Нельзя ссылаться на внутреннюю подпрограмму [ ARM 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
2 голосов
/ 22 июня 2019

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

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

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, или есливы находитесь на уровне вложенного кода, и все, что вы передали на уровень вложенности, - это доступ к значению подпрограммы.Но я думаю, что в целом лучше использовать непатентованные средства или, по крайней мере, рассматривать этот вариант в качестве первого предпочтения, если у вас нет веских причин не делать этого.

...