Prev: Ann: Generic Image Decoder v.01
Next: ANN: Tables 1.10
From: Phil Clayton on 6 Jul 2010 12:31 On Jul 6, 8:36 am, "Dmitry A. Kazakov" <mail...(a)dmitry-kazakov.de> wrote: > On Mon, 5 Jul 2010 15:47:41 -0700 (PDT), Phil Clayton wrote: > > On Jul 5, 2:12 pm, "Dmitry A. Kazakov" <mail...(a)dmitry-kazakov.de> > > wrote: > >> On Sun, 4 Jul 2010 18:27:04 -0700 (PDT), Phil Clayton wrote: > >>> In my view, condition expressions are a step in the right direction.... > >>> but I'm the sort of person who wants to write an array aggregate like > > >>> (for I in 1 .. 5 => (for J in 1 .. 7 => (if I = J then 1.0 else > >>> 0.0))) > > >> (for I in 1..5 => (for J in 1..7 => Float (Boolean'Pos (I = J)))) > > > Yep, I should have seen that one coming straight back... and taken > > steps to avoid it :) > > BTW, is your construct 1) a macro expansion (as I remember PL/1 > preprocessor also had %for statement alike) and how far are you ready to go > allowing "for" macros? Loops unrolling? Or else 2) it is an attempt to name > the components of an array element index. Definitely the latter... > In the latter case > > (I, J : others => <an expression involving I,J>) > (I : 1..5 => <an expression involving I>) > (Odd : 1 | 3 | 5 | 7 => <an expression involving Odd>, others => 0.0) > etc > > looks to me more consistent with existing Ada, e.g. when Error : others => > in exception handlers. Interesting. So, considering the difference between 1. X : T 2. for X in T My take on Ada is that [1] just declares a new variable X of subtype T (which may be initialized depending on context) whilst [2] is used when declaring a new variable X of subtype T and then giving X the values of T in some specified order, i.e. introducing some iteration scheme. If that is a fair assessment of things, then perhaps (for I in 1 .. 5 => F(I)) is more in keeping with existing Ada? (If I'm talking absolute drivel, please let me know...) The concept of an order is important because the function F could have side effects in the above example (though I would not advocate that as good practice). However, we would be able to write (for I in reverse A'Range => A(I)) to represent the reverse of the array A is perhaps a little confusing. Also, it really only makes sense to have one variable holding the array index. For example, if we could write (I, J : 1 .. 5 => ...) surely I and J would always be equal: there are only 5 elements in the array. Having (for I in 1 .. 5 => ...) syntactically rules out multiple variables. Phil
From: Dmitry A. Kazakov on 6 Jul 2010 13:18 On Tue, 6 Jul 2010 09:31:05 -0700 (PDT), Phil Clayton wrote: > The concept of an order is important because the function F could have > side effects in the above example (though I would not advocate that as > good practice). AFAIK, presently the order is not defined. So though this is legal X : String (1..80) := (others => Character'Read (Stream'Access)); It is not a good idea. > However, we would be able to write > > (for I in reverse A'Range => A(I)) > > to represent the reverse of the array A is perhaps a little confusing. The effect is undefined. Theoretically the compiler could initialize array elements concurrently on a multi-core processor. > Also, it really only makes sense to have one variable holding the > array index. For example, if we could write > > (I, J : 1 .. 5 => ...) > > surely I and J would always be equal: there are only 5 elements in the > array. Having > > (for I in 1 .. 5 => ...) > > syntactically rules out multiple variables. Yes, but many other things as well. However I prefer an absolutely different approach anyway, e.g. proper index types. In my world a diagonal would be initialized like: (Diagonal (5, 5) => 1.0, others => 0.0) where Diagonal is a proper function. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de
From: Phil Clayton on 7 Jul 2010 08:00 On Jul 6, 6:18 pm, "Dmitry A. Kazakov" <mail...(a)dmitry-kazakov.de> wrote: > On Tue, 6 Jul 2010 09:31:05 -0700 (PDT), Phil Clayton wrote: > > The concept of an order is important because the function F could have > > side effects in the above example (though I would not advocate that as > > good practice). > > AFAIK, presently the order is not defined. So though this is legal > > X : String (1..80) := (others => Character'Read (Stream'Access)); > > It is not a good idea. It would be good if the order was not defined because that would prevent people depending on it, so making it easier for a compiler to parallelize. > > However, we would be able to write > > > (for I in reverse A'Range => A(I)) > > > to represent the reverse of the array A is perhaps a little confusing. > > The effect is undefined. Theoretically the compiler could initialize array > elements concurrently on a multi-core processor. There are really two concepts here: 1. the order of evaluation of the expressions for each index 2. the value the bound variable I gets for each index I didn't make it clear that I was switching from [1] to [2], sorry. This above reverse example was really about [2] to show that the use of the keyword 'reverse' would result in I having the value A'Last at index A'First, A'Last - 1 at index A'First + 1, etc. I don't think it matters whether A(I) is evaluated for each index in parallel, so I think the expression should be well defined. > > Also, it really only makes sense to have one variable holding the > > array index. For example, if we could write > > > (I, J : 1 .. 5 => ...) > > > surely I and J would always be equal: there are only 5 elements in the > > array. Having > > > (for I in 1 .. 5 => ...) > > > syntactically rules out multiple variables. > > Yes, but many other things as well. However I prefer an absolutely > different approach anyway, e.g. proper index types. In my world a diagonal > would be initialized like: > > (Diagonal (5, 5) => 1.0, others => 0.0) > > where Diagonal is a proper function. Interesting.. how would you make the expression a function of the index? For example, how would you write (for I in 3 .. 8 => A(I) + B(I - 2)) ? Phil
From: Dmitry A. Kazakov on 7 Jul 2010 09:39
On Wed, 7 Jul 2010 05:00:47 -0700 (PDT), Phil Clayton wrote: > On Jul 6, 6:18�pm, "Dmitry A. Kazakov" <mail...(a)dmitry-kazakov.de> > wrote: >> On Tue, 6 Jul 2010 09:31:05 -0700 (PDT), Phil Clayton wrote: >>> The concept of an order is important because the function F could have >>> side effects in the above example (though I would not advocate that as >>> good practice). >> >> AFAIK, presently the order is not defined. So though this is legal >> >> � �X : String (1..80) := (others => Character'Read (Stream'Access)); >> >> It is not a good idea. > > It would be good if the order was not defined because that would > prevent people depending on it, so making it easier for a compiler to > parallelize. But then the language should define pure functions (relatively to the given context) and prohibit usage of impure ones in the constructs like above. >>> However, we would be able to write >> >>> � (for I in reverse A'Range => A(I)) >> >>> to represent the reverse of the array A is perhaps a little confusing. >> >> The effect is undefined. Theoretically the compiler could initialize array >> elements concurrently on a multi-core processor. > > There are really two concepts here: > 1. the order of evaluation of the expressions for each index > 2. the value the bound variable I gets for each index > > I didn't make it clear that I was switching from [1] to [2], sorry. > This above reverse example was really about [2] to show that the use > of the keyword 'reverse' would result in I having the value A'Last at > index A'First, A'Last - 1 at index A'First + 1, etc. OK. The objection is that in this case I is not the array's index, but a mapping of. That looks totally obscure. >>> Also, it really only makes sense to have one variable holding the >>> array index. �For example, if we could write >> >>> � (I, J : 1 .. 5 => ...) >> >>> surely I and J would always be equal: there are only 5 elements in the >>> array. �Having >> >>> � (for I in 1 .. 5 => ...) >> >>> syntactically rules out multiple variables. >> >> Yes, but many other things as well. However I prefer an absolutely >> different approach anyway, e.g. proper index types. In my world a diagonal >> would be initialized like: >> >> � �(Diagonal (5, 5) => 1.0, others => 0.0) >> >> where Diagonal is a proper function. > > Interesting.. how would you make the expression a function of the > index? I don't want such expressions at all. I mean if these are necessary it must be a function returning an array. Reading aggregates containing some inlined code is not readable to me. This is yet another topic, but I favor user-defined aggregates instead of hard coded special stuff like index dependent expressions. E.g. if you have some frequently used special type of "array literals" you should be able to provide a custom aggregate of. For example, let you deal with band matrices. The language should allow you to define a custom aggregate like A : Square_Matrix := ( Upper => (1.0, 2.4), Diagonal => (7.3, 8.0, 9.1), Lower => (3.0, 2.1) ); P.S. This issue boils down to the interfaces. The point is that you should be able to implement interface of any type for the given one. A record of arrays is an interface which has aggregates like above. Hang it on Square_Matrix and you will be able to do above aggregates and other useful stuff, like A.Upper. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de |