comp.lang.ada
 help / color / mirror / Atom feed
* array from static predicate on enumerated type
@ 2021-03-12 20:49 Matt Borchers
  2021-03-12 21:22 ` Egil H H
                   ` (2 more replies)
  0 siblings, 3 replies; 38+ messages in thread
From: Matt Borchers @ 2021-03-12 20:49 UTC (permalink / raw)


Say, for example, I define a static predicate on a sub-type of an enumerated type, like:

type LETTERS is ( A, B, C, D, E, F, G, H, I , J, K );

subtype CURVED is LETTERS
    with Static_Predicate CURVED in B | C | D | G | J;

What I want is an array over CURVED (using CURVED as the index), but since attributes 'First and 'Last (and thus 'Range) is not allowed, this cannot be done.

Also, I am restricted in that the order of LETTERS cannot be rearranged.

Has anybody come up with a clever data structure to make sub-types with predicates easy and sensible for indexing (not iterating)?

I only need read access, so I defined an array over 1..5 and then created a function that takes a LETTERS type as input and outputs a POSITIVE.

type ARR(1..5) of BOOLEAN;

function ARR_IDX( u : CURVED ) return POSITIVE is
    (case u is when B => 1, when C => 2, when D => 3, when G => 4, when J => 5);

states : ARR := (others => FALSE);
b : BOOLEAN;

Then later,

b := states(arr_idx(G))

What I don't like about this solution is all of it.  If an element is added to CURVED then the range of ARR would have to be updated and the case expression for ARR_IDX also needs to be updated.  At least with a case statement or expression, the compiler can identify that part for me.

I assume that internally an enumerated type is represented by its position such that LETTERS.G'Pos = 6.  Perhaps CURVED.G'Pos could result in 3?  If programmers could define an array over CURVED'Range, then any mapping math could be done by the compiler that they would have to do manually anyway.  It seems reasonable that the compiler could take care of this for us effectively as I have done, but there would be the benefit of doing static checks at compilation.  Perhaps a language lawyer could explain why this can't be so when the sub-type mark is explicitly provided.

I guess what I'm saying is that it would be nice if LETTERS.G equaled CURVED.G semantically (because CURVED is a sub-type), but LETTERS.G'Pos would not necessarily equal to CURVED.G'Pos.  I'm sure this was discussed and that there is a rational reason why this can't be so but I haven't given it a lot of thought myself.  I'm not expecting the same kind of lookup speed from the index mapping that needs to be done.

Beyond this, as an alternate solution, I think some type of basic hash functionality built into the language syntax for enumerated types would be useful and would go a long way to make Ada more contemporary and adoptable.  Using the generic hash packages in Containers is overkill for my needs.

Matt

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

* Re: array from static predicate on enumerated type
  2021-03-12 20:49 array from static predicate on enumerated type Matt Borchers
@ 2021-03-12 21:22 ` Egil H H
  2021-03-12 22:16 ` Jeffrey R. Carter
  2021-03-12 22:41 ` Dmitry A. Kazakov
  2 siblings, 0 replies; 38+ messages in thread
From: Egil H H @ 2021-03-12 21:22 UTC (permalink / raw)


On Friday, March 12, 2021 at 9:49:29 PM UTC+1, Matt Borchers wrote:
> Say, for example, I define a static predicate on a sub-type of an enumerated type, like: 
> 
> type LETTERS is ( A, B, C, D, E, F, G, H, I , J, K ); 
> 
> subtype CURVED is LETTERS 
> with Static_Predicate CURVED in B | C | D | G | J; 
> 
> What I want is an array over CURVED (using CURVED as the index), but since attributes 'First and 'Last (and thus 'Range) is not allowed, this cannot be done. 
> 

You should read what the Rationale says about predicates (http://www.ada-auth.org/standards/12rat/html/Rat12-2-5.html),
especially the part about 'First_Valid and 'Last_Valid:

"These rules can also be illustrated by considering the dartboard. We might like to accumulate a count of the number of times each particular score has been achieved. So we might like to declare
type Hit_Count is array (Score) of Integer;   -- illegal
but sadly this would result in an array with holes and so is forbidden. However, we could declare an array from 1 to 60 and then initialize it with 0 for those components used for hits and –1 for the unused components. Of course, we ought not to repeat literals such as 1 and 60 because of potential maintenance problems. But, we can use new attributes First_Valid and Last_Valid thus
type Hit_Count is array (Score'First_Valid .. Score'Last_Valid) of Integer :=
       (Score => 0, others => –1);
which uses Score to indicate the used components. The attributes First_Valid and Last_Valid can be applied to any static subtype but are particularly useful with static predicates.
In detail, First_Valid returns the smallest valid value of the subtype. It takes any range and/or predicate into account whereas First only takes the range into account. Similarly Last_Valid returns the largest value. Incidentally, they are illegal on null subtypes (because null subtypes have no valid values at all)."

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

* Re: array from static predicate on enumerated type
  2021-03-12 20:49 array from static predicate on enumerated type Matt Borchers
  2021-03-12 21:22 ` Egil H H
@ 2021-03-12 22:16 ` Jeffrey R. Carter
  2021-03-12 22:41 ` Dmitry A. Kazakov
  2 siblings, 0 replies; 38+ messages in thread
From: Jeffrey R. Carter @ 2021-03-12 22:16 UTC (permalink / raw)


On 3/12/21 9:49 PM, Matt Borchers wrote:
> Say, for example, I define a static predicate on a sub-type of an enumerated type, like:
> 
> type LETTERS is ( A, B, C, D, E, F, G, H, I , J, K );
> 
> subtype CURVED is LETTERS
>      with Static_Predicate CURVED in B | C | D | G | J;
> 
> What I want is an array over CURVED (using CURVED as the index), but since attributes 'First and 'Last (and thus 'Range) is not allowed, this cannot be done.
> 
> Has anybody come up with a clever data structure to make sub-types with predicates easy and sensible for indexing (not iterating)?
> 
> I only need read access ...
It sounds as if you want a map, for which one of the map containers in the 
standard library would be appropriate.

-- 
Jeff Carter
"[I]t is foolish to polish a program beyond the
point of diminishing returns, but most programmers
do too little revision; they are satisfied too
early."
Elements of Programming Style
189

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

* Re: array from static predicate on enumerated type
  2021-03-12 20:49 array from static predicate on enumerated type Matt Borchers
  2021-03-12 21:22 ` Egil H H
  2021-03-12 22:16 ` Jeffrey R. Carter
@ 2021-03-12 22:41 ` Dmitry A. Kazakov
  2021-03-13  2:06   ` Matt Borchers
  2 siblings, 1 reply; 38+ messages in thread
From: Dmitry A. Kazakov @ 2021-03-12 22:41 UTC (permalink / raw)


On 2021-03-12 21:49, Matt Borchers wrote:
> Say, for example, I define a static predicate on a sub-type of an enumerated type, like:
> 
> type LETTERS is ( A, B, C, D, E, F, G, H, I , J, K );
> 
> subtype CURVED is LETTERS
>      with Static_Predicate CURVED in B | C | D | G | J;

Do not use this thing, because its semantic is basically a lie as it 
violates contracts of other operations of the type, like 'Succ.

Using formal speak, CURVED is not substitutable for LETTERS in too many 
cases to be any useful.

This applies to any arbitrary constraints you could impose using a 
predicate. They break things. Do not ever consider them as an option.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de

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

* Re: array from static predicate on enumerated type
  2021-03-12 22:41 ` Dmitry A. Kazakov
@ 2021-03-13  2:06   ` Matt Borchers
  2021-03-13  4:55     ` Randy Brukardt
  2021-03-13  8:04     ` Dmitry A. Kazakov
  0 siblings, 2 replies; 38+ messages in thread
From: Matt Borchers @ 2021-03-13  2:06 UTC (permalink / raw)


I pretty much agree with Dmitry on this.  The usefulness of this is very, very low without better support from the language itself.  However, Dmitry, if programmers should not consider a feature of a language as an option for a solution, then it begs the question on the quality of the language, quality of the compiler, or questions the abilities of caretakers of Ada.  Don't get me wrong, however, I think Ada is exceptional.

I thought I read that 'Pred and 'Succ do work as one would expect for the Predicated sub-type, but I did not try them as I did not need them.

I did read the entire rationale and 'First_Valid and 'Last_Valid would allow the programmer to create an array with a range that guarantees inclusion of all enumerated values of the statically predicated sub-type.  But, this leaves holes in the array as wasted memory.  My actual use case is hundreds of enumerated values and the sub-types have very few values each.  Think of a case like a Unicode table where you might want to classify characters into small non-contiguous groups and these character may be far apart from one another.

I do want a map or hash table, but in this case, I was hoping that Ada would handle the mapping for me such that I did not have to instantiate such a complexity for a simple example.  I was a bit surprised after discovering Static_Predicate that the Ada language syntax was essentially useless in dealing with it in a consistent way.

I like the idea of creating non-contiguous enumerated sub-types.  I've found that I often want to do it and must seriously consider design decisions like enumeration order that really should not be something that is that important to program design.  I think that if the language lets you define them, then the rest of the supporting syntax of the language should also support them even if there is a small penalty of a double look-up through a mapping table.

I had a simple case many years ago with Ada 95, I think, when I was implementing a checkers game.  I wanted an enumeration of 5 items for the piece the occupied a square.

type PIECE is ( EMPTY, RED, BLACK, RED_KING, BLACK_KING );
p : PIECE;

This was a nice order because I could use the language syntax to determine if piece was a King.

subtype KING is PIECE range RED_KING..BLACK_KING;
if p in KING then...

However, I had to write a function to determine if a piece was Red or Black and thus different calling syntax.  The other order option was:

type PIECE is ( EMPTY, RED, RED_KING, BLACK, BLACK_KING );

This order was nice because the language let me easily determine the Color of a piece.

subtype REDS is PIECE range RED..RED_KING;
subtype BLACKS is PIECE range BLACK..BLACK_KING;

if p in REDS then...

but I'd have to write a function to determine if a piece was a King and still different calling syntax.

Unfortunately, back then, the programmer couldn't have it both ways though it would've been very convenient.  It appears that Static_Predicate solves this problem because "in" is updated to work with the Predicate.  So if this works, why was it decided that the rest of the language syntax be inconsistent?  Surely a map table would have sufficed with a slight performance penalty, but for the sake of language consistency you let the programmer decide.  I can imagine an internally compiled map table would be much faster than the instantiation of the Map or Hash Container package.

Matt

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

* Re: array from static predicate on enumerated type
  2021-03-13  2:06   ` Matt Borchers
@ 2021-03-13  4:55     ` Randy Brukardt
  2021-03-15 14:16       ` Matt Borchers
  2021-03-13  8:04     ` Dmitry A. Kazakov
  1 sibling, 1 reply; 38+ messages in thread
From: Randy Brukardt @ 2021-03-13  4:55 UTC (permalink / raw)


"Matt Borchers" writes:


>I do want a map or hash table, but in this case, I was hoping that Ada 
>would handle the mapping for me ...

Ada is not some sort of magic wand. What you want requires a complex data 
structure, and using an array (as defined in Ada) for it is not practical 
(mainly because of the slice operation of which I've complained previously).

>...such that I did not have to instantiate such a complexity for a simple 
>example.

Ada was designed to provide high-quality (that is, fast) code. If you want a 
language with a high degree of abstraction -- Ada isn't it. And in such a 
language, you wouldn't have arrays (in the Ada sense) at all - you would 
only have maps and sequences.

And if you think a single instance is "such complexity", I have no idea what 
you would want -- a map instance is simpler to write than an array type 
declaration (and *much* simpler under the covers). Do you also never use 
Unchecked_Deallocation?? It's harder to instantiate than an Ordered_Map.

>I was a bit surprised after discovering Static_Predicate that the Ada 
>language
>syntax was essentially useless in dealing with it in a consistent way.

I was in favor of set constraints rather than Static_Predicates, mainly 
because of the value problems Dmitry commented on. But even those would have 
been illegal in arrays -- an array makes a lousy way to describe a map.

Anyway, subtypes with Static Predicates work for case statements, 
memberships, an for loops; they're only disallowed for arrays. I don't think 
anyone should be writing an array in a modern language (outside of 
interfacing to something outside of that language) - it's a mixed up data 
structure that only makes sense because of historical reasons.

>I like the idea of creating non-contiguous enumerated sub-types.

Static predicates do that fine. Just don't use them with obsolete data 
structures. :-)

                          Randy.


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

* Re: array from static predicate on enumerated type
  2021-03-13  2:06   ` Matt Borchers
  2021-03-13  4:55     ` Randy Brukardt
@ 2021-03-13  8:04     ` Dmitry A. Kazakov
  2021-03-15 14:11       ` Matt Borchers
  1 sibling, 1 reply; 38+ messages in thread
From: Dmitry A. Kazakov @ 2021-03-13  8:04 UTC (permalink / raw)


On 2021-03-13 03:06, Matt Borchers wrote:
> I pretty much agree with Dmitry on this.  The usefulness of this is very, very low without better support from the language itself.  However, Dmitry, if programmers should not consider a feature of a language as an option for a solution, then it begs the question on the quality of the language, quality of the compiler, or questions the abilities of caretakers of Ada.  Don't get me wrong, however, I think Ada is exceptional.

Subtyping is a very difficult problem. When a new type is created by 
constraining [*] this necessarily breaks things.

Ada 83 was very careful to limit that to ranges and discriminant values. 
That breaks, sure, but the damage is minor and can be controlled [by the 
programmer]. In contrast, an arbitrary constraint [as well as arbitrary 
extension] is like a carpet bombing.

My view, as a programmer, is that features of type algebra [which 
subtyping by constraining is] must be carefully limited to enable 
massive language support in detection of substitutablity issues at 
*compile* time. Features must be reasonably safe to use.

----------------------------------
*  Sorry, guys, Ada subtypes are types.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de

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

* Re: array from static predicate on enumerated type
  2021-03-13  8:04     ` Dmitry A. Kazakov
@ 2021-03-15 14:11       ` Matt Borchers
  2021-03-15 17:48         ` Shark8
  0 siblings, 1 reply; 38+ messages in thread
From: Matt Borchers @ 2021-03-15 14:11 UTC (permalink / raw)


So, what I'm taking away from this discussion is that instantiating a Map is pretty much the best option when using a sub-type with a Static_Predicate to map a parent value to a sub-type.  The simple example I gave here is a one-dimensional array and what I actually have implemented is a multi-dimensional array.  I will have to do tests on the performance of a map of a map of a map of a...

The IN and INDEX operations (in this case sub-type'Pos) are very closely related and so in my mind and it would seem that if IN works, then indexing should work as well given a mapping function.  A map function in this case, to me at least, is a black box that takes an Integer input and outputs an Integer.  Doesn't a memory array (contiguous memory, not Ada array, possibly using a binary search) do this very quickly and a function or some other data structure a bit slower?  It seems the compiler could create this for the programmer if necessary.  I was only trying to suggest that when a new syntax feature is added, that it is very surprising that it would break seemingly simple things like attributes and arrays.  If using Static_Predicate induces a run-time cost in some instances then so be it -- the programmer can decide if the cost is unreasonable.  That is the nature of all programming -- finding the ideal solution to a problem given the constraints of the system in which it operates be it speed, memory footprint, etc.  I would not argue that speed is always of utmost importance.

It seems like the Ada community is always chasing higher adoption and better recognition of the Ada language.  If the community truly wants this, then Ada needs to be accessible as a general purpose language with very few surprises.  I evangelize for Ada when I can but I am of the opinion that language rules like these only frustrate people when create seemingly inconsistent usability.  There may be a good technical reason to break the behavior, but in this example and in my opinion, the technical excuse is not good enough when there is a very simple solution that the programmer should not have to implement.  My 2 cents.

Matt

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

* Re: array from static predicate on enumerated type
  2021-03-13  4:55     ` Randy Brukardt
@ 2021-03-15 14:16       ` Matt Borchers
  2021-03-15 17:53         ` Shark8
  2021-03-16  6:58         ` Randy Brukardt
  0 siblings, 2 replies; 38+ messages in thread
From: Matt Borchers @ 2021-03-15 14:16 UTC (permalink / raw)


On Friday, March 12, 2021 at 11:55:54 PM UTC-5, Randy Brukardt wrote:
> Just don't use them with obsolete data structures. :-) 

I can't tell if you are you being facetious?  If not, can you give me some reasons on why you think arrays are obsolete data structures?  To me, they remain one of the basic building blocks of all programs.

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

* Re: array from static predicate on enumerated type
  2021-03-15 14:11       ` Matt Borchers
@ 2021-03-15 17:48         ` Shark8
  2021-03-15 20:25           ` Dmitry A. Kazakov
  0 siblings, 1 reply; 38+ messages in thread
From: Shark8 @ 2021-03-15 17:48 UTC (permalink / raw)


On Monday, March 15, 2021 at 8:11:24 AM UTC-6, Matt Borchers wrote:
> So, what I'm taking away from this discussion is that instantiating a Map is pretty much the best option when using a sub-type with a Static_Predicate to map a parent value to a sub-type. The simple example I gave here is a one-dimensional array and what I actually have implemented is a multi-dimensional array. I will have to do tests on the performance of a map of a map of a map of a... 

Map is the best thing to use, because that's what you're doing.
There's some fundamental problems with how Ada's multidimensional arrays are vs what your mental-model likely is: namely because they're contiguous on the underlying type you cannot have an array with indices at, say, 3,5,7 leaving out the non-primes of 3..7. HOWEVER, you could have a type (Steve, James, Dave) with the representation of  (Steve => 3, James => 5, Dave => 7), and functionally achieve the same thing. This is because the static-predicate is *NOT* a new type, but the addition of constraints upon the base. -- This sort of problem comes along when talking about slices: suppose you have a 5x5x5 three-dimensional array. Given that the memory locations must be contiguous this means that (0,5,5) and (1,0,0) are adjacent so having some slicing like (2..3,2..3,2..3) would involve some tedious math/mapping and also result in something that has non-contiguous memory. -- This was either overlooked in Ada83 or considered too complex to do correctly and efficiently, overly burdening compiler creators.

So, in Ada, there's no good choice for how to actually DO an array with gaps in the index: do you make arrays possibly non-contiguous and force a more complex model onto compilers, or do you eat up all the space where the missing indices would have gone, completely destroying what indexing on an Ada83..Ada2005 RANGE-constrained subtype would be expected to do? (The same "no good choice" is why 'Succ and 'Pred are disallowed.)

> The IN and INDEX operations (in this case sub-type'Pos) are very closely related and so in my mind and it would seem that if IN works, then indexing should work as well given a mapping function.

But Array *isn't* a map, though often it is substituted as one.
Array has further constraints, like the contiguous memory labeled above.
Just like Array is different than Function, and the two can sometimes be switched, so too is the relationship between Array and Map. (And also Function and Map...)

> A map function in this case, to me at least, is a black box that takes an Integer input and outputs an Integer. Doesn't a memory array (contiguous memory, not Ada array, possibly using a binary search) do this very quickly and a function or some other data structure a bit slower?

Ada's arrays ARE contiguous memory; so I'm not sure what you're trying to distinguish here.

>It seems the compiler could create this for the programmer if necessary. I was only trying to suggest that when a new syntax feature is added, that it is very surprising that it would break seemingly simple things like attributes and arrays.

I'm interested in language design and IMO syntax is the worst place to start with language-features, I find it far more productive to think semantics-first then "hammer out" the syntax.

> If using Static_Predicate induces a run-time cost in some instances then so be it -- the programmer can decide if the cost is unreasonable. That is the nature of all programming -- finding the ideal solution to a problem given the constraints of the system in which it operates be it speed, memory footprint, etc. I would not argue that speed is always of utmost importance.

Static_Predicate should, IMO, be a compile-time thing; the problems though, were about how these features should be handled at compile-time; arguably the dissalowance of 'succ, 'pred and such [to possibly include arrays] was a punt on the issue.

> It seems like the Ada community is always chasing higher adoption and better recognition of the Ada language. If the community truly wants this, then Ada needs to be accessible as a general purpose language with very few surprises.

Ada does have very few surprises; this is why it disallows the non-contiguous subtype indexing of the array.

> I evangelize for Ada when I can but I am of the opinion that language rules like these only frustrate people when create seemingly inconsistent usability. There may be a good technical reason to break the behavior, but in this example and in my opinion, the technical excuse is not good enough when there is a very simple solution that the programmer should not have to implement. My 2 cents. 

I think that in order to really fix the issue, we'd have to revisit the idea of multi-dimensional slices, as shown above, and *THAT* is a big can of worms.
It *is* doable, I think, but at far more time or energy at both the standards-level (the ARG's members) and at the implementation-level (the compiler writers).

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

* Re: array from static predicate on enumerated type
  2021-03-15 14:16       ` Matt Borchers
@ 2021-03-15 17:53         ` Shark8
  2021-03-16  6:58         ` Randy Brukardt
  1 sibling, 0 replies; 38+ messages in thread
From: Shark8 @ 2021-03-15 17:53 UTC (permalink / raw)


On Monday, March 15, 2021 at 8:16:58 AM UTC-6, Matt Borchers wrote:
> On Friday, March 12, 2021 at 11:55:54 PM UTC-5, Randy Brukardt wrote: 
> > Just don't use them with obsolete data structures. :-)
> I can't tell if you are you being facetious? If not, can you give me some reasons on why you think arrays are obsolete data structures? To me, they remain one of the basic building blocks of all programs.
They are a basic building-block, yes.
But they *AREN'T* maps, nor are they functions... despite the tendency to think of them as nails for your hammer (Array), this really isn't the case... and now that Ada has Ada.Containers.Indefinite_Ordered_Maps it really is an obsolete data-structure for mapping in most cases. (Exceptions exist for things like finite-state machines and virtual-machine instruction-sets where you're working with a uniform/near-uniform collection and/or things like embedded.)

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

* Re: array from static predicate on enumerated type
  2021-03-15 17:48         ` Shark8
@ 2021-03-15 20:25           ` Dmitry A. Kazakov
  2021-03-16 13:27             ` Shark8
  2022-03-16  0:38             ` Thomas
  0 siblings, 2 replies; 38+ messages in thread
From: Dmitry A. Kazakov @ 2021-03-15 20:25 UTC (permalink / raw)


On 2021-03-15 18:48, Shark8 wrote:

> So, in Ada, there's no good choice for how to actually DO an array with gaps in the index:

That applies to all containers. The problem is mapping the key to a 
dense position when the key is not dense or might be unordered.

There is no gaps in positions.

> But Array *isn't* a map, though often it is substituted as one.

Of course it is, per definition of mapping. f : key -> element.

> Array has further constraints, like the contiguous memory labeled above.

No. The constraint here is a dense index. That is not specific to a 
general map or an array. It is a fundamental property of the set of keys 
being a convex set. Convex ensures certain useful mathematical 
properties invariant to the representation of the mapping. In 
particular, it gives a way to enumerate elements. If you want to 
enumerate non-convex keys of a map you have a problem. As the OP just 
encountered.

Arbitrary predicate kills convex, so the problem. Not array. A map would 
have just same problem: a map of LETTERS is in general not substitutable 
for a map of CURVED_LETTERS.

> Ada's arrays ARE contiguous memory; so I'm not sure what you're trying to distinguish here.

No. A dense index allows contiguous representation, but it does not 
require it.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de

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

* Re: array from static predicate on enumerated type
  2021-03-15 14:16       ` Matt Borchers
  2021-03-15 17:53         ` Shark8
@ 2021-03-16  6:58         ` Randy Brukardt
  1 sibling, 0 replies; 38+ messages in thread
From: Randy Brukardt @ 2021-03-16  6:58 UTC (permalink / raw)


"Matt Borchers" <mattborchers@gmail.com> wrote in message 
news:8f7d1d02-c5f0-4ed5-8003-09c6f467d63cn@googlegroups.com...
> On Friday, March 12, 2021 at 11:55:54 PM UTC-5, Randy Brukardt wrote:
>> Just don't use them with obsolete data structures. :-)
>
> I can't tell if you are you being facetious?  If not, can you give me some 
> reasons on
>why you think arrays are obsolete data structures?  To me, they remain one 
>of the
>basic building blocks of all programs.

If you're talking *representation*, then surely arrays are the root of 
everything. But a general purpose programming language should hide 
representation issues as much as possible. For most uses, how a data 
structure is implemented is irrelevant; you want to ask for the fundamental 
data.structure that you need and let the implementation chose the best 
implementation to meet your needs.

And an array is not a fundamental data structure: those are bags and 
sequences and maps (and trees and graphs, but those aren't relevant here). 
Arrays have features of all of these, as well as some others -- they're not 
a fundamental data structure at all.

Moreover, Ada in particular merges in additional features that have little 
to do with data structures, and end up with a mixed up mess where one gets 
surprises from super-null arrays and arrays whose lower isn't 'First and 
holey arrays and other such nonsense.

For instance, the primary reason that Ada cannot have holey arrays is 
because of the slice (mis)feature, in particular because a slice can be 
assigned and (worse) passed as an in out parameter. If one has holey arrays, 
one also would expect to have holey slices (else the language would be quite 
inconsistent). But implementing a holey slice is problematic. For parameter 
passing, pretty much the only way to implement that would be to provide a 
call-back subprogram with every parameter that knows how to write each index 
of the slice. But that would be a classic distributed overhead -- it would 
be incurred for *every* array parameter since one can always create a holey 
slice of an array -- even of a type that is not itself holey. That would 
make passing strings and other arrays *much* more expensive.

Consider the following (illegal) example:

     subtype Trouble is Positive with Static_Predicate => Trouble in 1 | 2 | 
8 | 10;

     Message : String := "Barb Judge!"

     Put_Line (Message(Trouble)); -- Illegal.

If this was legal, the Put_Line would have to output "Bad!". Now, you can 
probably think of ways to implement such a slice, but they'd require copying 
it at the call site. That would work for Put_Line of a few characters, but 
it could be too expensive for larger arrays. Moreover, consider 
Ada.Strings.Overwrite:

     Ada.Strings.Overwrite (Message(Trouble), Position => 2, "ooo");

This would be asking the compiler to somehow figure out that it needs to 
write the 2nd, 8th, and 10th characters of Message. And still be able to 
handle the more normal kinds of slices as well.

And then (if you want a completely consistent language), remember that array 
components can be by-reference types, that are not allowed to be copied when 
passed as parameters.

The point is that holey arrays are a massive can of worms, and its 
impossible to have a consistent language if discontiguous subtypes exist. 
Tucker likes to say that sometimes language design is like a bump under a 
carpet -- you can move the bump around, but you can't get rid of it without 
ripping out the carpet and starting over (with a different language design). 
This is one of those cases.

                                      Randy.


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

* Re: array from static predicate on enumerated type
  2021-03-15 20:25           ` Dmitry A. Kazakov
@ 2021-03-16 13:27             ` Shark8
  2021-03-16 14:25               ` Dmitry A. Kazakov
  2022-03-16  0:38             ` Thomas
  1 sibling, 1 reply; 38+ messages in thread
From: Shark8 @ 2021-03-16 13:27 UTC (permalink / raw)


On Monday, March 15, 2021 at 2:25:11 PM UTC-6, Dmitry A. Kazakov wrote:
> On 2021-03-15 18:48, Shark8 wrote: 
> 
> > So, in Ada, there's no good choice for how to actually DO an array with gaps in the index:
> That applies to all containers. The problem is mapping the key to a 
> dense position when the key is not dense or might be unordered. 
> 
> There is no gaps in positions.
> > But Array *isn't* a map, though often it is substituted as one.
> Of course it is, per definition of mapping. f : key -> element.

I think you misunderstand, I said it has further constraints.
That definition of map doesn't care how the order of 'key' is, Ada's array does.
That definition doesn't care if 'Key' is a discriminated-type, or constrained, or limited, Ada's array flat-out doesn't work without its 'key' (Index) being discrete, I don't know about limited as I haven't tried it.
That definition doesn't care how the resultant 'element' is stored, Ada's array requires that they all be in contiguous memory.
So, no, Array is not "a map" except when your problem space allows you to comply with [or ignore] all of those constraints and _then_ you may use it as one... which is exactly what I said above.

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

* Re: array from static predicate on enumerated type
  2021-03-16 13:27             ` Shark8
@ 2021-03-16 14:25               ` Dmitry A. Kazakov
  2021-03-17  4:05                 ` Matt Borchers
  0 siblings, 1 reply; 38+ messages in thread
From: Dmitry A. Kazakov @ 2021-03-16 14:25 UTC (permalink / raw)


On 2021-03-16 14:27, Shark8 wrote:
> On Monday, March 15, 2021 at 2:25:11 PM UTC-6, Dmitry A. Kazakov wrote:
>> On 2021-03-15 18:48, Shark8 wrote:
>>
>>> So, in Ada, there's no good choice for how to actually DO an array with gaps in the index:
>> That applies to all containers. The problem is mapping the key to a
>> dense position when the key is not dense or might be unordered.
>>
>> There is no gaps in positions.
>>> But Array *isn't* a map, though often it is substituted as one.
>> Of course it is, per definition of mapping. f : key -> element.
> 
> I think you misunderstand, I said it has further constraints.
> That definition of map doesn't care how the order of 'key' is, Ada's array does.

No, that is apples and oranges. You compare unconstrained map with 
constrained array. The OP wanted to constrain LETTER to CURVED_LETTER 
with the corresponding effect on the container.

You cannot do that with either arrays or a predefined vector container. 
Ada does not have mechanism to do that on the level of a type.

You can do that on the level individual values. That is a dynamic 
constraint, e.g. checking the key or index before using it.

> That definition doesn't care if 'Key' is a discriminated-type, or constrained, or limited, Ada's array flat-out doesn't work without its 'key' (Index) being discrete, I don't know about limited as I haven't tried it.

Try this:

with Ada.Text_IO; use Ada.Text_IO;

procedure Test is
    type CURVED is ('B', 'C', 'D', 'G', 'J');
    A : array (CURVED) of Integer;
begin
    Put_Line (Integer'Image (A'Length));
end Test;

It will print:

  5

Again, the problem is not arrays. The problem is lack of 
substitutability of things built upon constrained keys of a map.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de

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

* Re: array from static predicate on enumerated type
  2021-03-16 14:25               ` Dmitry A. Kazakov
@ 2021-03-17  4:05                 ` Matt Borchers
  2021-03-17  7:08                   ` Dmitry A. Kazakov
  2021-03-17 15:08                   ` Shark8
  0 siblings, 2 replies; 38+ messages in thread
From: Matt Borchers @ 2021-03-17  4:05 UTC (permalink / raw)


So, I understand why holey arrays are problematic and I'm not asking for holey arrays here.  I was looking for elegant solution around the fact that Ada intentionally does not provide a reasonable answer to 'First, 'Last, etc. when used on enumerated sub-types with a Predicate.  In my cases, I have a lot of small (less than 5 rows and columns) multi-dimensional static data.  It appears instantiating a Map and populating it at program start-up is the recommended solution.  However, it sure seems to me that a static constant array of data is ideal because loading the Map cannot be guaranteed correct by the compiler whereas a table would be.

It feels like an unfinished addition or incomplete feature to actively prevent 'First, 'Last, etc. from returning something reasonable about the sub-type in question.  Return SOMETHING, even if it pertains to the parent type, and let the programmer decide how it can be useful to them.  Using my LETTERS and CURVED_LETTERS example, I still don't see why the following would be problematic:

A <= LETTERS'First
K <= LETTERS'Last
11 <= LETTERS'Length
1 <= LETTERS'Pos(B)
10 <= LETTERS'Pos(J)

B <= CURVED_LETTERS'First
J <= CURVED_LETTERS'Last
5 <= CURVED_LETTERS'Length
0 <= CURVED_LETTERS'Pos(B)
4 <= CURVED_LETTERS'Pos(J)

I didn't address 'Succ and 'Pred, but these also seem reasonable.

Again, I don't know the inner workings of the compiler, but these responses (above) for CURVED_LETTERS seem like reasonable values related to the sub-type that the compiler could handle easily allowing programmers who might want to write:

type ARR(CURVED_LETTERS) of BOOLEAN;

but for strict legality purposes have to suffice with:

type ARR(CURVED_LETTERS'Pos(CURVED_LETTERS'First)..CURVED_LETTERS'Pos(CURVED_LETTERS'Last)) of BOOLEAN;

It sure is ugly and some of you will surely yell, but we can do this now with a regular enumerated type and so it should be consistent for an enumerated sub-type.  At least creating an array from this type can be do-able with access to these attributes and it can also be verified correct by the compiler.

Matt

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

* Re: array from static predicate on enumerated type
  2021-03-17  4:05                 ` Matt Borchers
@ 2021-03-17  7:08                   ` Dmitry A. Kazakov
  2021-03-17 18:44                     ` Matt Borchers
  2021-03-17 15:08                   ` Shark8
  1 sibling, 1 reply; 38+ messages in thread
From: Dmitry A. Kazakov @ 2021-03-17  7:08 UTC (permalink / raw)


On 2021-03-17 05:05, Matt Borchers wrote:

> It feels like an unfinished addition or incomplete feature to actively prevent 'First, 'Last, etc. from returning something reasonable about the sub-type in question.  Return SOMETHING, even if it pertains to the parent type, and let the programmer decide how it can be useful to them.  Using my LETTERS and CURVED_LETTERS example, I still don't see why the following would be problematic:
> 
> A <= LETTERS'First
> K <= LETTERS'Last
> 11 <= LETTERS'Length
> 1 <= LETTERS'Pos(B)
> 10 <= LETTERS'Pos(J)
> 
> B <= CURVED_LETTERS'First
> J <= CURVED_LETTERS'Last
> 5 <= CURVED_LETTERS'Length
> 0 <= CURVED_LETTERS'Pos(B)
> 4 <= CURVED_LETTERS'Pos(J)
> 
> I didn't address 'Succ and 'Pred, but these also seem reasonable.

Consider this:

    function Count (A : LETTERS) return Natural is
       Count : Natural := 0;
    begin
       for I in A'First..A'Last loop
          Count := Count + 1;
       end loop;
    end Count;

How this supposed to be compiled? Note that CURVED_LETTERS is a subtype 
of LETTERS. So you can pass CURVED_LETTERS to Count.

Count cannot use LETTERS'First, 'Succ etc in its body, they might be 
overridden they are like in CURVED_LETTERS.

In short it must either dispatch on the actual argument or else the 
argument must be converted to LETTERS in a way that LETTERS operations 
would yield the correct result.

Neither is possible.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de

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

* Re: array from static predicate on enumerated type
  2021-03-17  4:05                 ` Matt Borchers
  2021-03-17  7:08                   ` Dmitry A. Kazakov
@ 2021-03-17 15:08                   ` Shark8
  2021-03-17 19:08                     ` Matt Borchers
  1 sibling, 1 reply; 38+ messages in thread
From: Shark8 @ 2021-03-17 15:08 UTC (permalink / raw)


On Tuesday, March 16, 2021 at 10:05:31 PM UTC-6, Matt Borchers wrote:
> So, I understand why holey arrays are problematic and I'm not asking for holey arrays here.
> I was looking for elegant solution around the fact that Ada intentionally does not provide a reasonable answer to 'First, 'Last, etc. when used on enumerated sub-types with a Predicate.
As I attempted to explain up-thread, the issue you are looking at *IS* the issue with holey arrays.

> In my cases, I have a lot of small (less than 5 rows and columns) multi-dimensional static data. It appears instantiating a Map and populating it at program start-up is the recommended solution. However, it sure seems to me that a static constant array of data is ideal because loading the Map cannot be guaranteed correct by the compiler whereas a table would be.
Since you want holes, you could use the abstraction to your benefit:

    Subtype Letters is Character range 'A'..'Z';
    Subtype Curved  is Letters
      with Static_Predicate => Curved in 'B' | 'C' | 'D' | 'G' | 'J';
    Type Curved_2 is ('B', 'C', 'D', 'G', 'J')
       with Size => Letters'Size;
    For Curved_2 use (
       'B' => Character'Pos( 'B' ),
       'C' => Character'Pos( 'C' ),
       'D' => Character'Pos( 'D' ),
       'G' => Character'Pos( 'G' ),
       'J' => Character'Pos( 'J' )
      );

    --------------
    --Private/Body part
    Actual_Map : Constant Array (Curved_2) of Integer;

    -- In Body
    Function Do_Map(C : Character) return Integer is
        Function Convert is new Ada.Unchecked_Conversion(
           Source => Character,
           Target => Curved_2
          );
    Begin
        Return (if C in Curved then Actual_Map(Convert(C))
                     --ELSIF other_condition then Another_Map(Another_Convert(C))
                     else raise Constraint_Error with "Invalid Index: '"& C &"'.");
    End Do_Map;

An array might be "ideal", but only if the thing you're indexing by is contiguous, otherwise you literally ARE asking for a slice with holes.
Another option you might have is this:

    Table : Array (Character range 'A'..'Z') of Integer:= (Others => 12);
    K : Integer := 7
      with Address => Table('K')'Address;
> 
> It feels like an unfinished addition or incomplete feature to actively prevent 'First, 'Last, etc. from returning something reasonable about the sub-type in question. Return SOMETHING, even if it pertains to the parent type, and let the programmer decide how it can be useful to them. Using my LETTERS and CURVED_LETTERS example, I still don't see why the following would be problematic: 
> 
> A <= LETTERS'First 
> K <= LETTERS'Last 
> 11 <= LETTERS'Length 
> 1 <= LETTERS'Pos(B) 
> 10 <= LETTERS'Pos(J) 
> 
> B <= CURVED_LETTERS'First 
> J <= CURVED_LETTERS'Last 
> 5 <= CURVED_LETTERS'Length 
> 0 <= CURVED_LETTERS'Pos(B) 
> 4 <= CURVED_LETTERS'Pos(J) 
> 
> I didn't address 'Succ and 'Pred, but these also seem reasonable.
Read my post upthread, then Randy's, and you'll see that the absence of these features is tied to the holy-array/-slice problem.
Think about how difficult it would be to define multidimensional slices, which by their nature must be holey, and in a manner conducive to "efficiency" (in the C programmer's meaning).

> Again, I don't know the inner workings of the compiler, but these responses (above) for CURVED_LETTERS seem like reasonable values related to the sub-type that the compiler could handle easily allowing programmers who might want to write: 
> 
> type ARR(CURVED_LETTERS) of BOOLEAN; 
> 
> but for strict legality purposes have to suffice with: 
> 
> type ARR(CURVED_LETTERS'Pos(CURVED_LETTERS'First)..CURVED_LETTERS'Pos(CURVED_LETTERS'Last)) of BOOLEAN; 
> 
> It sure is ugly and some of you will surely yell, but we can do this now with a regular enumerated type and so it should be consistent for an enumerated sub-type. At least creating an array from this type can be do-able with access to these attributes and it can also be verified correct by the compiler.
Do you want such an array to hold 256 bits? One for each character with a CONSTRAINT_ERROR on bad indexing? (Meaning some sort of automatically generated function that is invisibly integrated into this object.)
Or are you wanting an array with holey indexes, collapsed spacewise, so that it's only 5 bits?
These are the questions which must be answered to even start to consider the issues at hand.

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

* Re: array from static predicate on enumerated type
  2021-03-17  7:08                   ` Dmitry A. Kazakov
@ 2021-03-17 18:44                     ` Matt Borchers
  2021-03-17 19:41                       ` Dmitry A. Kazakov
  0 siblings, 1 reply; 38+ messages in thread
From: Matt Borchers @ 2021-03-17 18:44 UTC (permalink / raw)


Dimitry,
I understand what you are saying.  But, we don't pass CURVED_LETTERS to Count, we pass a value of CURVED_LETTERS to Count.  In my mind, the value should then assumed to be of the type as declared in the parameter to Count -- which is LETTERS in your example.  Obviously any value of CURVED_LETTERS is actually a value of LETTERS.  This is how Ada treats this case now.

To your question, I would say that the compiler treat the argument for A : LETTERS as a member of LETTERS such that A'First = 0 and A'Last = 11 even if a value of CURVED_LETTERS was passed in (as it does now).

Runtime dispatching wouldn't work obviously.  It is also not legal to write two Count routines, one with A : LETTERS and the other with A : CURVED_LETTERS within the same scope.

If Count was written with a parameter A: CURVED_LETTERS then it can be assumed that A is a member of CURVED_LETTERS and A'First = 0 and A'Last = 4 and it would be up to the programmer to know that the sub-type Predicate has introduced additional constraints.  However, this would be different from all prior behavior of sub-types where the result of 'Pos (and the like) on both the enumerated type and the sub-type produce the same result.  In this sense, the introduction of the Predicate would alter the behavior and thus could, in some sense, be considered inconsistent.  I now see that implementing this could cause run-time errors in existing code that used 'Pos and the rest on a sub-type to which a Predicate was added.

This discussion is helpful as I am now understanding that what I'm thinking is perhaps also equally inconsistent.  My current thinking is that I preferred a value of a sub-type to continue to be comparable (with =) to a value of the parent type, but I also wanted it to behave like a full-fledged type when using its attributes.  Nevertheless, it still feels like an unfinished feature as it is now.

Regards,
Matt


On Wednesday, March 17, 2021 at 3:08:38 AM UTC-4, Dmitry A. Kazakov wrote:
> On 2021-03-17 05:05, Matt Borchers wrote: 
> 
> > It feels like an unfinished addition or incomplete feature to actively prevent 'First, 'Last, etc. from returning something reasonable about the sub-type in question. Return SOMETHING, even if it pertains to the parent type, and let the programmer decide how it can be useful to them. Using my LETTERS and CURVED_LETTERS example, I still don't see why the following would be problematic: 
> > 
> > A <= LETTERS'First 
> > K <= LETTERS'Last 
> > 11 <= LETTERS'Length 
> > 1 <= LETTERS'Pos(B) 
> > 10 <= LETTERS'Pos(J) 
> > 
> > B <= CURVED_LETTERS'First 
> > J <= CURVED_LETTERS'Last 
> > 5 <= CURVED_LETTERS'Length 
> > 0 <= CURVED_LETTERS'Pos(B) 
> > 4 <= CURVED_LETTERS'Pos(J) 
> > 
> > I didn't address 'Succ and 'Pred, but these also seem reasonable.
> Consider this: 
> 
> function Count (A : LETTERS) return Natural is 
> Count : Natural := 0; 
> begin 
> for I in A'First..A'Last loop 
> Count := Count + 1; 
> end loop; 
> end Count; 
> 
> How this supposed to be compiled? Note that CURVED_LETTERS is a subtype 
> of LETTERS. So you can pass CURVED_LETTERS to Count. 
> 
> Count cannot use LETTERS'First, 'Succ etc in its body, they might be 
> overridden they are like in CURVED_LETTERS. 
> 
> In short it must either dispatch on the actual argument or else the 
> argument must be converted to LETTERS in a way that LETTERS operations 
> would yield the correct result. 
> 
> Neither is possible.
> -- 
> Regards, 
> Dmitry A. Kazakov 
> http://www.dmitry-kazakov.de

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

* Re: array from static predicate on enumerated type
  2021-03-17 15:08                   ` Shark8
@ 2021-03-17 19:08                     ` Matt Borchers
  2021-03-17 20:41                       ` Shark8
  0 siblings, 1 reply; 38+ messages in thread
From: Matt Borchers @ 2021-03-17 19:08 UTC (permalink / raw)


Shark8,

I have read all posts in this thread and I'm pretty sure I understand the holey array and slice problem and I do not want holey arrays.  Your example is interesting but it adds a lot of complexity.  However, that could obviously be abstracted away.

My comment was not a request but a question just as you posed:  why "some sort of automatically generated function that is invisibly integrated into this object" to do the mapping is not possible for the implementations of the 'Pos, 'First, 'Last, etc. attributes.  "This object" being an enumerated sub-type with a Static_Predicate.

I was originally trying/hoping to create a collapsed array needing only the minimal memory required to support the Static_Predicate sub-type as the index.  In my previous post I began to realize that solving this inconsistency just might result in a different inconsistency and I would not be in favor of a solution like that.

Regards,
Matt

On Wednesday, March 17, 2021 at 11:08:58 AM UTC-4, Shark8 wrote:
> Do you want such an array to hold 256 bits? One for each character with a CONSTRAINT_ERROR on bad indexing? (Meaning some sort of automatically generated function that is invisibly integrated into this object.) 
> Or are you wanting an array with holey indexes, collapsed spacewise, so that it's only 5 bits? 
> These are the questions which must be answered to even start to consider the issues at hand.

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

* Re: array from static predicate on enumerated type
  2021-03-17 18:44                     ` Matt Borchers
@ 2021-03-17 19:41                       ` Dmitry A. Kazakov
  2021-03-18  1:30                         ` Matt Borchers
  0 siblings, 1 reply; 38+ messages in thread
From: Dmitry A. Kazakov @ 2021-03-17 19:41 UTC (permalink / raw)


On 2021-03-17 19:44, Matt Borchers wrote:

> I understand what you are saying.  But, we don't pass CURVED_LETTERS to Count, we pass a value of CURVED_LETTERS to Count.

You cannot pass that value. It is type violation as type operations and 
the values set are different. [Predicate does not create a new type, it 
only breaks the old one.] So the value must be converted to the expected 
type (the conversion can be null) or else the operation must be 
overridden or inherited with type conversion or else be class-wide and 
then the value must be converted to a class-wide value.

> In my mind, the value should then assumed to be of the type as declared in the parameter to Count -- which is LETTERS in your example.  Obviously any value of CURVED_LETTERS is actually a value of LETTERS.  This is how Ada treats this case now.

Yes and it is no different to how Ada treats arrays of CURVED_LETTERS 
right now.

> To your question, I would say that the compiler treat the argument for A : LETTERS as a member of LETTERS such that A'First = 0 and A'Last = 11 even if a value of CURVED_LETTERS was passed in (as it does now).

Then why you expect a different behavior from an array of CURVED_LETTERS?

> This discussion is helpful as I am now understanding that what I'm thinking is perhaps also equally inconsistent.  My current thinking is that I preferred a value of a sub-type to continue to be comparable (with =) to a value of the parent type, but I also wanted it to behave like a full-fledged type when using its attributes.

You cannot have it both ways.

> Nevertheless, it still feels like an unfinished feature as it is now.

It is not unfinished. It is irreparably broken.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de

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

* Re: array from static predicate on enumerated type
  2021-03-17 19:08                     ` Matt Borchers
@ 2021-03-17 20:41                       ` Shark8
  2021-03-18  1:04                         ` Matt Borchers
  0 siblings, 1 reply; 38+ messages in thread
From: Shark8 @ 2021-03-17 20:41 UTC (permalink / raw)


On Wednesday, March 17, 2021 at 1:08:36 PM UTC-6, Matt Borchers wrote:
> Shark8, 
> 
> I have read all posts in this thread and I'm pretty sure I understand the holey array and slice problem and I do not want holey arrays. Your example is interesting but it adds a lot of complexity. However, that could obviously be abstracted away. 
> 
> My comment was not a request but a question just as you posed: why "some sort of automatically generated function that is invisibly integrated into this object" to do the mapping is not possible for the implementations of the 'Pos, 'First, 'Last, etc. attributes. "This object" being an enumerated sub-type with a Static_Predicate.
Because it's undefined, and the operations prohibited.
You're jumping from "Let's have a continuous function" to "we can define division by zero as something useful."
And you can... but not automatically, and when someone brings up the function F(x) = 1/x and says "well, we have to resolve this issue, as the limit to zero comes from negative it becomes -Infinity, but from positive it becomes positive Infinity."

The same thing is happening here: you're saying that 'pos, 'succ, etc could be defined -- and that's true -- but you're ignoring the underlying problems.
Having something like "P : Constant Array (Primes) of Natural;" could indeed be useful, but what would P(12) be? If Primes'Succ(11) = 13, then what is Primes'Pred(2)? [This latter is a good example because in String manipulation, the 0 value is used for indicating things like "not-found", and we absolutely can say SUBTYPE INDEXER IS VALUE'First..INDEX(VALUE, "NOEXIST"); and have it be sensible when INDEXER is the null-range.]

> 
> I was originally trying/hoping to create a collapsed array needing only the minimal memory required to support the Static_Predicate sub-type as the index. In my previous post I began to realize that solving this inconsistency just might result in a different inconsistency and I would not be in favor of a solution like that.
Use type-system and/or PRIVATE- & implementation-parts.

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

* Re: array from static predicate on enumerated type
  2021-03-17 20:41                       ` Shark8
@ 2021-03-18  1:04                         ` Matt Borchers
  2021-03-18 14:25                           ` Shark8
  0 siblings, 1 reply; 38+ messages in thread
From: Matt Borchers @ 2021-03-18  1:04 UTC (permalink / raw)


On Wednesday, March 17, 2021 at 4:41:17 PM UTC-4, Shark8 wrote:

> Because it's undefined, and the operations prohibited. 
> You're jumping from "Let's have a continuous function" to "we can define division by zero as something useful." 
> And you can... but not automatically, and when someone brings up the function F(x) = 1/x and says "well, we have to resolve this issue, as the limit to zero comes from negative it becomes -Infinity, but from positive it becomes positive Infinity." 

This sounds like a strawman argument.  You're saying it can't work because it doesn't work.  I have a valid 1 to 1 mapping of values and that is the purest definition of a function.  It is up to the programmer to define what the mapping is.  Static_Predicate is only defining the list of valid inputs (and the order) to whatever I choose my mapping implementation to be.  A programmatic function does not need to be continuous and nor can it be when it is defined on an enumerated type.  The parent enumeration has an order specified in the program text and the sub-type also has an order.

> The same thing is happening here: you're saying that 'pos, 'succ, etc could be defined -- and that's true -- but you're ignoring the underlying problems. 
> Having something like "P : Constant Array (Primes) of Natural;" could indeed be useful, but what would P(12) be? If Primes'Succ(11) = 13, then what is Primes'Pred(2)? [This latter is a good example because in String manipulation, the 0 value is used for indicating things like "not-found", and we absolutely can say SUBTYPE INDEXER IS VALUE'First..INDEX(VALUE, "NOEXIST"); and have it be sensible when INDEXER is the null-range.]

Assuming,
subtype Primes is Natural with Static_Predicate Primes in 2|3|5|7|9|11|13...;
P : Constant Array (Primes) of Natural;

What I would expect is that P(12) would be an illegal access because 12 is not a valid value of Primes thus cannot be an index and a constraint error or out-of-range error would be thrown.  Wouldn't this just involve the compiler to insert "if x not in primes then raise..." if constraint checking is enabled?  Otherwise you have an erroneous program.  Similarly, Primes'Succ(12) is also illegal.  Primes'Pred(2) also illegal because there is no prime before 2 so presumably you have defined your Static_Predicate to enumerate the primes with 2 listed first.  A similar illegal invocation would be a function F defined with an argument for Primes, like "function F( p : Primes ) return Natural is" and you called F(12).

Regards,
Matt

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

* Re: array from static predicate on enumerated type
  2021-03-17 19:41                       ` Dmitry A. Kazakov
@ 2021-03-18  1:30                         ` Matt Borchers
  2021-03-18  8:20                           ` Dmitry A. Kazakov
  2021-03-18 10:15                           ` Niklas Holsti
  0 siblings, 2 replies; 38+ messages in thread
From: Matt Borchers @ 2021-03-18  1:30 UTC (permalink / raw)


On Wednesday, March 17, 2021 at 3:41:16 PM UTC-4, Dmitry A. Kazakov wrote:
> On 2021-03-17 19:44, Matt Borchers wrote: 
> 
> > I understand what you are saying. But, we don't pass CURVED_LETTERS to Count, we pass a value of CURVED_LETTERS to Count.
> You cannot pass that value. It is type violation as type operations and 
> the values set are different. [Predicate does not create a new type, it 
> only breaks the old one.] So the value must be converted to the expected 
> type (the conversion can be null) or else the operation must be 
> overridden or inherited with type conversion or else be class-wide and 
> then the value must be converted to a class-wide value.

So what I think I hear you saying is that values of a sub-types with a static predicate are not valid values of the parent without explicit type conversion -- like values of Natural are valid values of Integer without explicit type conversion.  Is that correct?  So, I certainly would expect B to be valid without a cast when assigned to a variable of type LETTERS or CURVED_LETTERS.  I need to verify this.

> > In my mind, the value should then assumed to be of the type as declared in the parameter to Count -- which is LETTERS in your example. Obviously any value of CURVED_LETTERS is actually a value of LETTERS. This is how Ada treats this case now.
> Yes and it is no different to how Ada treats arrays of CURVED_LETTERS 
> right now.

Given:
subtype HEX_LETTERS is LETTERS range A..F;

When I create an array over Natural Ada does not create an array over Integer.  So I would expect that WITHOUT Static_Predicate, Ada would not create an array over the parent enumeration LETTERS when defined on the sub-type HEX_LETTERS.  So, this was my expectation for CURVED_LETTERS with the Static_Predicate before I read the rules.

> > To your question, I would say that the compiler treat the argument for A : LETTERS as a member of LETTERS such that A'First = 0 and A'Last = 11 even if a value of CURVED_LETTERS was passed in (as it does now).
> Then why you expect a different behavior from an array of CURVED_LETTERS?

I think you misunderstood me.  Given the following,
function L_POS( x : LETTERS ) return NATURAL is (LETTERS'Pos(x));
and
function CL_POS( x : CURVED_LETTERS ) return NATURAL is (CURVED_LETTERS'Pos(x));

I would have expected the following results:
1 <= l_pos(B)
0 <= cl_pos(B)
4 <= l_pos(E)
exception <= cl_pos(E)

> > This discussion is helpful as I am now understanding that what I'm thinking is perhaps also equally inconsistent. My current thinking is that I preferred a value of a sub-type to continue to be comparable (with =) to a value of the parent type, but I also wanted it to behave like a full-fledged type when using its attributes.
> You cannot have it both ways.

Of course, and I'm not requesting what my expectations were.  But, I'm still trying to understand why it can't be done because, after all, if a programmer can write it, then a compiler could code-generate it.

> > Nevertheless, it still feels like an unfinished feature as it is now.
> It is not unfinished. It is irreparably broken.

And this does not make for good advertising for Ada.

Regards,
Matt

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

* Re: array from static predicate on enumerated type
  2021-03-18  1:30                         ` Matt Borchers
@ 2021-03-18  8:20                           ` Dmitry A. Kazakov
  2021-03-19  0:10                             ` Matt Borchers
  2021-03-18 10:15                           ` Niklas Holsti
  1 sibling, 1 reply; 38+ messages in thread
From: Dmitry A. Kazakov @ 2021-03-18  8:20 UTC (permalink / raw)


On 2021-03-18 02:30, Matt Borchers wrote:
> On Wednesday, March 17, 2021 at 3:41:16 PM UTC-4, Dmitry A. Kazakov wrote:
>> On 2021-03-17 19:44, Matt Borchers wrote:
>>
>>> I understand what you are saying. But, we don't pass CURVED_LETTERS to Count, we pass a value of CURVED_LETTERS to Count.
>> You cannot pass that value. It is type violation as type operations and
>> the values set are different. [Predicate does not create a new type, it
>> only breaks the old one.] So the value must be converted to the expected
>> type (the conversion can be null) or else the operation must be
>> overridden or inherited with type conversion or else be class-wide and
>> then the value must be converted to a class-wide value.
> 
> So what I think I hear you saying is that values of a sub-types with a static predicate are not valid values of the parent without explicit type conversion -- like values of Natural are valid values of Integer without explicit type conversion.

Each natural value has a corresponding integer value and IF the compiler 
uses same representation for both THEN conversion can be identity 
function. The backward conversion is also identity + constraint check.

>>> In my mind, the value should then assumed to be of the type as declared in the parameter to Count -- which is LETTERS in your example. Obviously any value of CURVED_LETTERS is actually a value of LETTERS. This is how Ada treats this case now.

No. A value may have only one type. Ada treats subtypes as same type, 
but the fact is that a subtype is a distinct type if the behavior is 
different, and it is. So a natural value is not an integer value, it 
only has a corresponding integer value. You can ignore that distinction 
almost everywhere but it is still there.

AFAIK, incoming Ada will have arbitrary range integers. Now, if Natural 
were be a constrained subtype of that [and I am almost certain it will 
not be] then the representation of Natural would become an issue.

>> Yes and it is no different to how Ada treats arrays of CURVED_LETTERS
>> right now.
> 
> Given:
> subtype HEX_LETTERS is LETTERS range A..F;
> 
> When I create an array over Natural Ada does not create an array over Integer.  So I would expect that WITHOUT Static_Predicate, Ada would not create an array over the parent enumeration LETTERS when defined on the sub-type HEX_LETTERS.  So, this was my expectation for CURVED_LETTERS with the Static_Predicate before I read the rules.

As I said, ranged subtypes are done more correctly than predicates. 
HEX_LETTERS does not break array abstractions, CURVED_LETTERS do.

>>> To your question, I would say that the compiler treat the argument for A : LETTERS as a member of LETTERS such that A'First = 0 and A'Last = 11 even if a value of CURVED_LETTERS was passed in (as it does now).
>> Then why you expect a different behavior from an array of CURVED_LETTERS?
> 
> I think you misunderstood me.  Given the following,
> function L_POS( x : LETTERS ) return NATURAL is (LETTERS'Pos(x));
> and
> function CL_POS( x : CURVED_LETTERS ) return NATURAL is (CURVED_LETTERS'Pos(x));
> 
> I would have expected the following results:
> 1 <= l_pos(B)
> 0 <= cl_pos(B)
> 4 <= l_pos(E)
> exception <= cl_pos(E)

That would be a total catastrophe.

>>> This discussion is helpful as I am now understanding that what I'm thinking is perhaps also equally inconsistent. My current thinking is that I preferred a value of a sub-type to continue to be comparable (with =) to a value of the parent type, but I also wanted it to behave like a full-fledged type when using its attributes.

Derived types inherit operations, comparison is one of such operations. 
It is difficult to break comparison and so long the representation is 
same it is easy to inherit. BUT once you have different representations 
you start to enjoy all combinatorial fruits of multiple dispatch.

>> You cannot have it both ways.
> 
> Of course, and I'm not requesting what my expectations were.  But, I'm still trying to understand why it can't be done because, after all, if a programmer can write it, then a compiler could code-generate it.

It cannot be done mathematically. A subset is not a subtype. Subtype 
here is used in the Liskov's meaning: S is a subtype of T if any 
proposition p true on T holds on S.

Any constraint breaks something (= some proposition become untrue). A 
rational language design is to allow only constraints that would either

- allow static verification of the program at hand [rather than 
universal substitutability, which is not possible]

- allow formulation of weaker contracts that hold, e.g. adding 
Constraint_Error to the contract is such a method.

Range constraints satisfy the above principles, arbitrary predicates do not.

>>> Nevertheless, it still feels like an unfinished feature as it is now.
>> It is not unfinished. It is irreparably broken.
> 
> And this does not make for good advertising for Ada.

Come on, other languages do not bother themselves with whatever 
correctness issues at all.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de

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

* Re: array from static predicate on enumerated type
  2021-03-18  1:30                         ` Matt Borchers
  2021-03-18  8:20                           ` Dmitry A. Kazakov
@ 2021-03-18 10:15                           ` Niklas Holsti
  2021-03-18 10:47                             ` AdaMagica
  2021-03-19  0:34                             ` Matt Borchers
  1 sibling, 2 replies; 38+ messages in thread
From: Niklas Holsti @ 2021-03-18 10:15 UTC (permalink / raw)


On 2021-03-18 3:30, Matt Borchers wrote:
> On Wednesday, March 17, 2021 at 3:41:16 PM UTC-4, Dmitry A. Kazakov wrote:
>> On 2021-03-17 19:44, Matt Borchers wrote:


   [about "sparse" enumeration subtypes defined by static predicates,
    and arrays indexed by such subtypes]


>>> Nevertheless, it still feels like an unfinished feature as it is now.
>> It is not unfinished. It is irreparably broken.
> 
> And this does not make for good advertising for Ada.


Matt, you should be aware that Dmitry has strong opinions about language 
and program design that are not shared by all Ada users and Ada proponents.

To be sure, Ada is showing some of its age. Updates of the Ada standards 
have made extensive additions to the language, while taking great pains 
to remain mostly upwards compatible, not only in syntax and semantics 
but also in wider usability goals such as remaining competitive for 
hard-real-time embedded systems and safety-critical systems where 
implementation overheads and implementation complexity must be held 
down. This inevitably means that new high-level features such as static 
predicates cannot always be fully orthogonal to other features of the 
language.

There have been suggestions and discussion here of an "Ada successor" 
language, and Dmitry in particular thinks that the type system should be 
completely overhauled for such a new language. Unfortunately there seems 
to be no demand from any large potential user group for such a language, 
or if there is demand, it is being satisfied mostly by new "grass-roots" 
languages such as Rust.

I have some hope that the swiftly growing scope and impact of malware 
and SW security breaches will prompt a major effort to develop computer 
systems, including programming languages, which are provably secure and 
incorruptible, and perhaps that will be an opportunity for an Ada 
successor language.

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

* Re: array from static predicate on enumerated type
  2021-03-18 10:15                           ` Niklas Holsti
@ 2021-03-18 10:47                             ` AdaMagica
  2021-03-18 11:26                               ` Dmitry A. Kazakov
  2021-03-19  0:34                             ` Matt Borchers
  1 sibling, 1 reply; 38+ messages in thread
From: AdaMagica @ 2021-03-18 10:47 UTC (permalink / raw)


Niklas Holsti schrieb am Donnerstag, 18. März 2021 um 11:15:34 UTC+1:
> There have been suggestions and discussion here of an "Ada successor" 
> language, and Dmitry in particular thinks that the type system should be 
> completely overhauled for such a new language.

It's even unclear what Dmitry's type system would look like. He never posted a set of rules (not necessarily complete) that could be discussed. He only points out deficiencies of Ada's as he sees them.
Seeing deficiencies is a valid standpoint, Ada certainly has some, but we cannot discuss an alternative model without a set of requirements such a model shall fulfil. Currently there is none.

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

* Re: array from static predicate on enumerated type
  2021-03-18 10:47                             ` AdaMagica
@ 2021-03-18 11:26                               ` Dmitry A. Kazakov
  0 siblings, 0 replies; 38+ messages in thread
From: Dmitry A. Kazakov @ 2021-03-18 11:26 UTC (permalink / raw)


On 2021-03-18 11:47, AdaMagica wrote:
> Niklas Holsti schrieb am Donnerstag, 18. März 2021 um 11:15:34 UTC+1:
>> There have been suggestions and discussion here of an "Ada successor"
>> language, and Dmitry in particular thinks that the type system should be
>> completely overhauled for such a new language.
> 
> It's even unclear what Dmitry's type system would look like. He never posted a set of rules (not necessarily complete) that could be discussed. He only points out deficiencies of Ada's as he sees them.

It should be consistent and capable to express existing Ada type system. 
There is nothing inherently broken there in Ada.

> Seeing deficiencies is a valid standpoint, Ada certainly has some, but we cannot discuss an alternative model without a set of requirements such a model shall fulfil. Currently there is none.

I do not believe a new language is necessary. It is usual hand waving, 
Ada is too old etc. Rubbish, what is consistent in Ada remains 
consistent regardless the age. There is at least one new C developed 
from scratch each year, much difference? Garbage in, garbage out.

I do not believe in alternative models. There can be only one consistent 
model, like there is only one mathematics. Alternative to right is wrong.

Predicates will never work in any language, old or new, because the 
concept is wrong.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de

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

* Re: array from static predicate on enumerated type
  2021-03-18  1:04                         ` Matt Borchers
@ 2021-03-18 14:25                           ` Shark8
  2021-03-18 23:36                             ` Matt Borchers
  0 siblings, 1 reply; 38+ messages in thread
From: Shark8 @ 2021-03-18 14:25 UTC (permalink / raw)


On Wednesday, March 17, 2021 at 7:04:06 PM UTC-6, Matt Borchers wrote:
> What I would expect is that P(12) would be an illegal access because 12 is not a valid value of Primes thus cannot be an index and a constraint error or out-of-range error would be thrown.
Which is reasonable.
> Wouldn't this just involve the compiler to insert "if x not in primes then raise..." if constraint checking is enabled?
Possibly, there are also dynamic-predicates to consider; imagine a subtype wherein the usage of some number excludes that number from the subtype. Maybe a "unused_room_keys" subtype for a hotel.
> Otherwise you have an erroneous program. Similarly, Primes'Succ(12) is also illegal. Primes'Pred(2) also illegal because there is no prime before 2 so presumably you have defined your Static_Predicate to enumerate the primes with 2 listed first.
Why?
Given the standard "subtype Natural is Integer range 0..Integer'Last" and "subtype Positive is Natural range Natural'Succ(Natural'First)..Natural'Last"
Positive'Pred( 1 ) = 0, and no CONSTRAINT_ERROR.
Do you want to break standard Ada usage?

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

* Re: array from static predicate on enumerated type
  2021-03-18 14:25                           ` Shark8
@ 2021-03-18 23:36                             ` Matt Borchers
  0 siblings, 0 replies; 38+ messages in thread
From: Matt Borchers @ 2021-03-18 23:36 UTC (permalink / raw)


On Thursday, March 18, 2021 at 10:25:02 AM UTC-4, Shark8 wrote:

> > Otherwise you have an erroneous program. Similarly, Primes'Succ(12) is also illegal. Primes'Pred(2) also illegal because there is no prime before 2 so presumably you have defined your Static_Predicate to enumerate the primes with 2 listed first.
> Why? 
> Given the standard "subtype Natural is Integer range 0..Integer'Last" and "subtype Positive is Natural range Natural'Succ(Natural'First)..Natural'Last" 
> Positive'Pred( 1 ) = 0, and no CONSTRAINT_ERROR. 
> Do you want to break standard Ada usage?

I'm certainly not advocating for inconsistency as stated many times.  The integers exist essentially in a continuum with hardware limitations.  An enumeration has a programmer defined first and last value and so does a subtype on Positive with a Static_Predicate.  I pulled those ideas out of my head while I was responding and I admit there should be more discussion on behavior if this were to ever be implemented.  But that is highly doubtful.

Regards,
Matt

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

* Re: array from static predicate on enumerated type
  2021-03-18  8:20                           ` Dmitry A. Kazakov
@ 2021-03-19  0:10                             ` Matt Borchers
  2021-03-19  8:00                               ` Dmitry A. Kazakov
  0 siblings, 1 reply; 38+ messages in thread
From: Matt Borchers @ 2021-03-19  0:10 UTC (permalink / raw)


Dmitry,

I don't think we can blatantly say that subtypes are types in every sense of the meaning.  If they were distinct then there would be no difference between:

subtype HEX_LETTERS is LETTERS range A..F;

and

type HEX_LETTERS is new LETTERS range A..F;

when given:

type LETTERS is ( A, B, C, D, E, F, G, H, I, J, K );

Please correct me if I am wrong, but I have always thought that the values A through F in the sub-type were the same values of the parent type and are effectively used interchangeably with the corresponding values of the parent type.  The sub-type simply provides a kind of restricted "view" constraint. That is, the constraint checking used for variables of these types depends on the type "view" of the variable.  I don't know if I can explain myself very well.  I expected, therefore, that when a Static_Predicate was applied to the sub-type, just a more complex constraint checking routine would be applied rather that a simple "in range" check.

>> I think you misunderstood me. Given the following,
>> function L_POS( x : LETTERS ) return NATURAL is (LETTERS'Pos(x));
>> and
>> function CL_POS( x : CURVED_LETTERS ) return NATURAL is (CURVED_LETTERS'Pos(x));
>>
>> I would have expected the following results:
>> 1 <= l_pos(B)
>> 0 <= cl_pos(B)
>> 4 <= l_pos(E)
>> exception <= cl_pos(E)

> That would be a total catastrophe. 

In regards to what L_POS and CL_POS return, I don't understand why that would be a catastrophe.  Those values seem like reasonable answers to what the programmer requested.  This is really the point of this pose and my question in the first place:  What is the reason that there is absolutely no way to implement useful results for 'First, 'Last, etc. with Static_Predicates?  And because of this, what is the best work-around?  And I do feel like this requires a work-around.

If CURVED_LETTERS with a predicate is not a sub-type, then it should not be declared with a sub-type keyword.  I like the word you used: subset.  It should have been:

subset CURVED_LETTERS is LETTERS (B,C,D,G,J);

And then Ada can be free to define a whole new set of rules for sub-sets while keeping sub-types consistent.

Regards,
Matt

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

* Re: array from static predicate on enumerated type
  2021-03-18 10:15                           ` Niklas Holsti
  2021-03-18 10:47                             ` AdaMagica
@ 2021-03-19  0:34                             ` Matt Borchers
  2021-03-19  0:49                               ` Jeffrey R. Carter
  2021-03-22 19:09                               ` Niklas Holsti
  1 sibling, 2 replies; 38+ messages in thread
From: Matt Borchers @ 2021-03-19  0:34 UTC (permalink / raw)


Niklas,

Don't get me wrong, I love Ada and use extensively.  The ease in which a programmer can quickly get from a modestly complex problem to a correct program when using Ada is great.  Like many have said, Ada requires you to have a program design in your head before writing the program.  The Static_Predicate thing was certainly a surprise to me.  One now has to decide early on in design if they'd rather have a convenient way to do member tests with 'in' or do they require the use of 'Pos, 'First, etc.  Sorry, not both.  Pretty useless IMO.  I still haven't heard or read of a good reason to decide to not implement any kind of usability for the constraint attributes.  I wish I had the transcript from the Ada Group's discussions on this topic.  It must have been a good one.  Do they keep transcripts of their discussions?  If so, does anybody know where to find them?

Regards,
Matt

On Thursday, March 18, 2021 at 6:15:34 AM UTC-4, Niklas Holsti wrote:
> To be sure, Ada is showing some of its age. Updates of the Ada standards 
> have made extensive additions to the language, while taking great pains 
> to remain mostly upwards compatible, not only in syntax and semantics 
> but also in wider usability goals such as remaining competitive for 
> hard-real-time embedded systems and safety-critical systems where 
> implementation overheads and implementation complexity must be held 
> down. This inevitably means that new high-level features such as static 
> predicates cannot always be fully orthogonal to other features of the 
> language. 

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

* Re: array from static predicate on enumerated type
  2021-03-19  0:34                             ` Matt Borchers
@ 2021-03-19  0:49                               ` Jeffrey R. Carter
  2021-03-23  1:07                                 ` Matt Borchers
  2021-03-22 19:09                               ` Niklas Holsti
  1 sibling, 1 reply; 38+ messages in thread
From: Jeffrey R. Carter @ 2021-03-19  0:49 UTC (permalink / raw)


On 3/19/21 1:34 AM, Matt Borchers wrote:
> 
> I wish I had the transcript from the Ada Group's discussions on this topic.  It must have been a good one.  Do they keep transcripts of their discussions?  If so, does anybody know where to find them?

http://www.ada-auth.org/arg.html

You probably want ai05-0153-1 at

http://www.ada-auth.org/cgi-bin/cvsweb.cgi/ai05s/ai05-0153-1.txt?rev=1.15&raw=N

-- 
Jeff Carter
"Ditto, you provincial putz?"
Blazing Saddles
86

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

* Re: array from static predicate on enumerated type
  2021-03-19  0:10                             ` Matt Borchers
@ 2021-03-19  8:00                               ` Dmitry A. Kazakov
  0 siblings, 0 replies; 38+ messages in thread
From: Dmitry A. Kazakov @ 2021-03-19  8:00 UTC (permalink / raw)


On 2021-03-19 01:10, Matt Borchers wrote:

> I don't think we can blatantly say that subtypes are types in every sense of the meaning.  If they were distinct then there would be no difference between:
> 
> subtype HEX_LETTERS is LETTERS range A..F;
> 
> and
> 
> type HEX_LETTERS is new LETTERS range A..F;

These are two different type operations. The first creates a derived 
type. The second creates a clone of a type.

> when given:
> 
> type LETTERS is ( A, B, C, D, E, F, G, H, I, J, K );
> 
> Please correct me if I am wrong, but I have always thought that the values A through F in the sub-type were the same values of the parent type and are effectively used interchangeably with the corresponding values of the parent type.

There exist a mapping between the values of a derived type and the 
values of the base type. Depending on the properties of this mapping 
(e.g. conjuctive, surjective etc) you may be able to substitute one 
value for another.

... and independently on that the language may allow you to substitute 
regardless the above. This is what you get with CURVED_LETTERS and 
LETTERS. The language allowed you to substitute CURVED_LETTERS for 
LETTERS even when you should not. In glorious FORTRAN-IV you could pass 
INTEGER*8 for REAL*4. Did that make INTEGER*8 a subtype? No, it did 
FORTRAN-IV broken.

> The sub-type simply provides a kind of restricted "view" constraint. That is, the constraint checking used for variables of these types depends on the type "view" of the variable.

Nothing simple. It is elementary to show why natural is not integer. 
Consider the proposition:

    forall x Integer exists -x Integer

It is almost true for Integer (depending on the range, e.g. 2's 
complement usually has one value that cannot be negated). It is almost 
wrong for Natural. A program relying on this property gets broken if you 
substitute Natural for Integer.

> I don't know if I can explain myself very well. 

You confuse set membership with properties of a set as a whole. A set is 
more than the sum of individual elements. Like a type is not a set of 
values it is a set of values + operations defined on them. Taking out or 
adding values breaks operations.

>>> I think you misunderstood me. Given the following,
>>> function L_POS( x : LETTERS ) return NATURAL is (LETTERS'Pos(x));
>>> and
>>> function CL_POS( x : CURVED_LETTERS ) return NATURAL is (CURVED_LETTERS'Pos(x));
>>>
>>> I would have expected the following results:
>>> 1 <= l_pos(B)
>>> 0 <= cl_pos(B)
>>> 4 <= l_pos(E)
>>> exception <= cl_pos(E)
> 
>> That would be a total catastrophe.
> 
> In regards to what L_POS and CL_POS return, I don't understand why that would be a catastrophe.  Those values seem like reasonable answers to what the programmer requested.  This is really the point of this pose and my question in the first place:  What is the reason that there is absolutely no way to implement useful results for 'First, 'Last, etc. with Static_Predicates?  And because of this, what is the best work-around?  And I do feel like this requires a work-around.

You describe overriding of a base type operation ('Pos) in the same 
breath with claiming it is the same type.

> If CURVED_LETTERS with a predicate is not a sub-type, then it should not be declared with a sub-type keyword.  I like the word you used: subset.  It should have been:
> 
> subset CURVED_LETTERS is LETTERS (B,C,D,G,J);

What should that change? Again, the problem is mathematical, not 
linguistic. Wording changes nothing.

1. What is the relation between instances of CURVED_LETTERS and LETTERS?

2. Which operations are inherited from LETTERS = you can use 
CURVED_LETTERS in place of LETTERS?

3. Which inherited operations get overridden?

4. Which operations are exported [*] for CURVED_LETTERS to LETTERS = you 
can use LETTERs in place of CURVED_LETTERS?

5. Which exported operations get overridden?

-----------
* In Ada, "subtype is" imports and exports everything visible, while 
"type is new with" imports (inherits) only primitive and class-wide 
operations.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de

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

* Re: array from static predicate on enumerated type
  2021-03-19  0:34                             ` Matt Borchers
  2021-03-19  0:49                               ` Jeffrey R. Carter
@ 2021-03-22 19:09                               ` Niklas Holsti
  1 sibling, 0 replies; 38+ messages in thread
From: Niklas Holsti @ 2021-03-22 19:09 UTC (permalink / raw)


On 2021-03-19 2:34, Matt Borchers wrote:
> Niklas,
> 
> Don't get me wrong, I love Ada and use extensively.


Ok, and good for you, but I did not mean to imply otherwise, nor do I 
look down on people who do not love Ada.

I was mainly trying to say that even if Dmitry thinks that some feature 
of Ada is "irreparably broken", it does not mean that all here share 
that opinion; many of us may think that the feature is quite useful, 
although it has limitations or even some warts. As long as we know those 
limitations and keep them in mind when we design and code.

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

* Re: array from static predicate on enumerated type
  2021-03-19  0:49                               ` Jeffrey R. Carter
@ 2021-03-23  1:07                                 ` Matt Borchers
  2021-03-23  3:43                                   ` Randy Brukardt
  0 siblings, 1 reply; 38+ messages in thread
From: Matt Borchers @ 2021-03-23  1:07 UTC (permalink / raw)


On Thursday, March 18, 2021 at 8:49:43 PM UTC-4, Jeffrey R. Carter wrote:
> On 3/19/21 1:34 AM, Matt Borchers wrote: 
> > 
> > I wish I had the transcript from the Ada Group's discussions on this topic. It must have been a good one. Do they keep transcripts of their discussions? If so, does anybody know where to find them?
> http://www.ada-auth.org/arg.html 
> 
> You probably want ai05-0153-1 at 
> 
> http://www.ada-auth.org/cgi-bin/cvsweb.cgi/ai05s/ai05-0153-1.txt?rev=1.15&raw=N 

Thanks Jeff.  This is going to take a while to get through and it is heavy reading.  I had no idea this subject has been fermenting for 12+ years.  However, in only the tiny portion I've read so far it seems a few commenters of high repute share some of my sentiments -- which only makes me 12 years late to the party of the losing side. :)

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

* Re: array from static predicate on enumerated type
  2021-03-23  1:07                                 ` Matt Borchers
@ 2021-03-23  3:43                                   ` Randy Brukardt
  0 siblings, 0 replies; 38+ messages in thread
From: Randy Brukardt @ 2021-03-23  3:43 UTC (permalink / raw)


To get as complete as possible a picture of how some Ada feature came to be, 
you need to not only read the AI and especially it's e-mail, but also the 
meeting minutes associated with that AI. We now have an index for that 
purpose on Ada-Auth.org, the Ada 2005 AI version is found at:
    http://www.ada-auth.org/AI05-VOTING.HTML

Unfortunately, for Ada 2012, a lot of design occurred in unofficial phone 
meetings. No minutes were produced for those meetings, and so far as I know 
the only existing material is the notes I have kept on my hard disk. If I 
ever get some time, I want to get a version of those on-line so this sort of 
research can work usefully for Ada 2012. (Ideally in the format that the 
indexing tool can pick up and put into those indexes.)

Note that all three AI05-0153-x versions were involved, so it is useful to 
read all of them. (There also was some cross-AI discussions, which is 
probably beyond anyone's ability to find, at least for fun.)

                                            Randy.

P.S. Noticed this when looking at the evolution of aspect specifications. In 
the material on-line, they essentially appear in a near final form. That's 
not how it was!

"Matt Borchers" <mattborchers@gmail.com> wrote in message 
news:d3f4e8ad-8d5b-49b2-939d-1d1c7938d554n@googlegroups.com...
On Thursday, March 18, 2021 at 8:49:43 PM UTC-4, Jeffrey R. Carter wrote:
> On 3/19/21 1:34 AM, Matt Borchers wrote:
> >
> > I wish I had the transcript from the Ada Group's discussions on this 
> > topic. It must have been a good one. Do they keep transcripts of their 
> > discussions? If so, does anybody know where to find them?
> http://www.ada-auth.org/arg.html
>
> You probably want ai05-0153-1 at
>
> http://www.ada-auth.org/cgi-bin/cvsweb.cgi/ai05s/ai05-0153-1.txt?rev=1.15&raw=N

Thanks Jeff.  This is going to take a while to get through and it is heavy 
reading.  I had no idea this subject has been fermenting for 12+ years. 
However, in only the tiny portion I've read so far it seems a few commenters 
of high repute share some of my sentiments -- which only makes me 12 years 
late to the party of the losing side. :) 


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

* Re: array from static predicate on enumerated type
  2021-03-15 20:25           ` Dmitry A. Kazakov
  2021-03-16 13:27             ` Shark8
@ 2022-03-16  0:38             ` Thomas
  1 sibling, 0 replies; 38+ messages in thread
From: Thomas @ 2022-03-16  0:38 UTC (permalink / raw)


In article <s2ofr1$1cg3$1@gioia.aioe.org>,
 "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote:

> On 2021-03-15 18:48, Shark8 wrote:
> 
> > So, in Ada, there's no good choice for how to actually DO an array with 
> > gaps in the index:
> 
> That applies to all containers. The problem is mapping the key to a 
> dense position when the key is not dense or might be unordered.
> 
> There is no gaps in positions.
> 
> > But Array *isn't* a map, though often it is substituted as one.
> 
> Of course it is, per definition of mapping. f : key -> element.
> 
> > Array has further constraints, like the contiguous memory labeled above.
> 
> No. The constraint here is a dense index. That is not specific to a 
> general map or an array. It is a fundamental property of the set of keys 
> being a convex set. Convex ensures certain useful mathematical 
> properties invariant to the representation of the mapping. In 
> particular, it gives a way to enumerate elements.

> Arbitrary predicate kills convex, so the problem. Not array. A map would 
> have just same problem: a map of LETTERS is in general not substitutable 
> for a map of CURVED_LETTERS.


i don't understand,
since Ada.Containers.Ordered_Maps.Key_Type is private,
and so new Ada.Containers.Ordered_Maps (CURVED_LETTERS, Integer) is 
allowed.

-- 
RAPID maintainer
http://savannah.nongnu.org/projects/rapid/

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

end of thread, other threads:[~2022-03-16  0:38 UTC | newest]

Thread overview: 38+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-03-12 20:49 array from static predicate on enumerated type Matt Borchers
2021-03-12 21:22 ` Egil H H
2021-03-12 22:16 ` Jeffrey R. Carter
2021-03-12 22:41 ` Dmitry A. Kazakov
2021-03-13  2:06   ` Matt Borchers
2021-03-13  4:55     ` Randy Brukardt
2021-03-15 14:16       ` Matt Borchers
2021-03-15 17:53         ` Shark8
2021-03-16  6:58         ` Randy Brukardt
2021-03-13  8:04     ` Dmitry A. Kazakov
2021-03-15 14:11       ` Matt Borchers
2021-03-15 17:48         ` Shark8
2021-03-15 20:25           ` Dmitry A. Kazakov
2021-03-16 13:27             ` Shark8
2021-03-16 14:25               ` Dmitry A. Kazakov
2021-03-17  4:05                 ` Matt Borchers
2021-03-17  7:08                   ` Dmitry A. Kazakov
2021-03-17 18:44                     ` Matt Borchers
2021-03-17 19:41                       ` Dmitry A. Kazakov
2021-03-18  1:30                         ` Matt Borchers
2021-03-18  8:20                           ` Dmitry A. Kazakov
2021-03-19  0:10                             ` Matt Borchers
2021-03-19  8:00                               ` Dmitry A. Kazakov
2021-03-18 10:15                           ` Niklas Holsti
2021-03-18 10:47                             ` AdaMagica
2021-03-18 11:26                               ` Dmitry A. Kazakov
2021-03-19  0:34                             ` Matt Borchers
2021-03-19  0:49                               ` Jeffrey R. Carter
2021-03-23  1:07                                 ` Matt Borchers
2021-03-23  3:43                                   ` Randy Brukardt
2021-03-22 19:09                               ` Niklas Holsti
2021-03-17 15:08                   ` Shark8
2021-03-17 19:08                     ` Matt Borchers
2021-03-17 20:41                       ` Shark8
2021-03-18  1:04                         ` Matt Borchers
2021-03-18 14:25                           ` Shark8
2021-03-18 23:36                             ` Matt Borchers
2022-03-16  0:38             ` Thomas

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