# \[Solved\] Access to a "method"?

**URL:** <https://forum.ada-lang.io/t/solved-access-to-a-method/755>\
**Category:** General\
**Created:** [April 8, 2024, 9:29am UTC](https://forum.ada-lang.io/t/solved-access-to-a-method/755 "2024-04-08T09:29:18Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![Shuihuzhuan](https://forum.ada-lang.io/letter_avatar_proxy/v4/letter/s/c6cbf5/32.png) [@Shuihuzhuan](https://forum.ada-lang.io/u/Shuihuzhuan)\
**Post date:** [April 8, 2024, 9:29am UTC](https://forum.ada-lang.io/t/solved-access-to-a-method/755/1 "2024-04-08T09:29:18Z")

</div>

Hi,

I’m writing a small library. I’m now sealing few records that were in the API into tagged private records with getters and setters.

However members of the records were ‘in out’ parameters of some procedures. I’ve tried a few things but I can’t find a proper way/syntax to replace `Process (Item.Member)` with an equivalent `Process (Item.Set_Member)`.

In the example (simplified) code below, I get `error: no selector "Set_Member" for private type "Test"` if I uncomment the last line.

```ada
with Ada.Wide_Wide_Text_IO;

procedure Bacasable is

   package AIO renames Ada.Wide_Wide_Text_IO;

   package Test_P is

      -- Old record
      -- type Test is record
      -- Member : Integer := 0;
      -- end Test;

      -- New sealed record
      type Test is tagged private;
      procedure Set_Member (T : in out Test; Value : Integer);

   private

      type Test is tagged record
         Member : Integer := 0;
      end record;

   end Test_P;

   package body Test_P is

      procedure Set_Member (T : in out Test; Value : Integer) is
      begin
         T.Member := Value;
      end Set_Member;

   end Test_P;

   -- Old Process procedure
   -- procedure Process (Value : in out Integer)
   -- is
   -- begin
   -- Value := 10;
   -- end Process;

   -- What I hoped could work
   type Integer_A is access procedure (Value : Integer);

   procedure Process (Value : Integer_A) is
   begin
      Value (10);
   end Process;

   Item : Test_P.Test;

begin

   AIO.Put_Line (Item'Wide_Wide_Image);
   Item.Set_Member (2);
   AIO.Put_Line (Item'Wide_Wide_Image);
   -- Process (Item.Set_Member'Access);
   -- ^--- This does'nt work             
end Bacasable;

```

For the moment, I only use a temporary variable `Process (Temp)` and then `Item.Set_Member (Temp)` but it’s quite ugly.

Am I missing something?

Thanks for your help.

---

<div class="post-metadata">

**Author:** ![godunko](https://forum.ada-lang.io/user_avatar/forum.ada-lang.io/godunko/32/22_2.png) [@godunko](https://forum.ada-lang.io/u/godunko)\
**Post date:** [April 8, 2024, 9:58am UTC](https://forum.ada-lang.io/t/solved-access-to-a-method/755/2 "2024-04-08T09:58:48Z")

</div>

`Item.Set_Member` is a “call of the procedure Set\_Member”. Compiler unable to find function declaration with appropriate profile, thus reports error. It is hard to guess what happened from the error here.

Can you provide a bit more details what you want to do? There are few possible solutions, with access to subprogram, with generics…

---

<div class="post-metadata">

**Author:** ![Shuihuzhuan](https://forum.ada-lang.io/letter_avatar_proxy/v4/letter/s/c6cbf5/32.png) [@Shuihuzhuan](https://forum.ada-lang.io/u/Shuihuzhuan)\
**Post date:** [April 8, 2024, 11:40am UTC](https://forum.ada-lang.io/t/solved-access-to-a-method/755/3 "2024-04-08T11:40:53Z")

</div>

Thanks for your reply.

In the library, I’m processing some JSON file to update a record.

Depending on the JSON field I’m currently reading, I was calling `Process_Integer`, `Process_Date`, `Process_String_Vector` and the likes with the corresponding field of the record as `Item` parameter. These procedures had signatures similar to:

```ada
procedure Parse_Integer
     (Reader : in out VSS.JSON.Pull_Readers.JSON_Pull_Reader'Class;
      Item : out Long_Long_Integer;
      Success : out Boolean)

```

I would have expected that `Item.Set_Member'Access` could be interpreted as an access to `Test_P.Set_Member (T => Item, <other parameter>)` as there’s no ambiguity (some sort of a closure).

---

<div class="post-metadata">

**Author:** ![jere](https://forum.ada-lang.io/user_avatar/forum.ada-lang.io/jere/32/87_2.png) [@jere](https://forum.ada-lang.io/u/jere)\
**Post date:** [April 8, 2024, 2:36pm UTC](https://forum.ada-lang.io/t/solved-access-to-a-method/755/4 "2024-04-08T14:36:20Z")

</div>

The problem is your set member function has the signature similar to:  
`procedure Set_Member (T : in out Test; Value : Integer);`

While your access type expects:  
`type Integer_A is access procedure (Value : Integer);`

which is a totally different signature.

If all your objects are of type Test, then you can change it to:  
`type Integer_A is access procedure (T : in out Test; Value : Integer);`

or if they are different but have the same base class, you can make Set\_Member a base class operation, avoid the access types all together, and change process to:

```ada
   procedure Process (Source : in out Base_Class'Class) is
   begin
      Source.Set_Member(10);
   end Process;

```

if they aren’t the same base class, you can make an interface with Set\_Member as primitive and adjust each of the types to implement the interface and again change process to:

```ada
   procedure Process (Source : in out Your_Interface'Class) is
   begin
      Source.Set_Member(10);
   end Process;

```

Full example:

```ada
with Ada.Text_IO; use Ada.Text_IO;

procedure jdoodle is

   package Test_Interfaces is
        type Integer_Test is limited interface;
        procedure Set_Member(Self : in out Integer_Test; Value : Integer) is abstract;
   end Test_Interfaces;
    
   package Test_P is
   
      use Test_Interfaces;

      -- Old record
      -- type Test is record
      -- Member : Integer := 0;
      -- end Test;

      -- New sealed record
      type Test is new Integer_Test with private;
      procedure Set_Member (T : in out Test; Value : Integer);

   private

      type Test is new Integer_Test with record
         Member : Integer := 0;
      end record;

   end Test_P;

   package body Test_P is

      procedure Set_Member (T : in out Test; Value : Integer) is
      begin
         T.Member := Value;
      end Set_Member;

   end Test_P;

   procedure Process (Source : in out Test_Interfaces.Integer_Test'Class) is
   begin
      Source.Set_Member (10);
   end Process;

   Item : Test_P.Test;
    
begin
   Process(Item);
end jdoodle;

```

---

<div class="post-metadata">

**Author:** ![Shuihuzhuan](https://forum.ada-lang.io/letter_avatar_proxy/v4/letter/s/c6cbf5/32.png) [@Shuihuzhuan](https://forum.ada-lang.io/u/Shuihuzhuan)\
**Post date:** [April 8, 2024, 3:43pm UTC](https://forum.ada-lang.io/t/solved-access-to-a-method/755/5 "2024-04-08T15:43:07Z")

</div>

Yes,

But, as I understand your proposal, `Set_Member` will be encoded in the `Process` procedures instead of passed as an argument. Thus `Process` will be specialized for that field of the record only.

`Process_Integer`, `Process_Date` and … are ‘generic’ in the sense that they don’t encode which specific field of the record they need to update (I may have twenty of them).

Here is an example of how it’s used (with all the `if`’s and `Temp` variables I need now).

```ada
while Success loop
   case Reader.Read_Next is
	when VSS.JSON.Streams.Key_Name =>
	   if Reader.Key_Name = "ID" then
	      Parse_Integer (Reader, Temp_Integer, Success);
	      if Success then
	         Item.Set_Id (Temp_Integer);
	      end if;
	   elsif Reader.Key_Name = "Name" then
	      Parse_String (Reader, Temp_String, Success);
	      if Success then
	         Item.Set_Name (Temp_String);
	      end if;
	   elsif Reader.Key_Name = "Description" then
	      Parse_String (Reader, Temp_String, Success);
	      if Success then
	         Item.Set_Description (Temp_String);
	      end if;
	   elsif …

```

I don’t really like the idea, but I can probably replace my procedures with functions returning the value and keep an `out` parameter for `Success` to avoid all the `if`.

Something like:

```ada
function Parse_String (Reader : in out VSS.JSON.Pull_Readers.JSON_Pull_Reader'Class;
                       Item : in Virtual_String; 
                       Success : out Boolean)
   return Virtual_String;

```

and then I’ll just have to:

```ada
…
elsif Reader.Key_Name = "Name" then
   Item.Set_Name (Parse_String (Reader, Item.Get_Name, Success));
elsif Reader.Key_Name = "Description" then
…

```

The argument `Item.Get_Name` is used here to return the previous value in case of failure. `Success` is needed to end the loop.

It’s less verbose, but also less optimal as `Set_Name` is called even if nothing changes. And functions with `out` parameters are not ideal.

---

<div class="post-metadata">

**Author:** ![jere](https://forum.ada-lang.io/user_avatar/forum.ada-lang.io/jere/32/87_2.png) [@jere](https://forum.ada-lang.io/u/jere)\
**Post date:** [April 8, 2024, 6:00pm UTC](https://forum.ada-lang.io/t/solved-access-to-a-method/755/6 "2024-04-08T18:00:21Z")

</div>

I guess what is confusing me on your question is why doesn’t the following work for you?

```ada
   type Integer_A is access procedure (Item : in out Test_P.Test; Value : Integer);

   procedure Process (Item: in out Test_P.Test; Value : Integer_A) is
   begin
      Value (Item, 10);
   end Process;

```

```ada
   AIO.Put_Line (Item'Wide_Wide_Image);
   Item.Set_Member (2);
   AIO.Put_Line (Item'Wide_Wide_Image);
   Process (Item, Test_P.Set_Member'Access);  

   AIO.Put_Line (Item'Wide_Wide_Image);

```

From your original post, I had assumed different types were hanging you up, but based on your last post, the types are all the same, just different member functions?

---

<div class="post-metadata">

**Author:** ![Shuihuzhuan](https://forum.ada-lang.io/letter_avatar_proxy/v4/letter/s/c6cbf5/32.png) [@Shuihuzhuan](https://forum.ada-lang.io/u/Shuihuzhuan)\
**Post date:** [April 8, 2024, 8:25pm UTC](https://forum.ada-lang.io/t/solved-access-to-a-method/755/7 "2024-04-08T20:25:29Z")

</div>

Thanks! I was looking for something too complicated.

Passing `Item` and `Set_Member` as different parameters instead of a single `Item.Set_Member` is just simple.

I’ll probably have to add `'Class` as I have at least two possible types for `Item`. But they live in the same hierarchy, so the solution is perfect for me.

---

<div class="post-metadata">

**Author:** ![jere](https://forum.ada-lang.io/user_avatar/forum.ada-lang.io/jere/32/87_2.png) [@jere](https://forum.ada-lang.io/u/jere)\
**Post date:** [April 8, 2024, 10:04pm UTC](https://forum.ada-lang.io/t/solved-access-to-a-method/755/8 "2024-04-08T22:04:15Z")

</div>

No problem. Sorry it took a while to figure out.
