February 17, 2005 Re: Possible rewrite of array operation spec | ||||
---|---|---|---|---|
| ||||
Posted in reply to Regan Heath | Regan Heath schrieb:
> What about:
>
> test.length //length of array
> test[].length //length of each element in array
Bad idea: 'test[]' is an array by itself, so it has a length property by itself...
|
February 17, 2005 Re: Possible rewrite of array operation spec | ||||
---|---|---|---|---|
| ||||
Posted in reply to xs0 | xs0 wrote: > Stewart Gordon wrote: > >> To reuse the result array, you use >> >> a[] = b; >> >> This would remain the same when array operations are involved. > > but a[]=b doesn't look like a can be [re]allocated (and it can be, if > it is the wrong size or null). anyhow, it's not that important :) What would be the sense of assigning in-place if the destination array is going to be either the wrong size or null? I see two motives for assigning in-place: - to keep the data in sync when there are multiple references to it. But this already isn't going to work if you need to keep resizing the array, unless you wrap the array in a pointer or class to make it work. - to save the overhead of memory allocation during calculations. But when the arrays can arbitrarily change in size, this overhead just comes back. >>> But why would you prefer a new array instead of in-place (when possible)? >> >> Because you want x to still contain the same old data, of course. > > But in this case you'd normally do > > x=y.dup; > y=...; Only if there are other references to the same data somewhere in the program, and I want x to break away so that I can modify it independently. Otherwise, the .dup is just wasteful. > Except in case of array expressions, where you suggest > > x=y; > y=...; // y is new No "except" to it. The semantics of a = ... and a[] = ... are completely independent of the form of the right operand. >> Of course not. Why would you declare two references to the same array in the same scope if (x === y) is going to remain true throughout? > > Who said anything about the same scope? Any anyhow, when I asked about your preference, I meant why do you think it's better to lose references as easily as possible, than the opposite? I'm not sure what you mean by this. My spec was written with three basic intentions: (a) to be well-defined (b) to keep D consistent within itself (c) to be backward compatible with the current assignment semantics Do you actually understand how my spec works? Let's look at some examples mechanically. Current D (semantics will be preserved): int[] x, y, z; ... z = x; assign x by reference to z z[] = x; copy the contents of x into z (requires that z and x are already the same size) z = x.dup; make a copy of x, and assign this copy by reference to z (The array previously referenced by z may still have references somewhere, or otherwise it would become eligible for GC.) With array ops: z = x + y; create an array of x[i] + y[i] assign this new array by reference to z z[] = x + y; create an array of x[i] + y[i] copy the contents of this new array in z (A decent compiler would implement this by adding the elements directly into z, bypassing the temporary array. But this is part of compiler optimisations, rather than of the basic semantics.) z = x * 2 + y; create an array of x[i] * 2 create an array of result[i] + y[i] assign this new result by reference to z (x * 2 is a temporary, and so the compiler can optimise it away.) z[] = x * 2 + y; create an array of x[i] * 2 create an array of result[i] + y[i] copy the contents of this new array into z (Here there are two temporaries: x * 2 and x * 2 + y.) See how they fit together now? <snip> > Sure, a struct would work, it might needlessly complicate things, though. In most cases you just want the min/max value and checking for multiples is much rarer. <snip> Indeed, there's no reason we can't have both the struct and plain minEl and maxEl. Stewart. -- My e-mail is valid but not my primary mailbox. Please keep replies on the 'group where everyone may benefit. |
February 17, 2005 Re: Possible rewrite of array operation spec | ||||
---|---|---|---|---|
| ||||
Posted in reply to Regan Heath | Regan Heath wrote: > On Wed, 16 Feb 2005 12:58:46 +0000, Stewart Gordon <smjg_1998@yahoo.com> wrote: <snip> >> b = a; >> a = a.dup; >> foreach (inout x; a) x--; > > > Not this, because "b = a" is a copy i.e. "b = a.dup" What do you mean? b = a on dynamic arrays is, by definition, a reference assignment. >> or >> >> b = a.dup; >> foreach (inout x; a) x--; > > This is probably the most sensible. <snip> And it's also consistent with what can be done with opPostInc and opPostDec on a class. Stewart. -- My e-mail is valid but not my primary mailbox. Please keep replies on the 'group where everyone may benefit. |
February 17, 2005 Re: Possible rewrite of array operation spec | ||||
---|---|---|---|---|
| ||||
Posted in reply to Norbert Nemec | In article <cv17tg$22nb$1@digitaldaemon.com>, Norbert Nemec says... > >One more detail: it should be clear, that the order of evaluation is not defined and that the temporary array is not guaranteed to be created. Any code that depends on the order of evaluation or the existance of temporaries is to be considered erraneous, like: > > a[1:9] = a[0:8]+1; > >(The compiler may not always be able to reliably detect such errors. Maybe a case for warnings?) > >If the order is unnecessarily defined in the specs, this might seriously limit the optimizability of the code. Currently, the wording "is equivalent to" sounds very dangerous in that respect. > >Ciao, >Norbert > Norbert - a few questions on all this if you have the time. How has the F95 FORALL statement gone over in numerical computing? Is it being used in a lot of codes and/or has there been a lot of software being re-written to use it? How are the optimizing compilers dealing with it - are they using it to good advantage? I gather there has been at least a little movement towards C/++ from Fortran, especially since more and more numerical software specialists have gotten into the field and pried the keyboard out of the hands of the people with the white lab coats. Problem has been that Fortran is so darn good at what it does. So, Is it possible for D (done correctly) to attract a good number of numerical computing people, or is Fortran so entrenched that this would be difficult with even a great language implementation? Is there/has there been a general feeling that it's time to "move past" Fortran in that field? Thanks, - Dave > > >Stewart Gordon schrieb: >> This'll probably get people asking the prospect of array operations for 1.0 to be resurrected, but still.... >> >> Here is a possible specification for array operations that I feel is better-defined than the one in the current out-of-date spec. Of course, there are still some open questions, which I've put at the bottom. >> >> >> Array operations >> ---------------- >> Arithmetic and bitwise operators are defined on array operands. An expression involving an array evaluates to a new array in which the operator has been applied to the elements of the operands in turn. >> >> In essence, when an expression contains more than one array operation, a new array is created to hold the result of each operation. However, a quality implementation will optimize the evaluation of the expression to eliminate temporaries where possible. >> >> Unary operations >> ~~~~~~~~~~~~~~~~ >> For the unary operators +, - and ~, the expression evaluates to a new >> array containing the result of applying the operator to each element. >> For example, with the declaration >> >> int[] x, y; >> >> then the statement >> >> y = -x; >> >> is simply equivalent to >> >> y = new int[x.length]; >> for (int i = 0; i < y.length; i++) { >> y[i] = -x[i]; >> } >> >> Binary operations >> ~~~~~~~~~~~~~~~~~ >> The binary operations supported are +, -, *, /, %, &, |, ^, <<, >> and >>>. >> >> If the two arrays are of the same dimension and of compatible types, then the expression evaluates to a new array in which each element is the result of applying the operator to corresponding elements of the operands. For example, with the declarations >> >> int[] x, y, z; >> >> the statement >> >> z = x + y; >> >> is equivalent to >> >> z = new int[x.length]; >> for (int i = 0; i < z.length; i++) { >> z[i] = x[i] + y[i]; >> } >> >> Both operands must be of the same length. If they are not, an ArrayBoundsError is thrown. >> >> For higher dimensions, this definition is applied recursively. For example, with >> >> int[][] x, y, z; >> >> the statement >> >> z = x * y; >> >> is equivalent to >> >> z = new int[x.length]; >> for (int i = 0; i < z.length; i++) { >> z[i] = x[i] * y[i]; >> } >> >> which is in turn equivalent to >> >> z = new int[x.length]; >> for (int i = 0; i < z.length; i++) { >> z[i] = new int[x[i].length]; >> for (int j = 0; j < z[i].length; j++) { >> z[i][j] = x[i][j] * y[i][j]; >> } >> } >> >> If the operands do not match in dimension, then the operator is applied to each element of the higher-dimension operation with the whole of the lower-dimension one. For example, with >> >> int[] x, z; >> int y; >> >> the statement >> >> z = x - y; >> >> is equivalent to >> >> z = new int[x.length]; >> for (int i = 0; i < z.length; i++) { >> z[i] = x[i] - y; >> } >> >> Similarly, >> >> z = y - x; >> >> is equivalent to >> >> z = new int[x.length]; >> for (int i = 0; i < z.length; i++) { >> z[i] = y - x[i]; >> } >> >> This definition is applied recursively if the dimensions differ by two or more. >> >> Assignment operations >> ~~~~~~~~~~~~~~~~~~~~~ >> When x is an array, the assignment >> >> x op= y; >> >> is taken as equivalent to >> >> x = x op y; >> >> whether y is an array of matching dimension, an array of lower dimension or a scalar. Thus the operation creates a new array and assigns it to x. If a sliced lvalue is used, the array is modified in place, so that >> >> x[] op= y; >> >> is equivalent to >> >> x[] = x[] op y; >> >> The preincrement and predecrement operators are handled in the same way. >> >> User-defined types >> ~~~~~~~~~~~~~~~~~~ >> A class, struct or union type may have operators overloaded with array >> types as parameters. To avoid conflicts between overloaded operators >> and array operations, binary operations involving both array and >> user-defined types are resolved as follows: >> >> 1. The normal operator overloading rules are applied. >> 2. If no match is found, the array operation rules are applied until >> both operands are reduced to scalar type; operator overloading rules are >> then applied to the result. >> 3. If the expression still does not resolve, it is an error. >> >> >> Open questions >> ~~~~~~~~~~~~~~ >> Should postincrement and postdecrement be allowed? How should they be >> handled? >> >> Should we generalise the concept to function calls? If so, I guess that overload resolution would work in much the same way as for operations on user-defined types. >> >> If we do allow it on function calls, should we allow it to work on functions of three or more parameters? In this case, the highest-dimension argument would be reduced to the dimension of the second highest, and then these two reduced together to match the third highest, and so on. >> >> Of course, these questions raise one more: how easy or hard would these ideas be to implement? >> >> >> Any thoughts? >> >> Stewart. >> |
February 17, 2005 Re: Possible rewrite of array operation spec | ||||
---|---|---|---|---|
| ||||
Posted in reply to Dave | Dave schrieb:
> Norbert - a few questions on all this if you have the time.
>
> How has the F95 FORALL statement gone over in numerical computing? Is it being
> used in a lot of codes and/or has there been a lot of software being re-written
> to use it? How are the optimizing compilers dealing with it - are they using it
> to good advantage?
>
> I gather there has been at least a little movement towards C/++ from Fortran,
> especially since more and more numerical software specialists have gotten into
> the field and pried the keyboard out of the hands of the people with the white
> lab coats. Problem has been that Fortran is so darn good at what it does. So, Is
> it possible for D (done correctly) to attract a good number of numerical
> computing people, or is Fortran so entrenched that this would be difficult with
> even a great language implementation? Is there/has there been a general feeling
> that it's time to "move past" Fortran in that field?
Very good questions indeed. I cannot easily give an answer to them.
Fact is that people move slowly. The use what they know and what has proven to work. Before they even think about changing, you'll have to demonstrate without a doubt that the alternative is superior. And even then, most will make a decision to change and need years before they find the time to actually do the step.
In my immediate environment, people use
* plain C, because they had some course as a junior
* Fortran, because it has great libraries
* Matlab, because it is so well documented and easy to start with
* Python, because it is a beautiful wrapper around ugly C/Fortran code
To pull any of them, it will take years. The only hope that I have is, that D gains momentum for its general purpose qualities, and when the Numerics people finally arrive, they realize that everything is prepared for them to dive in.
As far as I can observe, numerics people usually have a very pragmatic approach and take what's there. To invest in their support is a very long-term investment, but once we have them, we can be sure that it will pay back by their investment in the quality of compilers.
About the practical use of the vectorizing F95 features - I do not really know. I know that F95 is an awfully complicated language and that the implementations are far behind C++. I know that many people use F90 compilers only because of the nicer syntax but stick to their well-known programming style. The world is changing awfully slow...
|
February 17, 2005 Re: Possible rewrite of array operation spec | ||||
---|---|---|---|---|
| ||||
Posted in reply to Norbert Nemec | In article <cv27t5$2k6$1@digitaldaemon.com>, Norbert Nemec says... > >Dave schrieb: >> Norbert - a few questions on all this if you have the time. >> >> How has the F95 FORALL statement gone over in numerical computing? Is it being used in a lot of codes and/or has there been a lot of software being re-written to use it? How are the optimizing compilers dealing with it - are they using it to good advantage? >> >> I gather there has been at least a little movement towards C/++ from Fortran, especially since more and more numerical software specialists have gotten into the field and pried the keyboard out of the hands of the people with the white lab coats. Problem has been that Fortran is so darn good at what it does. So, Is it possible for D (done correctly) to attract a good number of numerical computing people, or is Fortran so entrenched that this would be difficult with even a great language implementation? Is there/has there been a general feeling that it's time to "move past" Fortran in that field? > >Very good questions indeed. I cannot easily give an answer to them. > >Fact is that people move slowly. The use what they know and what has proven to work. Before they even think about changing, you'll have to demonstrate without a doubt that the alternative is superior. And even then, most will make a decision to change and need years before they find the time to actually do the step. > >In my immediate environment, people use >* plain C, because they had some course as a junior >* Fortran, because it has great libraries >* Matlab, because it is so well documented and easy to start with >* Python, because it is a beautiful wrapper around ugly C/Fortran code > >To pull any of them, it will take years. The only hope that I have is, that D gains momentum for its general purpose qualities, and when the Numerics people finally arrive, they realize that everything is prepared for them to dive in. > >As far as I can observe, numerics people usually have a very pragmatic approach and take what's there. To invest in their support is a very long-term investment, but once we have them, we can be sure that it will pay back by their investment in the quality of compilers. > >About the practical use of the vectorizing F95 features - I do not really know. I know that F95 is an awfully complicated language and that the implementations are far behind C++. I know that many people use F90 compilers only because of the nicer syntax but stick to their well-known programming style. The world is changing awfully slow... Aye, in some ways at least. Maybe D can change some of that - I think the array operations that you, Walter and Stewart (sorry if I forgot anyone) are hashing out may be a big part of it. Even if the numerics developers are slow on the uptake, I bet the rest of us will find some use for what you're discussing! Thanks, - Dave |
February 17, 2005 Re: Possible rewrite of array operation spec | ||||
---|---|---|---|---|
| ||||
Posted in reply to Stewart Gordon | >> but a[]=b doesn't look like a can be [re]allocated (and it can be, if >> it is the wrong size or null). anyhow, it's not that important :) > > What would be the sense of assigning in-place if the destination array > is going to be either the wrong size or null? that would, of course, make no sense :) that's why I don't like a[]=b+c; a[] implies that a is already allocated and the right size (you even state that yourself below).. With what you're suggesting, any code that cares about performance will look like: while (...) { if (a==null || a.length!=x.length) a=new int[x.length]; a[]=x+y; ... } And I'd like it to simply look like while (...) { a=x+y; ... } while having the same thing done performance.. > I see two motives for assigning in-place: > > - to keep the data in sync when there are multiple references to it. > But this already isn't going to work if you need to keep resizing the array, unless you wrap the array in a pointer or class to make it work. I don't think most cases will be working with arrays of multiple sizes; when they do, my guess that the actual arrays will already be wrapped with their meta-data.. And like I suggested, you can alternatively leave other references alone by doing a=(x+y).dup where it's at least obvious you want the allocation done. > - to save the overhead of memory allocation during calculations. But > when the arrays can arbitrarily change in size, this overhead just comes > back. True, but when the arrays don't arbitrarily change (like I said, IMO that is the majority), there's a chance to save a lot of overhead (with small arrays, memory allocation will easily take more time than calculations, so what's the point of having compiler support anyway then?). > I'm not sure what you mean by this. My spec was written with three basic intentions: > > (a) to be well-defined > (b) to keep D consistent within itself > (c) to be backward compatible with the current assignment semantics I don't see how either of these is broken by reusing the result array even when [] is not used. The spec can easily be well-defined by "if the result is assigned to an array reference which is non-null and of exactly the same dimensions as the result, its allocated memory will be reused; otherwise, a new array will be allocated to store the result." And that's far more similar to how slices work now (memory is reused, unless you extend a slice beyond the original size). As for consistency, consider: SomeClass a=new ...; SomeClass b=a; a+=5; // now, a is still the same object and a===b ---------- int[] a=new ...; int[] b=a; a+=5; // with my suggestion, a is still the same object and a===b // according to your spec a!==b OK, granted, reuse also breaks some consistency, but so does reallocating always. > Do you actually understand how my spec works? Completely :) > Let's look at some examples mechanically. > > Current D (semantics will be preserved): These all stay the same, even if arrays are reused. > With array ops: > > z = x + y; > > create an array of x[i] + y[i] > assign this new array by reference to z I really fail to see why a new array is necessary here, if it already exists. To me it looks the same, as if: int a=3; int* b=&a; a=2+3; // or even a+=2 if (*b==5) { // this is normal } else { // this is what you're suggesting with arrays } Now that I think about it, I don't even think the result should be completely new, instead its length can be adjusted. Then, you can allocate a big chunk of memory (to hold even your biggest inputs) and just use it without any allocation whatsoever. Basically, instead of what you wrote, z=x+y should translate to: -------------------------- assert(x.length=y.length); if (z==null) z=new int[x.length]; else if (z.length!=x.length) { // unless this is already checked z.length=x.length; } for(...) { ... } -------------------------- and z[]=x+y should translate to -------------------------- assert(z!=null && z.length==x.length && x.length==y.length); for(...) { ... } -------------------------- This means that z[] is expected to be non-null and the same size as x and y (and it is an error if it is not so), exactly like it is now when arrays are just copied (and that's the only current array op, afaik). > z = x * 2 + y; > z[] = x * 2 + y; This is exactly the same case. > <snip> > > Indeed, there's no reason we can't have both the struct and plain minEl and maxEl. Have you even read what I wrote? What type would the struct be? It'd have to be MinMaxValues!(int) or something. Like I said, that needlessly instantiates templates and having .count(value) is more useful as it can be used for things other than counting min/max values.. Actually, min/maxElIndex and count are all that is necessary, although data.minEl does looks better than data[data.minElIndex]. To finish this post, I'd like to reiterate again that having array ops is not important just because of prettier syntax but because of the speed the compiler can achieve by exploiting the knowledge it gets when you use such operations (e.g. the whole point of Expression templates in C++ is to have the compiler see what it is you want to do, rather than just seeing parts of it). I assume you agree. Now, if speed is important, you don't want to waste time allocating memory (it costs allocation, collection of the old array, breaks cache on processor etc. etc). So, it is better to reuse the array even when the programmer forgots to do so (or is too lazy to write the checks), as most probably, it was still the effect he wanted. If it is not, he can still easily create new arrays explicitly just by typing .dup, which is far less characters than those nulls and lengths checking :) Finally, consider all the potential users that D will lose without this. I bet that someone that wants to evaluate D will not read enough to know better and will write a=b+c instead of a[]=b+c. Running that in a loop (of, say, 5_000_000_000 iterations :) just to see performance will make him run away, as billions of new vectors will get allocated. Why is it so slow? Why did something so simple allocate MBs of memory? I thought native code was supposed to be fast, so I guess this D and its compiler really suck. I'd better learn Fortran! :) xs0 |
February 17, 2005 Re: Possible rewrite of array operation spec | ||||
---|---|---|---|---|
| ||||
Posted in reply to xs0 | xs0 wrote: <snip> > that's why I don't like a[]=b+c; a[] implies that a is already allocated and the right size (you even state that yourself below).. With what you're suggesting, any code that cares about performance will look like: Code that cares about performance would probably be written with at least some preconception of whether the array is going to be the same size. > while (...) { > if (a==null || a.length!=x.length) > a=new int[x.length]; > a[]=x+y; > ... > } > > And I'd like it to simply look like > > while (...) { > a=x+y; > ... > } How about this? while (...) { a.length = x.length; a[] = x + y; } (Assuming that the contents of ... have some side effect on the length of x - otherwise how about making it even more efficient by putting the length assignment outside the loop?) > while having the same thing done performance.. > >> I see two motives for assigning in-place: >> >> - to keep the data in sync when there are multiple references to it. >> But this already isn't going to work if you need to keep resizing the array, unless you wrap the array in a pointer or class to make it work. > > I don't think most cases will be working with arrays of multiple sizes; Exactly. So it seems silly to convolute the language semantics for this minority of cases. <snip> > True, but when the arrays don't arbitrarily change (like I said, IMO that is the majority), there's a chance to save a lot of overhead (with small arrays, memory allocation will easily take more time than calculations, so what's the point of having compiler support anyway then?). Exactly. Then one would use the []. >> I'm not sure what you mean by this. My spec was written with three basic intentions: >> >> (a) to be well-defined >> (b) to keep D consistent within itself >> (c) to be backward compatible with the current assignment semantics > > > I don't see how either of these is broken by reusing the result array even when [] is not used. Where a is a dynamic array, a = ... by definition does a reference assignment. <snip> > As for consistency, consider: > > SomeClass a=new ...; > SomeClass b=a; > > a+=5; > > // now, a is still the same object and a===b Yes, iff the class defines opAddAssign. (At least from what I can make of the spec.) > ---------- > > int[] a=new ...; > int[] b=a; > > a+=5; > > // with my suggestion, a is still the same object and a===b > // according to your spec a!==b > > OK, granted, reuse also breaks some consistency, but so does reallocating always. Hmm.... >> Do you actually understand how my spec works? > > Completely :) > >> Let's look at some examples mechanically. > >> >> Current D (semantics will be preserved): > > > These all stay the same, even if arrays are reused. Just think about it. Suppose z = x; does a reference assignment, but z = x + y; does an in-place modification. Then you are changing the semantics of the = operator by changing the right operand. And you're not even changing the type of the right operand, only its form. This is a cause of confusion that is bound to lead to bugs, never mind trying to generalise the semantics of = applied to arbitrary expressions. >> With array ops: >> >> z = x + y; >> >> create an array of x[i] + y[i] >> assign this new array by reference to z > > I really fail to see why a new array is necessary here, if it already exists. To me it looks the same, as if: Because this is what the programmer asked for. <snip> > So, it is better to reuse the array even when the programmer forgots to do so (or is too lazy to write the checks), as most probably, it was still the effect he wanted. If it is not, he can still easily create new arrays explicitly just by typing .dup, which is far less characters than those nulls and lengths checking :) <snip> As has been said plenty of times, a program is only as good as the person who wrote it. And so if the programmer is lazy, he/she/it shouldn't be too surprised if the program is lazy. Stewart. -- My e-mail is valid but not my primary mailbox. Please keep replies on the 'group where everyone may benefit. |
February 17, 2005 Re: Possible rewrite of array operation spec | ||||
---|---|---|---|---|
| ||||
Posted in reply to Stewart Gordon | > How about this? > > while (...) { > a.length = x.length; > a[] = x + y; > } Again, why would this not be the default case (i.e. done by the compiler?) Also consider that if a is int[][][], you'll also need to allocate all the int[][]'s and really really quickly that a=x+y becomes totally invisible, all because you didn't want to change your spec (which is completely fine, aside from the issue we're arguing over). And I'd guess that only the outer array gets reused with a[]=x+y? So what would you have the user type then? a[][][]=x+y? That's probably not even legal.. And what if a is of type T as in template(T)? > Exactly. So it seems silly to convolute the language semantics for this minority of cases. There's nothing convoluted.. both a= and a[]= are defined only for things that are currently supported. x+y on arrays is not defined currently, so you can define = for array ops as you want. = doesn't do the same for structs and classes either, and no one seems to mind (even though they're really similar otherwise). > <snip> you tend to snip my best arguments, methinks :P > Where a is a dynamic array, a = ... by definition does a reference assignment. I don't agree there's any such definition, but let's not go there. What if it is a static array, you'll force the users to type [] every time? When they (this time really) obviously want it in-place. Or would you have it work differently in each case? > Yes, iff the class defines opAddAssign. (At least from what I can make of the spec.) obviously.. the point was, however, that a and b still point to the same object. a+=b acts like in-place for classes, is in-place for primitives, so why would it be different for arrays? >> int[] a=new ...; >> int[] b=a; >> >> a+=5; >> >> // with my suggestion, a is still the same object and a===b >> // according to your spec a!==b >> >> <snip> > > > Hmm.... Hmm what? > Just think about it. Suppose > > z = x; > > does a reference assignment, but > > z = x + y; > > does an in-place modification. Maybe, but z+=x certainly indicates in-place modification, so it would seem you can't have it totally consistent anyhow.. If that is the case I'd certainly prefer in-place whenever possible. > <snip> The semantics of the = operator are not always the same even without array ops. x+y is also not defined to be anything in particular (currently). Why do you keep insisting that they are? Considering that your spec itself says that the effect is the same as if you wrote the indicated code, you can just change the expansion in the spec to not reallocate when not necessary and there you have it. >>> z = x + y; >> I really fail to see why a new array is necessary here, if it already exists. To me it looks the same, as if: > > Because this is what the programmer asked for. No, he didn't. I can't see from that statement that the programmer wishes to allocate a new z. _You_ say that is what he asked for; all I can see is he wanted z to contain the sum and if he really wanted a new array, he'd write (x+y).dup. It's the same with slices - sometimes you get a completely new memory space, and sometimes you don't, and the default is what's most efficient ; how come it doesn't bother anyone that setting subslice.length can have the effect of losing the reference to original memory? And that's exactly the same thing - you get to reuse memory when possible, and other cases are handled as well as they can be automatically. When you're certain you want a stand-alone copy, you use .dup, and that's it. >> <snip on newbies> > <snip on newbies suck> Well, considering that everyone is a newbie at first, and that D does need more users, saying "they suck so why deal with them" is not helping anything.. class Sumator(T) { T sum; void set(T val) { sum=val; } void add(T val) { sum+=val; } T get() { return sum; } } Newbie or not, Sumator!(int) is fine, while Sumator!(int[]) totally sucks (unless, of course, you prefer code that runs really slowly) and you can't even make it better, unless you specialize it for all array dimensions in which you use it, which makes using a template pointless.. For what reason? And this is just a trivial case... To sum up, you'd have stuff defined like this: a = b + c; // create a new array (really bad performance-wise, // but still desired behavior like 1% of time) a[] = b + c; // fail if a is null/wrong size, otherwise work in-place // useful when the operands are really known to be the same // size all the time (that would be like 20% of time) a = (b+c).dup; // same as a=b+c (and as useless) And I'd have it defined like this: a = b + c; // work in-place when possible (useful like 80% of the time) a[] = b + c; // same as above a = (b+c).dup; // same as above So you'd have two syntaxes for the same crappy-most-of-the-time behavior, and you'd have the programmer write additional code for the most common case (for handling arbitrary lengths with memory reuse). Would you agree that is a good summary? xs0 |
February 17, 2005 Re: Possible rewrite of array operation spec | ||||
---|---|---|---|---|
| ||||
Posted in reply to xs0 | On Thu, 17 Feb 2005 17:29:44 +0100, xs0 <xs0@xs0.com> wrote:
>>> but a[]=b doesn't look like a can be [re]allocated (and it can be, if
>>> it is the wrong size or null). anyhow, it's not that important :)
>> What would be the sense of assigning in-place if the destination array
>> is going to be either the wrong size or null?
>
> that would, of course, make no sense :)
>
> that's why I don't like a[]=b+c; a[] implies that a is already allocated and the right size (you even state that yourself below).. With what you're suggesting, any code that cares about performance will look like:
>
>
> while (...) {
> if (a==null || a.length!=x.length)
> a=new int[x.length];
> a[]=x+y;
> ...
> }
>
> And I'd like it to simply look like
>
> while (...) {
> a=x+y;
> ...
> }
>
> while having the same thing done performance..
Doesn't array bounds checking handle this?
With bounds checking on, it will be handled at runtime with an exception.
With it off, it will be fast as it has no checking.
Regan
|
Copyright © 1999-2021 by the D Language Foundation