comp.lang.ada
 help / color / mirror / Atom feed
* API design considerations - variable-length array in record type
@ 2012-10-08  9:03 Maciej Sobczak
  2012-10-08 11:13 ` Simon Wright
                   ` (3 more replies)
  0 siblings, 4 replies; 11+ messages in thread
From: Maciej Sobczak @ 2012-10-08  9:03 UTC (permalink / raw)


Hi,

I am working on the API design where there is a need for a record type with field(s) that are arrays of some predefined type (say, Integer). So, an example record type might look like this:

type R is record
   X : Integer;
   Y : Unbounded_String;
   Z : Array_Of_Integers_That_We_Talk_About_Here;
end record;

The trouble is, the types involved should comply with the following requirements:

- the enclosing record type should not be limited (it should be copyable)
- the record type can be explicitly controlled, if necessary
- the record type should be definite (it should not require initialization)
- it should be possible to assign to Z, just as it is possible to assign to X and Y, and the new value for Z *might have a different length*

An important relaxation is that it is not necessary to support in-place modifications of the field in question. That is, Y above can be modified (by appending or modifying individual characters, for example) in place. It is not necessary to support it for Z, assignment of the whole array is the only operation that is needed there.

A straightforward choice is a predefined instantiation of Ada.Containers.Vectors for Integer and this would be probably the least surprising, especially in the context of Y : Unbounded_String, but at the same time I'm open to consider some more lightweight alternatives.
The problem is - any other alternative I can think of leads to the complication of API in the form of introducing Ada.Finalization.Controlled to the picture.

Do you have some favourite solutions?

For comparison, in C++ this would be solved with std::vector<int>, which suggests Ada.Containers.Vectors for Ada; but in Java this would be done simply with int[], which is conceptually lighter and easier to use in this particular context.

-- 
Maciej Sobczak * http://www.msobczak.com * http://www.inspirel.com



^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: API design considerations - variable-length array in record type
  2012-10-08  9:03 API design considerations - variable-length array in record type Maciej Sobczak
@ 2012-10-08 11:13 ` Simon Wright
  2012-10-08 11:29 ` Egil Høvik
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 11+ messages in thread
From: Simon Wright @ 2012-10-08 11:13 UTC (permalink / raw)


Maciej Sobczak <see.my.homepage@gmail.com> writes:

> A straightforward choice is a predefined instantiation of
> Ada.Containers.Vectors for Integer and this would be probably the
> least surprising, especially in the context of Y : Unbounded_String,
> but at the same time I'm open to consider some more lightweight
> alternatives.

This would be my choice!

> The problem is - any other alternative I can think of leads to the
> complication of API in the form of introducing
> Ada.Finalization.Controlled to the picture.

You could use "private with".



^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: API design considerations - variable-length array in record type
  2012-10-08  9:03 API design considerations - variable-length array in record type Maciej Sobczak
  2012-10-08 11:13 ` Simon Wright
@ 2012-10-08 11:29 ` Egil Høvik
  2012-10-08 11:53   ` Maciej Sobczak
  2012-10-09  2:02 ` Shark8
  2012-10-09  3:10 ` Stephen Leake
  3 siblings, 1 reply; 11+ messages in thread
From: Egil Høvik @ 2012-10-08 11:29 UTC (permalink / raw)


On Monday, October 8, 2012 11:03:04 AM UTC+2, Maciej Sobczak wrote:
> 
> A straightforward choice is a predefined instantiation of Ada.Containers.Vectors for Integer and this would be probably the least surprising, especially in the context of Y : Unbounded_String, but at the same time I'm open to consider some more lightweight alternatives.
> 

If you don't mind using Ada 2012 packages, there's also Ada.Containers.Indefinite_Holders (RM A.18.18).
I haven't used it myself yet, so I can't say anything about how lightweight it is compared to Vector.

-- 
~egilhh



^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: API design considerations - variable-length array in record type
  2012-10-08 11:29 ` Egil Høvik
@ 2012-10-08 11:53   ` Maciej Sobczak
  2012-10-08 14:37     ` Tero Koskinen
  0 siblings, 1 reply; 11+ messages in thread
From: Maciej Sobczak @ 2012-10-08 11:53 UTC (permalink / raw)


Hi Egil,

W dniu poniedziałek, 8 października 2012 13:29:26 UTC+2 użytkownik Egil Høvik napisał:

> If you don't mind using Ada 2012 packages, there's also Ada.Containers.Indefinite_Holders (RM A.18.18).

That would be a perfectly justified choice, except for the fact that this is a library code, which is intended for wider use and relying on Ada 2012 would be too constraining.
Still, a possible approach would be to (re)implement Indefinite_Holders as a supporting package and at some point in the future switch to the standard package with minimal or no impact. I will seriously take it into consideration.

Regards,

-- 
Maciej Sobczak * http://www.msobczak.com * http://www.inspirel.com



^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: API design considerations - variable-length array in record type
  2012-10-08 11:53   ` Maciej Sobczak
@ 2012-10-08 14:37     ` Tero Koskinen
  0 siblings, 0 replies; 11+ messages in thread
From: Tero Koskinen @ 2012-10-08 14:37 UTC (permalink / raw)


Hi,

On Mon, 8 Oct 2012 04:53:15 -0700 (PDT)
Maciej Sobczak <see.my.homepage@gmail.com> wrote:
> W dniu poniedziałek, 8 października 2012 13:29:26 UTC+2 użytkownik Egil Høvik napisał:
> 
> > If you don't mind using Ada 2012 packages, there's also Ada.Containers.Indefinite_Holders (RM A.18.18).
> 
> That would be a perfectly justified choice, except for the fact that this is a library code, which is intended for wider use and relying on Ada 2012 would be too constraining.
> Still, a possible approach would be to (re)implement Indefinite_Holders as a supporting package and at some point in the future switch to the standard package with minimal or no impact. I will seriously take it into consideration.

I have variation of Indefinite_Holders implemented in Ada 95 here:
https://bitbucket.org/tkoskine/hauki/src/tip/src/hauki-containers-object_holders.ads
https://bitbucket.org/tkoskine/hauki/src/tip/src/hauki-containers-object_holders.adb

My implementation probably doesn't match Ada 2012 100%, but shows
that it is possible to implemented them in Ada 95 also.

> 
> Regards,
> 
> -- 
> Maciej Sobczak * http://www.msobczak.com * http://www.inspirel.com


-- 
Tero Koskinen - http://iki.fi/tero.koskinen/



^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: API design considerations - variable-length array in record type
  2012-10-08  9:03 API design considerations - variable-length array in record type Maciej Sobczak
  2012-10-08 11:13 ` Simon Wright
  2012-10-08 11:29 ` Egil Høvik
@ 2012-10-09  2:02 ` Shark8
  2012-10-09  5:16   ` Adam Beneschan
  2012-10-09  5:42   ` Niklas Holsti
  2012-10-09  3:10 ` Stephen Leake
  3 siblings, 2 replies; 11+ messages in thread
From: Shark8 @ 2012-10-09  2:02 UTC (permalink / raw)


On Monday, October 8, 2012 3:03:04 AM UTC-6, Maciej Sobczak wrote:
> 
> type R is record
>    X : Integer;
>    Y : Unbounded_String;
>    Z : Array_Of_Integers_That_We_Talk_About_Here;
> end record;
> 
> Requirements:
> 1 - the enclosing record type should not be limited (it should be copyable)
> 2 - the record type can be explicitly controlled, if necessary
> 3 - the record type should be definite (it should not require initialization)
> 4 - it should be possible to assign to Z, just as it is possible to assign to X and Y, and the new value for Z *might have a different length* 

Why not use discriminants on the record?

Default : Constant := Natural'First;
type R( Array_Length : Natural:= Natural'First ) is record
   X : Integer;
   Y : Unbounded_String;
   Z : Array_Of_Integers_That_We_Talk_About_Here(1..Array_Length):= (Others => Default);
end record;



^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: API design considerations - variable-length array in record type
  2012-10-08  9:03 API design considerations - variable-length array in record type Maciej Sobczak
                   ` (2 preceding siblings ...)
  2012-10-09  2:02 ` Shark8
@ 2012-10-09  3:10 ` Stephen Leake
  2012-10-09  7:47   ` Maciej Sobczak
  3 siblings, 1 reply; 11+ messages in thread
From: Stephen Leake @ 2012-10-09  3:10 UTC (permalink / raw)


Maciej Sobczak <see.my.homepage@gmail.com> writes:

> Hi,
>
> I am working on the API design where there is a need for a record type
> with field(s) that are arrays of some predefined type (say, Integer).
> So, an example record type might look like this:
>
> type R is record
>    X : Integer;
>    Y : Unbounded_String;
>    Z : Array_Of_Integers_That_We_Talk_About_Here;
> end record;
>
> A straightforward choice is a predefined instantiation of
> Ada.Containers.Vectors for Integer and this would be probably the
> least surprising, especially in the context of Y : Unbounded_String,
> but at the same time I'm open to consider some more lightweight
> alternatives.
> The problem is - any other alternative I can think of leads to the
> complication of API in the form of introducing
> Ada.Finalization.Controlled to the picture.
>
> Do you have some favourite solutions?

Ada.Containers.Bounded_Vectors meets these requirements.

-- 
-- Stephe



^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: API design considerations - variable-length array in record type
  2012-10-09  2:02 ` Shark8
@ 2012-10-09  5:16   ` Adam Beneschan
  2012-10-09  5:45     ` Shark8
  2012-10-09  5:42   ` Niklas Holsti
  1 sibling, 1 reply; 11+ messages in thread
From: Adam Beneschan @ 2012-10-09  5:16 UTC (permalink / raw)


On Monday, October 8, 2012 7:02:37 PM UTC-7, Shark8 wrote:
> On Monday, October 8, 2012 3:03:04 AM UTC-6, Maciej Sobczak wrote:
> 
> > type R is record
> >    X : Integer;
> >    Y : Unbounded_String;
> >    Z : Array_Of_Integers_That_We_Talk_About_Here;
> > end record;
> 
> > Requirements:
> 
> > 1 - the enclosing record type should not be limited (it should be copyable)
> > 2 - the record type can be explicitly controlled, if necessary
> > 3 - the record type should be definite (it should not require initialization)
> > 4 - it should be possible to assign to Z, just as it is possible to assign to X and Y, and the new value for Z *might have a different length* 
> 
> Why not use discriminants on the record?
> 
> Default : Constant := Natural'First;
> type R( Array_Length : Natural:= Natural'First ) is record
>    X : Integer;
>    Y : Unbounded_String;
>    Z : Array_Of_Integers_That_We_Talk_About_Here(1..Array_Length):= (Others => Default);
> end record;

Note that this will not work on all implementations.  There are two ways to implement an array component whose bound depends on a discriminant: (1) the record type will contain space for the largest possible array, or (2) the record type can contain a pointer to a dynamically sized array, which then may need to be deallocated and reallocated when a new value is assigned to the record.  (Other methods are possible in theory.)  The above won't work well on compilers that implement (1) because the record will then need to be big enough to hold Natural'Last integers (plus the other fields), and that could be way too much space depending on the range of Natural.  If there is a known, fairly small upper bound, and you're willing to allocate that much space in every record, then declare a subtype of Natural and use that subtype in the discriminant clause.  Otherwise I'd avoid this construct.

(P.S. Is it just me, or is anyone else irritated by the use of Natural'First or Positive'First?  Using something like Integer'First is a great idea, because that makes things portable between implementations since not all implementations have the same Integer bounds.  And if you have a subtype S, you should usually say S'First instead of coding the literal value, because who knows what reason you might have in the future for deciding to change the declaration of S, and then you only have to change it in one place.  But I don't see the point of Natural'First.  It will always be 0, on all implementations, and can never be changed no matter how many times you redesign your program, so why not just write 0?  OK, that's my one rant for the day.)

                           -- Adam




^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: API design considerations - variable-length array in record type
  2012-10-09  2:02 ` Shark8
  2012-10-09  5:16   ` Adam Beneschan
@ 2012-10-09  5:42   ` Niklas Holsti
  1 sibling, 0 replies; 11+ messages in thread
From: Niklas Holsti @ 2012-10-09  5:42 UTC (permalink / raw)


On 12-10-09 05:02 , Shark8 wrote:
> On Monday, October 8, 2012 3:03:04 AM UTC-6, Maciej Sobczak wrote:
>>
>> type R is record
>>    X : Integer;
>>    Y : Unbounded_String;
>>    Z : Array_Of_Integers_That_We_Talk_About_Here;
>> end record;
>>
>> Requirements:
>> 1 - the enclosing record type should not be limited (it should be copyable)
>> 2 - the record type can be explicitly controlled, if necessary
>> 3 - the record type should be definite (it should not require initialization)
>> 4 - it should be possible to assign to Z, just as it is possible to assign to X and Y, and the new value for Z *might have a different length* 
> 
> Why not use discriminants on the record?
> 
> Default : Constant := Natural'First;
> type R( Array_Length : Natural:= Natural'First ) is record
>    X : Integer;
>    Y : Unbounded_String;
>    Z : Array_Of_Integers_That_We_Talk_About_Here(1..Array_Length):= (Others => Default);
> end record;

Requirement 4 is not satisfied: if you assign a new value to R.Z, it has
to have the same length as the old value (R.Array_Length). You can
change the length only by assigning a new value, with the new discrimant
value, to the whole record.

And there is the memory usage problem that Adam described.

-- 
Niklas Holsti
Tidorum Ltd
niklas holsti tidorum fi
      .      @       .



^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: API design considerations - variable-length array in record type
  2012-10-09  5:16   ` Adam Beneschan
@ 2012-10-09  5:45     ` Shark8
  0 siblings, 0 replies; 11+ messages in thread
From: Shark8 @ 2012-10-09  5:45 UTC (permalink / raw)


On Monday, October 8, 2012 11:16:28 PM UTC-6, Adam Beneschan wrote:
> 
> Note that this will not work on all implementations.  There are two ways to implement an array component whose bound depends on a discriminant: (1) the record type will contain space for the largest possible array, or 

I think that's only an issue if the discriminant itself has a default value.
(Something to do with view-changing, now that you mention this possible problem.)

> (Other methods are possible in theory.)

I'd like to know what those theories are.

> (P.S. Is it just me, or is anyone else irritated by the use of Natural'First or Positive'First?  

I'm more irritated there's no 'type attribute so you can't say something like Type K( X : Enum_21:= X'Type'First ) [...] for specifying that you do want the type to have a defaulted discriminant, and that should be the 'First of that type. {After-all the type of X has to be known at compile-time.} Though that particular example might not be the best; using X before it's declaration is illegal. -- Though the idea could be useful other places.

> if you have a subtype S, you should usually say S'First instead of coding the literal value, because who knows what reason you might have in the future for deciding to change the declaration of S, and then you only have to change it in one place.  But I don't see the point of Natural'First.  It will always be 0, on all implementations, and can never be changed no matter how many times you redesign your program, so why not just write 0?  OK, that's my one rant for the day.)

I usually do it to remind myself that I'm dealing w/ subtypes. {That is, it helps me to think in terms of sets/subsets.}



^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: API design considerations - variable-length array in record type
  2012-10-09  3:10 ` Stephen Leake
@ 2012-10-09  7:47   ` Maciej Sobczak
  0 siblings, 0 replies; 11+ messages in thread
From: Maciej Sobczak @ 2012-10-09  7:47 UTC (permalink / raw)


W dniu wtorek, 9 października 2012 05:10:49 UTC+2 użytkownik Stephen Leake napisał:

> Ada.Containers.Bounded_Vectors meets these requirements.

No, because there is no predefined upper bound on the length of array.

I have to admit that the idea with Indefinite_Holders looks the most attractive and the essential parts of this solution are very easy to implement.

-- 
Maciej Sobczak * http://www.msobczak.com * http://www.inspirel.com



^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2012-10-16  1:57 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-10-08  9:03 API design considerations - variable-length array in record type Maciej Sobczak
2012-10-08 11:13 ` Simon Wright
2012-10-08 11:29 ` Egil Høvik
2012-10-08 11:53   ` Maciej Sobczak
2012-10-08 14:37     ` Tero Koskinen
2012-10-09  2:02 ` Shark8
2012-10-09  5:16   ` Adam Beneschan
2012-10-09  5:45     ` Shark8
2012-10-09  5:42   ` Niklas Holsti
2012-10-09  3:10 ` Stephen Leake
2012-10-09  7:47   ` Maciej Sobczak

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox