www.digitalmars.com         C & C++   DMDScript  

D - Spec Clarification: Can .length be set?

reply Russ Lewis <russ deming-os.org> writes:
I'm assuming that the .length property of a dynamic array can be set,
causing the code to change the size, right?  This is not specified in
the spec, that I can see.

Also, I assume that such a resize operation can (if expanding) result in
an out-of-memory exception being thrown, just like operator new.  I
don't see specs for either of those...
Sep 05 2001
next sibling parent "Bradeeoh" <bradeeoh crosswinds.net> writes:
Walter may bash me down as wrong on this one, but it was always my
understanding that the .length variable of arrays was a read only property
of the array, exactly as in Java, initialized upon creation of the array.

-Brady

"Russ Lewis" <russ deming-os.org> wrote in message
news:3B96A34F.DABE45E5 deming-os.org...
 I'm assuming that the .length property of a dynamic array can be set,
 causing the code to change the size, right?  This is not specified in
 the spec, that I can see.

 Also, I assume that such a resize operation can (if expanding) result in
 an out-of-memory exception being thrown, just like operator new.  I
 don't see specs for either of those...
Sep 05 2001
prev sibling next sibling parent reply "Walter" <walter digitalmars.com> writes:
I've gone back and forth on this issue (whether setting .length resizes the
array, or is it read-only). What do y'all think?


Russ Lewis wrote in message <3B96A34F.DABE45E5 deming-os.org>...
I'm assuming that the .length property of a dynamic array can be set,
causing the code to change the size, right?  This is not specified in
the spec, that I can see.

Also, I assume that such a resize operation can (if expanding) result in
an out-of-memory exception being thrown, just like operator new.  I
don't see specs for either of those...
Sep 05 2001
next sibling parent Dan Hursh <a b.c> writes:
	Resizing is good.  I don't mind the syntax.  If the setter/getter stuff
doesn't work out, the syntax might feel a bit like an anomaly.
	Not directly related, but have you though any more about
differentiating between attributes and members in structs?

Dan

Walter wrote:
 
 I've gone back and forth on this issue (whether setting .length resizes the
 array, or is it read-only). What do y'all think?
 
 Russ Lewis wrote in message <3B96A34F.DABE45E5 deming-os.org>...
I'm assuming that the .length property of a dynamic array can be set,
causing the code to change the size, right?  This is not specified in
the spec, that I can see.

Also, I assume that such a resize operation can (if expanding) result in
an out-of-memory exception being thrown, just like operator new.  I
don't see specs for either of those...
Sep 05 2001
prev sibling next sibling parent Jan Knepper <jan smartsoft.cc> writes:
I think it should set the size of an array. I seem to remember from early
spec's that .length on character arrays would change if a longer string would
be assigned.
It would be cool to be able to truncate a string by just setting the .length.
(Just one thing). There are a lot more.

Jan



Walter wrote:

 I've gone back and forth on this issue (whether setting .length resizes the
 array, or is it read-only). What do y'all think?

 Russ Lewis wrote in message <3B96A34F.DABE45E5 deming-os.org>...
I'm assuming that the .length property of a dynamic array can be set,
causing the code to change the size, right?  This is not specified in
the spec, that I can see.

Also, I assume that such a resize operation can (if expanding) result in
an out-of-memory exception being thrown, just like operator new.  I
don't see specs for either of those...
Sep 05 2001
prev sibling next sibling parent reply Charles Hixson <charleshixsn earthlink.net> writes:
Walter wrote:

 I've gone back and forth on this issue (whether setting .length resizes the
 array, or is it read-only). What do y'all think?
 
 
 Russ Lewis wrote in message <3B96A34F.DABE45E5 deming-os.org>...
 
I'm assuming that the .length property of a dynamic array can be set,
causing the code to change the size, right?  This is not specified in
the spec, that I can see.

Also, I assume that such a resize operation can (if expanding) result in
an out-of-memory exception being thrown, just like operator new.  I
don't see specs for either of those...
Are you resizing the array, or just changing the length of it that is counted as filled? If you are resizing the array, then I don't like that syntax. It seems to imply that what you are doing is taking a string, and then saying "I'm interested in *this* much of it". I.e., it implies that all that you are doing is changing a variable. If this includes an implicit resize and potentially string copying and garbage collection, then it seems to be to be the wrong syntax. On the other hand, it would frequently be nice to take a block of text and say "this variable represents 20 characters starting at character 97". (But this doesn't seem to be what D strings are. Pity. Could you consider string range variables?)
Sep 06 2001
next sibling parent "Bradeeoh" <bradeeoh crosswinds.net> writes:
The length variable doesn't refer to how much of the array is filled.  It
refers to the capacity of the array.  Keep in mind, a length 20 int[] is
always filled with 20 ints - even if they were just initialized to zilch.

The debate is about whether or not length is a read only variable to learn
something about that particular array, or a property that can be set to
dynamically change the size of the array.

I agree with you on that note - changing the size of the array can
potentially be a process that's more invovled that just changing a length
variable.  That syntax doesn't seem appropriate for those circumstances.  I
think alot of the array implementation in D is shooting for similarities to
Java, and one thing that makes .length and other array properties work in
Java is that arrays are create-once, read-only.  Dynamic arrays are
implemented in a class (Vector) which takes care of capacity vs size, and
other administrative issues.

Which is why I'm still not exactly sure how D intends to do dynamic arrays.
Or, I guess, where it's going by trying to provide them.  In Java, .length
and other properties are handled by arrays being instances of the array
class, and the [bracket] notation merely being syntactic sugar on top of the
array object.  Try to provide the same facilities as Java's "Array", much
less the same facilities as Java's "Vector" as built in, primitive parts of
the language has never quite made sense to me (as to how it will actually
work).

-Brady

 Are you resizing the array, or just changing the length of it
 that is counted as filled?  If you are resizing the array, then
 I don't like that syntax.  It seems to imply that what you are
 doing is taking a string, and then saying "I'm interested in
 *this* much of it".  I.e., it implies that all that you are
 doing is changing a variable.  If this includes an implicit
 resize and potentially string copying and garbage collection,
 then it seems to be to be the wrong syntax.  On the other hand,
 it would frequently be nice to take a block of text and say
 "this variable represents 20 characters starting at character
 97".  (But this doesn't seem to be what D strings are.  Pity.
 Could you consider string range variables?)
Sep 06 2001
prev sibling parent reply Russ Lewis <russ deming-os.org> writes:
Charles Hixson wrote:

 Are you resizing the array, or just changing the length of it
 that is counted as filled?  If you are resizing the array, then
 I don't like that syntax.  It seems to imply that what you are
 doing is taking a string, and then saying "I'm interested in
 *this* much of it".  I.e., it implies that all that you are
 doing is changing a variable.  If this includes an implicit
 resize and potentially string copying and garbage collection,
 then it seems to be to be the wrong syntax.  On the other hand,
 it would frequently be nice to take a block of text and say
 "this variable represents 20 characters starting at character
 97".  (But this doesn't seem to be what D strings are.  Pity.
 Could you consider string range variables?)
If you are trying to get a substring of a string, just use this syntax: char[] longString = /*some code that creates a long string*/; char[] subString = longString[97..116]; /* contains 20 characters of the other string */ This (in cooperation with garbage collection) is going to be *really* nice for regular expressions. You can just return a dynamic array that is a subset of another string. Since strings are not null terminated in D, no copying is needed!
Sep 06 2001
next sibling parent Axel Kittenberger <axel dtone.org> writes:
 This (in cooperation with garbage collection) is going to be *really* nice
 for
 regular expressions.  You can just return a dynamic array that is a subset
 of
 another string.  Since strings are not null terminated in D, no copying is
 needed!
Have you considered taking a deeper look at phython? They call it slices, and implement them pretty well: There is more than just creating slices, you can compare them, reverse them, stack them, queue them, etc. etc. http://python.sourceforge.net/devel-docs/tut/node7.html Again people, I can only repeat myself, don't take on the script languages! They all run relative slow(er) on runtime, but you'll never be able to pit on them at syntax/comfort. We've just to distinquish what a language is for. Is in example D a procedural language or a function language? For a functional I would think having dynamic arrays in the language is nealy a must, for a procedural it's a counter indication. Don't try to be a pathic function language, you'll defintly loose against the true functionals, if you want to be a procedural language try to be a good one, and this means high control, predictable memory and code size. control on the generated output (in example allignment) and don't burn up on sugar that would fit better to a functional language. - Axel
Sep 06 2001
prev sibling next sibling parent reply Charles Hixson <charleshixsn earthlink.net> writes:
Russ Lewis wrote:

 Charles Hixson wrote:
 
 
Are you resizing the array, or just changing the length of it
that is counted as filled?  If you are resizing the array, then
I don't like that syntax.  It seems to imply that what you are
doing is taking a string, and then saying "I'm interested in
*this* much of it".  I.e., it implies that all that you are
doing is changing a variable.  If this includes an implicit
resize and potentially string copying and garbage collection,
then it seems to be to be the wrong syntax.  On the other hand,
it would frequently be nice to take a block of text and say
"this variable represents 20 characters starting at character
97".  (But this doesn't seem to be what D strings are.  Pity.
Could you consider string range variables?)
If you are trying to get a substring of a string, just use this syntax: char[] longString = /*some code that creates a long string*/; char[] subString = longString[97..116]; /* contains 20 characters of the other string */ This (in cooperation with garbage collection) is going to be *really* nice for regular expressions. You can just return a dynamic array that is a subset of another string. Since strings are not null terminated in D, no copying is needed!
I was actually talking about using a substring *without* taking it out of the string. Sort of a safe version of C's pointer to char variable. You might be able to declare that: char [] inline; declare inline [1,15] user_id; declare inline [16, 29] first_name; declare inline [35, 50] last_name; declare inline [16, 60] full_name; ... This would be read-only access within a routine, and could only be passed as a parameter with copy semantics (which would negate much of the benefit), but it could be quite useful in making code easier to read without requiring excessive string copying. Or perhaps an optimizer could avoid the extra string copies. I don't know. But from my simple view it would be easier to read in a record as a string with (overlapping) fields defined on it, and then operate on those. This would let one say something like: the_name = trim (last_name) + ", " + trim (first_name) rather than the equivalent the_name = trim (substring(inline, 35, 15) ) + ", " + trim (substring(inline, 1, 15) ) One could, of course have defined intermediate variables, but then one would be doing an extra copy for each field for each record (unless an optimizer could decide that the extra copy wasn't needed without being told).
Sep 06 2001
parent reply Russ Lewis <russ deming-os.org> writes:
Charles Hixson wrote:

 I was actually talking about using a substring *without* taking
 it out of the string.  Sort of a safe version of C's pointer to
 char variable.  You might be able to declare that:
 char [] inline;
 declare inline [1,15] user_id;
 declare inline [16, 29] first_name;
 declare inline [35, 50] last_name;
 declare inline [16, 60] full_name;
 ...
Right, my understanding is that you could do the following: void foo(char[] data) // data is passed by reference, NOT value { char[] user_id = data[1..15]; char[] first_name = data[16..29]; char[] last_name = data[35..50]; char[] full_name = data[16..60]; user_id = data[1..15]; first_name = data[16..29]; last_name = data[35..50]; full_name = data[16..60]; ... }; As I understand it, none of this does any string copying. All of the field arrays point into the main array (and, BTW, count as references to the main array - so you won't get garbage collected at the wrong time).
 the_name = trim (last_name) + ", " + trim (first_name)
Similarly, the beauty of D dynamic arrays is that the trim function can return an array that points into the original argument but has a different length. Once it is used in the concatenation process, that reference to the array goes away automagically....
Sep 06 2001
parent reply Charles Hixson <charleshixsn earthlink.net> writes:
Russ Lewis wrote:

 Charles Hixson wrote:
 
 
I was actually talking about using a substring *without* taking
it out of the string.  Sort of a safe version of C's pointer to
char variable.  You might be able to declare that:
char [] inline;
declare inline [1,15] user_id;
declare inline [16, 29] first_name;
declare inline [35, 50] last_name;
declare inline [16, 60] full_name;
...
Right, my understanding is that you could do the following: void foo(char[] data) // data is passed by reference, NOT value { char[] user_id = data[1..15]; char[] first_name = data[16..29]; char[] last_name = data[35..50]; char[] full_name = data[16..60]; user_id = data[1..15]; first_name = data[16..29]; last_name = data[35..50]; full_name = data[16..60]; ... }; As I understand it, none of this does any string copying. All of the field arrays point into the main array (and, BTW, count as references to the main array - so you won't get garbage collected at the wrong time).
the_name = trim (last_name) + ", " + trim (first_name)
Similarly, the beauty of D dynamic arrays is that the trim function can return an array that points into the original argument but has a different length. Once it is used in the concatenation process, that reference to the array goes away automagically....
Thanks, that sounds like *just* what I was asking for! (And a bit more, as it can be passed as a parameter.) (And a bit less, as the original string isn't "safe" from the references.)
Sep 07 2001
parent reply "Walter" <walter digitalmars.com> writes:
Charles Hixson wrote in message <3B98DD7E.6030905 earthlink.net>...
Thanks, that sounds like *just* what I was asking for!  (And a
bit more, as it can be passed as a parameter.)  (And a bit less,
as the original string isn't "safe" from the references.)
There is a bit of a dark side to this. The trouble is that resizing a dynamic array has the semantics of a "realloc". This means it can be copied, but might not be. Thus, if you are holding another reference to the same array, you can get indeterminate behavior: char foo[]; foo = new char[50]; foo[6] = 'b'; char bar[] = foo; // foo and bar point to the same data bar.length = 55; // now foo and bar may or may not point to the same data bar[6] = 'a'; // is foo[6] now 'a' or 'b'? Now, foo's data won't be free'd, because the gc will find it is still pointed to by foo, so at least this won't produce a pointer bug. If anyone has a good solution to this problem, I'd like to hear it. I don't want to make a resize into an "always copy" semantics, for performance reasons.
Sep 08 2001
parent reply a <a b.c> writes:
Walter wrote:
 
 Charles Hixson wrote in message <3B98DD7E.6030905 earthlink.net>...
Thanks, that sounds like *just* what I was asking for!  (And a
bit more, as it can be passed as a parameter.)  (And a bit less,
as the original string isn't "safe" from the references.)
There is a bit of a dark side to this. The trouble is that resizing a dynamic array has the semantics of a "realloc". This means it can be copied, but might not be. Thus, if you are holding another reference to the same array, you can get indeterminate behavior: char foo[]; foo = new char[50]; foo[6] = 'b'; char bar[] = foo; // foo and bar point to the same data bar.length = 55; // now foo and bar may or may not point to the same data bar[6] = 'a'; // is foo[6] now 'a' or 'b'? Now, foo's data won't be free'd, because the gc will find it is still pointed to by foo, so at least this won't produce a pointer bug. If anyone has a good solution to this problem, I'd like to hear it. I don't want to make a resize into an "always copy" semantics, for performance reasons.
I wish I had an answer, and I'm afraid I might make things worse. What happens here? char foo[]; foo = "Hi there!"; // 9 character string char bar[] = foo; // we share it foo.length = foo.length - 1; // now foo is 8 char, possibly a word boundary bar[8]; // could this now be unallocated space? I guess I'm not sure of the specifics here, but it seems that after a decrease in size, that a part of unallocated or (worse) reallocated memory could still be accessed. My best guess here is to never actually shrink the allocated memory whether or not it is unused, but that could create other nasty memory leaks. Dan
Sep 08 2001
parent "Walter" <walter digitalmars.com> writes:
a wrote in message <3B9A77F3.F62BC5BE b.c>...
What
happens here?

 char foo[];
 foo = "Hi there!";              // 9 character string
 char bar[] = foo;               // we share it
 foo.length = foo.length - 1;    // now foo is 8 char, possibly a word
boundary
 bar[8];                         // could this now be unallocated space?

I guess I'm not sure of the specifics here, but it seems that after a
decrease in size, that a part of unallocated or (worse) reallocated
memory could still be accessed.  My best guess here is to never actually
shrink the allocated memory whether or not it is unused, but that could
create other nasty memory leaks.
The memory leak issue won't happen, because the garbage collected realloc does not just free the old storage. It will only free it if no other references to it exist.
Sep 08 2001
prev sibling parent "Walter" <walter digitalmars.com> writes:
Russ Lewis wrote in message <3B97CEF7.6223A784 deming-os.org>...
This (in cooperation with garbage collection) is going to be *really* nice
for
regular expressions.  You can just return a dynamic array that is a subset
of
another string.  Since strings are not null terminated in D, no copying is
needed!
Being able to "map" arrays onto other arrays, no copying necessary, can result in some large performance boosts over the traditional way of doing C strings.
Sep 08 2001
prev sibling next sibling parent reply Russell Borogove <kaleja estarcion.com> writes:
Walter wrote:
 
 I've gone back and forth on this issue (whether setting .length resizes the
 array, or is it read-only). What do y'all think?
I think I'm in favor. Is there any other way to resize an array already provided? -RB
Sep 06 2001
parent reply "Walter" <walter digitalmars.com> writes:
"Russell Borogove" <kaleja estarcion.com> wrote in message
news:3B97D5B9.9FF40BD7 estarcion.com...
 Walter wrote:
 I've gone back and forth on this issue (whether setting .length resizes
the
 array, or is it read-only). What do y'all think?
I think I'm in favor. Is there any other way to resize an array already provided? -RB
The current way is to new a new array and copy the contents of the old one. Such always seemed like too much fiddling to me, and fiddling code is just more code that harbors bugs. The three choices are: array.length = newlength; array = renew(array, newlength, array[0].size); array.setLength(newlength); I am leaning towards the first because it is simpler and so less prone to bugs. What I don't like about it is it appears to be a simple assignment, but is not.
Sep 06 2001
next sibling parent Russ Lewis <russ deming-os.org> writes:
Walter wrote:

 The current way is to new a new array and copy the contents of the old one.
 Such always seemed like too much fiddling to me, and fiddling code is just
 more code that harbors bugs. The three choices are:

     array.length = newlength;

     array = renew(array, newlength, array[0].size);

     array.setLength(newlength);

 I am leaning towards the first because it is simpler and so less prone to
 bugs. What I don't like about it is it appears to be a simple assignment,
 but is not.
4th option: array.append(int[10]); I think that it's better to have the syntax match programmer conception rather than internal construction. I believe that there are 3 types of programmers: Experts: understand the language and compiler in depth. Are fully aware of the impact of their code. Shortcuts (like setting .length) just let them code more quickly, efficiently, and accurately. Newbies/Scripters: only have a vague understanding of the language and the syntax. Either don't know or don't care what impact their shortcuts have on runtime. Intermediates (most programmers): have a good understanding of the language, though not expert level. Understand some key performance drains (mostly what they've read about in textbooks or the web), but sometimes are inefficient. Most programmers are intermediates. IMHO, experts will use your language only if they find in it an efficient way to express the algorithm they're thinking of. D's roots in C/C++ mean that we'll get a lot of those. They will set .length if appropriate, or use other algorithms if they think that something else is better. Newbies will use only what they can learn and understand quickly. Setting .length is good for them, since they can easily see what it does (though they have no idea how it does it). Some intermediates will use .length judiciously, knowing its cost. Others will abuse it. Having the language easy to read encourages newbies to become intermediates, since it's easy to use and come to know the language. Similarly, it encourages intermediates to become experts, as they spend less time learning (and relearning) the syntax of the language and more time getting (or reading/hearing about) real experience with the language. So that's my $.02
Sep 06 2001
prev sibling next sibling parent reply Russell Borogove <kaleja estarcion.com> writes:
Walter wrote:
 
 "Russell Borogove" <kaleja estarcion.com> wrote in message
 news:3B97D5B9.9FF40BD7 estarcion.com...
 I think I'm in favor. Is there any other way to resize an array
 already provided?
The current way is to new a new array and copy the contents of the old one.
There are cases where you have a very large array in an "unpacked" or otherwise wasteful format, and you want to convert the data in place to a more compact format. In this case, if you have to create a new array and compact-on-copy, you might be spending more memory than you want to in the intermediate case. (Obviously, to make this work, your data-typing has to be fairly weak.) With a truncating resize, you can get through a memory-tight situation that you can't survive otherwise.
 Such always seemed like too much fiddling to me, and fiddling code is just
 more code that harbors bugs. The three choices are:
 
     array.length = newlength;
 
     array = renew(array, newlength, array[0].size);
 
     array.setLength(newlength);
 
 I am leaning towards the first because it is simpler and so less prone to
 bugs. What I don't like about it is it appears to be a simple assignment,
 but is not.
*nod* Russ Lewis wrote:
 
 4th option:
 array.append(int[10]);
But this doesn't offer a truncation semantic. -RB
Sep 06 2001
parent reply Chris Holland <cholland whitecapdirect.com> writes:
Just found this thread.. but you could handle this java'esq

give arrays another property called capacity.

int[] dyn;

dyn.capacity = 500
dyn.length   = 100

dyn[] = 1;

dyn.length     = 200
dyn[101...500] = 2

not sure if the array slice can be an lvalue.

Regardless you get control of the allocation and control of the data.

-Chris


Russell Borogove wrote:

 
 
 Walter wrote:
 
 "Russell Borogove" <kaleja estarcion.com> wrote in message
 news:3B97D5B9.9FF40BD7 estarcion.com...
 I think I'm in favor. Is there any other way to resize an array
 already provided?
The current way is to new a new array and copy the contents of the old one.
There are cases where you have a very large array in an "unpacked" or otherwise wasteful format, and you want to convert the data in place to a more compact format. In this case, if you have to create a new array and compact-on-copy, you might be spending more memory than you want to in the intermediate case. (Obviously, to make this work, your data-typing has to be fairly weak.) With a truncating resize, you can get through a memory-tight situation that you can't survive otherwise.
 Such always seemed like too much fiddling to me, and fiddling code is
 just more code that harbors bugs. The three choices are:
 
     array.length = newlength;
 
     array = renew(array, newlength, array[0].size);
 
     array.setLength(newlength);
 
 I am leaning towards the first because it is simpler and so less prone to
 bugs. What I don't like about it is it appears to be a simple assignment,
 but is not.
*nod* Russ Lewis wrote:
 
 4th option:
 array.append(int[10]);
But this doesn't offer a truncation semantic. -RB
Sep 20 2001
parent Chris Holland <cholland whitecapdirect.com> writes:
Oops I already have a bug... the lvalue should throw an array out of 
bounds.. off the topic though.

-Chris

Chris Holland wrote:

 Just found this thread.. but you could handle this java'esq
 
 give arrays another property called capacity.
 
 int[] dyn;
 
 dyn.capacity = 500
 dyn.length   = 100
 
 dyn[] = 1;
 
 dyn.length     = 200
 dyn[101...500] = 2
 
 not sure if the array slice can be an lvalue.
 
 Regardless you get control of the allocation and control of the data.
 
 -Chris
 
 
 Russell Borogove wrote:
 
 
 
 Walter wrote:
 
 "Russell Borogove" <kaleja estarcion.com> wrote in message
 news:3B97D5B9.9FF40BD7 estarcion.com...
 I think I'm in favor. Is there any other way to resize an array
 already provided?
The current way is to new a new array and copy the contents of the old one.
There are cases where you have a very large array in an "unpacked" or otherwise wasteful format, and you want to convert the data in place to a more compact format. In this case, if you have to create a new array and compact-on-copy, you might be spending more memory than you want to in the intermediate case. (Obviously, to make this work, your data-typing has to be fairly weak.) With a truncating resize, you can get through a memory-tight situation that you can't survive otherwise.
 Such always seemed like too much fiddling to me, and fiddling code is
 just more code that harbors bugs. The three choices are:
 
     array.length = newlength;
 
     array = renew(array, newlength, array[0].size);
 
     array.setLength(newlength);
 
 I am leaning towards the first because it is simpler and so less prone
 to bugs. What I don't like about it is it appears to be a simple
 assignment, but is not.
*nod* Russ Lewis wrote:
 
 4th option:
 array.append(int[10]);
But this doesn't offer a truncation semantic. -RB
Sep 20 2001
prev sibling next sibling parent "Bradeeoh" <bradeeoh crosswinds.net> writes:
I just spoke on this one in a different part of this thread.  The first one
does have a nice simplicity to it, but I would be concerned to stay away
from it for the very reason you say - it looks like a simple assignment when
it's really not.

I vote for 3 (though in my other response the function name I chose was
'resize( newlength )' )

-Brady

 The current way is to new a new array and copy the contents of the old
one.
 Such always seemed like too much fiddling to me, and fiddling code is just
 more code that harbors bugs. The three choices are:

     array.length = newlength;

     array = renew(array, newlength, array[0].size);

     array.setLength(newlength);

 I am leaning towards the first because it is simpler and so less prone to
 bugs. What I don't like about it is it appears to be a simple assignment,
 but is not.
Sep 06 2001
prev sibling parent reply Charles Hixson <charleshixsn earthlink.net> writes:
Walter wrote:

 "Russell Borogove" <kaleja estarcion.com> wrote in message
 news:3B97D5B9.9FF40BD7 estarcion.com...
 
Walter wrote:

I've gone back and forth on this issue (whether setting .length resizes
the
array, or is it read-only). What do y'all think?
I think I'm in favor. Is there any other way to resize an array already provided? -RB
The current way is to new a new array and copy the contents of the old one. Such always seemed like too much fiddling to me, and fiddling code is just more code that harbors bugs. The three choices are: array.length = newlength; array = renew(array, newlength, array[0].size); array.setLength(newlength); I am leaning towards the first because it is simpler and so less prone to bugs. What I don't like about it is it appears to be a simple assignment, but is not.
I would prefer: array.setLength(newLength); This is clearly a method call. The first choice looks to me like you are adjusting a variable that says how much of it you are using, and this isn't what you mean (though it might be nice to have such a value...size? [I would have choosen length to mean that, but size is a good alternative, and they mean about the same]. Possibly contains? Or cells_used? That is one that it would make sense to have with variable semantics, since all that it is is an internal variable. my second choice would be: array = array.asSize(newSize); This syntax makes it clear that a copy of the array is being done. I just don't like the name, and haven't been able to think of a decent on that makes the function clear. Again, this is clearly a method call. Possibly the name could be "copyWithSize", but that isn't a good choice if it's the only way to do it. It's too long a name for such a common operation.
Sep 06 2001
parent reply Russ Lewis <russ deming-os.org> writes:
Charles Hixson wrote:

 This is clearly a method call.  The first choice looks to me
 like you are adjusting a variable that says how much of it you
 are using, and this isn't what you mean (though it might be nice
 to have such a value...size?
size would be a good choice, but it's already a parameter that works a lot like a dynamic sizeof: int[] array = {3,4,5}; int len = array.length; /* returns 3 */ int size = array.size; /* returns 12, if you assume 32bit ints */
Sep 06 2001
parent reply "Walter" <walter digitalmars.com> writes:
Russ Lewis wrote in message <3B980568.6E0E71EC deming-os.org>...
size would be a good choice, but it's already a parameter that works a lot
like a
dynamic sizeof:
int[] array = {3,4,5};
int len = array.length; /* returns 3 */
int size = array.size; /* returns 12, if you assume 32bit ints */
Actually, no, .size returns 8 for arrays. The reason is because that's how much storage the reference takes up. .size doesn't refer to how much space the actual data in the array consumes. The reason it is this way is so you can sum the .size's of, say, a struct's members and arrive at the .size of the struct (assuming 1 byte alignment). Doing otherwise would lead to ambiguities, like what would the .size be for an array of arrays? To get the size of the data bytes in the array: array.length * array[0].size
Sep 06 2001
parent Russ Lewis <russ deming-os.org> writes:
Walter wrote:

 Russ Lewis wrote in message <3B980568.6E0E71EC deming-os.org>...
size would be a good choice, but it's already a parameter that works a lot
like a
dynamic sizeof:
int[] array = {3,4,5};
int len = array.length; /* returns 3 */
int size = array.size; /* returns 12, if you assume 32bit ints */
Actually, no, .size returns 8 for arrays. The reason is because that's how much storage the reference takes up. .size doesn't refer to how much space the actual data in the array consumes. The reason it is this way is so you can sum the .size's of, say, a struct's members and arrive at the .size of the struct (assuming 1 byte alignment). Doing otherwise would lead to ambiguities, like what would the .size be for an array of arrays? To get the size of the data bytes in the array: array.length * array[0].size
My mistake, sorry :)
Sep 07 2001
prev sibling parent reply a <a b.c> writes:
	A lot of people seem to think a lot of things.  I think the question
got over interpreted.  Walter, would it be safe to say that dynamic
arrays are not like other languages' Vector classes or script languages'
dynamic arrays?  Specifically in that D's dynamic arrays don't try to
provide enhanced appending, prepending, truncation, splicing or manage
how much space is allocated vs. used?
	Perhaps it would be safer for folks to think of a dynamic array in D as
a C dynamically allocated array that knows how much space it has
allocated?  Given that, it might be nice to have resizing done with a
property.  A method is apparently making people think that this is a
class with all sorts of nice features that it is not supposed to
provide.  Instead it is a basic type that abstracts way a very common
and error prone operation, realloc, so you can implement all of these
other wonderful abstractions with less worry.  Of course since realloc
is definitely an operation and not a trivial one, it would imply a
method would be the way to go.  How am I doing so far?
	In the end, property or method, I don't really care.  I guess I would
like the syntax that uses less typing, since I'm comfortable with the
operation that's happening.  I'm content with either, but I do think
that this thread has gone overboard with great expectations for a very
simple type & abstraction.  Are my expectation too low for what was
intended of the dynamic array?

	I would like a syntax that could do a resize in-place since the runtime
memory management system could probably do it when space allows. 
(Realloc works this way on most systems, right?)  Forcing a reassignment
would almost guarantee a copy whether or not it was really needed. 
Also, I would assume that any resize operation could potentially throw
an exception.  If so, then that should probably be considered with
respect to the whole exception specification issue.

	I guess I'll take the opportunity to provide another nudge for some
form of overloading while I'm at it.  If in fact D's dynamic arrays are
meant to be merely the primitive used to create these other spectacular
container types that people clamor for, it would be nice if the higher
level containers could have a square brace operator.

Dan


Walter wrote:
 
 I've gone back and forth on this issue (whether setting .length resizes the
 array, or is it read-only). What do y'all think?
 
 Russ Lewis wrote in message <3B96A34F.DABE45E5 deming-os.org>...
I'm assuming that the .length property of a dynamic array can be set,
causing the code to change the size, right?  This is not specified in
the spec, that I can see.

Also, I assume that such a resize operation can (if expanding) result in
an out-of-memory exception being thrown, just like operator new.  I
don't see specs for either of those...
Sep 06 2001
parent reply "Walter" <walter digitalmars.com> writes:
I've pretty much settled on the array.length=newlength version. Such also
fits in with the idea of a property assignment being a "put", which can be a
function call.

There are actually two dimensions to a dynamic array - the used length and
the allocated length, with used<=alloced. The implementation only carries
around the used length as the .length property. The alloced length is only
known to the garbage collector.

Resizing an array therefore must be integrated with the collector
implementation, so it could be reallocated in place, without copying, when
possible.

Another poster mentioned that the alloced length for a resizable array
should go in increments of powers of 2, I have empirically found this to be
most appropriate in my own work. Thus, dynamic arrays will be allocated in
power of 2 buckets, so resizing them will only require a copy operation if
it grows or shrinks over a power of 2 size.

a wrote in message <3B984E93.4A154FA4 b.c>...
 A lot of people seem to think a lot of things.  I think the question
got over interpreted.  Walter, would it be safe to say that dynamic
arrays are not like other languages' Vector classes or script languages'
dynamic arrays?  Specifically in that D's dynamic arrays don't try to
provide enhanced appending, prepending, truncation, splicing or manage
how much space is allocated vs. used?
 Perhaps it would be safer for folks to think of a dynamic array in D as
a C dynamically allocated array that knows how much space it has
allocated?  Given that, it might be nice to have resizing done with a
property.  A method is apparently making people think that this is a
class with all sorts of nice features that it is not supposed to
provide.  Instead it is a basic type that abstracts way a very common
and error prone operation, realloc, so you can implement all of these
other wonderful abstractions with less worry.  Of course since realloc
is definitely an operation and not a trivial one, it would imply a
method would be the way to go.  How am I doing so far?
 In the end, property or method, I don't really care.  I guess I would
like the syntax that uses less typing, since I'm comfortable with the
operation that's happening.  I'm content with either, but I do think
that this thread has gone overboard with great expectations for a very
simple type & abstraction.  Are my expectation too low for what was
intended of the dynamic array?

 I would like a syntax that could do a resize in-place since the runtime
memory management system could probably do it when space allows.
(Realloc works this way on most systems, right?)  Forcing a reassignment
would almost guarantee a copy whether or not it was really needed.
Also, I would assume that any resize operation could potentially throw
an exception.  If so, then that should probably be considered with
respect to the whole exception specification issue.

 I guess I'll take the opportunity to provide another nudge for some
form of overloading while I'm at it.  If in fact D's dynamic arrays are
meant to be merely the primitive used to create these other spectacular
container types that people clamor for, it would be nice if the higher
level containers could have a square brace operator.

Dan


Walter wrote:
 I've gone back and forth on this issue (whether setting .length resizes
the
 array, or is it read-only). What do y'all think?

 Russ Lewis wrote in message <3B96A34F.DABE45E5 deming-os.org>...
I'm assuming that the .length property of a dynamic array can be set,
causing the code to change the size, right?  This is not specified in
the spec, that I can see.

Also, I assume that such a resize operation can (if expanding) result in
an out-of-memory exception being thrown, just like operator new.  I
don't see specs for either of those...
Sep 06 2001
parent reply Russell Bornschlegel <kaleja estarcion.com> writes:
Walter wrote:
 Another poster mentioned that the alloced length for a resizable array
 should go in increments of powers of 2, I have empirically found this to be
 most appropriate in my own work. Thus, dynamic arrays will be allocated in
 power of 2 buckets, so resizing them will only require a copy operation if
 it grows or shrinks over a power of 2 size.
This is very sensible for moderately-sized arrays. It's very wasteful for very large arrays. May I recommend power-of-two doubling up to somewhere in the 16K to 256K range, then a linear incrementage after that? -Russell B
Sep 07 2001
parent "Walter" <walter digitalmars.com> writes:
Russell Bornschlegel wrote in message <3B990850.73590841 estarcion.com>...
Walter wrote:
 Another poster mentioned that the alloced length for a resizable array
 should go in increments of powers of 2, I have empirically found this to
be
 most appropriate in my own work. Thus, dynamic arrays will be allocated
in
 power of 2 buckets, so resizing them will only require a copy operation
if
 it grows or shrinks over a power of 2 size.
This is very sensible for moderately-sized arrays. It's very wasteful for very large arrays. May I recommend power-of-two doubling up to somewhere in the 16K to 256K range, then a linear incrementage after that?
The power of 2 allocation goes up to 4k, and then is rounded up to the next 4k size.
Sep 07 2001
prev sibling next sibling parent reply Axel Kittenberger <axel dtone.org> writes:
 I'm assuming that the .length property of a dynamic array can be set,
 causing the code to change the size, right?  This is not specified in
 the spec, that I can see.
 
 Also, I assume that such a resize operation can (if expanding) result in
 an out-of-memory exception being thrown, just like operator new.  I
 don't see specs for either of those...
 
I don't want to be a constant critic, but I cannot see the real benefit of dynamic arrays been handeled by the language/compiler itself. Normally I would order this task to better fit in the languages standard library. Sometimes you need just a little more intelligence for a spefic task than the normal dynamic array offers, in C++/Java/etc no problem you simply overload Vector and put your special stuff over it. After all thats the idea behind object oriented programming. How do you do this if the vector is already part of the language? Will the compiler force a specific allocatation strategy? If you're a numerical algorihm freak for Vector classes you can even change it. Yes I know you'll proparly be able to do vector classes altough the compiler itself provides dynamic arrays nativly. But I personally hate the principle fact on languages that user written code has an other quality on use than compiler provided code. (Like write() in Pascal, a programmer could not make such a function himself, one of the biggest drawbacks of Pascal, as I see it, it gives you as a programmer a kind of depressive feeling beeing 2nd class only) - Axel
Sep 05 2001
next sibling parent reply Russ Lewis <russ deming-os.org> writes:
Axel Kittenberger wrote:

 I'm assuming that the .length property of a dynamic array can be set,
 causing the code to change the size, right?  This is not specified in
 the spec, that I can see.

 Also, I assume that such a resize operation can (if expanding) result in
 an out-of-memory exception being thrown, just like operator new.  I
 don't see specs for either of those...
I don't want to be a constant critic, but I cannot see the real benefit of dynamic arrays been handeled by the language/compiler itself. Normally I would order this task to better fit in the languages standard library.
Generally I agree that the compiler should be kept as simple as possible. But I also think that it should handle the common cases and make them easy for the programmer to access. Reallocation of arrays is a major headache in C/C++, and I am of the opinion that it (like native string handling, garbage collection, and other features) are a Good Thing to have in a modern language.
 Sometimes you need just a little more intelligence for a spefic task than
 the normal dynamic array offers, in C++/Java/etc no problem you simply
 overload Vector and put your special stuff over it. After all thats the
 idea behind object oriented programming. How do you do this if the vector
 is already part of the language?
If you're a massochist, implement a Vector class in D by allocating an array with new, saving a pointer to that array, and making people do everything by hand.
 Will the compiler force a specific allocatation strategy? If you're a
 numerical algorihm freak for Vector classes you can even change it. Yes I
 know you'll proparly be able to do vector classes altough the compiler
 itself provides dynamic arrays nativly. But I personally hate the principle
 fact on languages that user written code has an other quality on use than
 compiler provided code. (Like write() in Pascal, a programmer could not
 make such a function himself, one of the biggest drawbacks of Pascal, as I
 see it, it gives you as a programmer a kind of depressive feeling beeing
 2nd class only)
I don't know what you mean about "allocation strategy" exactly. The "append" operation appends a single element onto an array, presumably increasing it by only one element. That's a simple increase by one...nice for algorithms, although it's kind of wasteful if you end up having to do it a lot. If you want to increase the size of an array by more, just extend it to whatever size you want by (if Walter allows it) setting .length, or by reallocating the array: int[] myArray; // time to extend it int len = myArray.length; (myArray = new int[len*2])[0..len-1] = myArray[]; (at least, I think that syntax would work...) Walter, I'm really thinking that making .length settable would be a Good Thing. It would be good to have some sort of primitive that allows the programmer to extend arrays in place (when space is available). If there is no such primitive, then we have no choice but to do a allocate-copy-release algorithm, which will discourage use of dynamic arrays for performance reasons.
Sep 06 2001
parent reply Axel Kittenberger <axel dtone.org> writes:
 If you're a massochist, implement a Vector class in D by allocating an
 array with new, saving a pointer to that array, and making people do
 everything by hand.
I expeted that, and I answered it already in the original post, spend a whole paragraph on explaining how programmers feeling can be quite depressing if his code is 'second class' to what language offers.
 I don't know what you mean about "allocation strategy" exactly.  The
 "append" operation appends a single element onto an array, presumably
 increasing it by only one element.  That's a simple increase by 
 one...nice for algorithms, although it's kind of wasteful if you end up 
 having to do it a 
Exactly! So which one do you force on the user? If you add only a few seldom times +1 might be okay, but most of the times you've to use a dynamic array at all it's not. A good algorithm has been proofen to double the size of the vector each time the memory exceeds, most vectors I've seen to that this way. If you say simply set the size to what I want to add before, well generally if I would know the size I will use I would not need a dynamic vector after all or? And saying before each append() check the size and expand it before, there is no longer any comfort at this language idea when using it, you would end up implementing it in a class having won null as net result. I think I've even seen sometimes a vector class that even allowed to change it's allocation strategy by the user. I guess it were even the java ones, for people knowing what they do, they could specify at class construction the initial vector size, and the reallaction factor (ie. 2.0 is the default) - Axel
Sep 06 2001
parent Russ Lewis <russ deming-os.org> writes:
Axel Kittenberger wrote:

 If you're a massochist, implement a Vector class in D by allocating an
 array with new, saving a pointer to that array, and making people do
 everything by hand.
I expeted that, and I answered it already in the original post, spend a whole paragraph on explaining how programmers feeling can be quite depressing if his code is 'second class' to what language offers.
I apologize for the 'massochist' remark. It was meant light-heartedly, but I should have remembered that such things don't work well in newsgroups. I apologize.
 I don't know what you mean about "allocation strategy" exactly.  The
 "append" operation appends a single element onto an array, presumably
 increasing it by only one element.  That's a simple increase by
 one...nice for algorithms, although it's kind of wasteful if you end up
 having to do it a
Exactly! So which one do you force on the user? If you add only a few seldom times +1 might be okay, but most of the times you've to use a dynamic array at all it's not. A good algorithm has been proofen to double the size of the vector each time the memory exceeds, most vectors I've seen to that this way. If you say simply set the size to what I want to add before, well generally if I would know the size I will use I would not need a dynamic vector after all or? And saying before each append() check the size and expand it before, there is no longer any comfort at this language idea when using it, you would end up implementing it in a class having won null as net result. I think I've even seen sometimes a vector class that even allowed to change it's allocation strategy by the user. I guess it were even the java ones, for people knowing what they do, they could specify at class construction the initial vector size, and the reallaction factor (ie. 2.0 is the default)
So you're talking about a class that automatically expands the array when you run out, without user code? I guess I can see that. I'm just having trouble understanding how having the arrays length-aware hurts anything. A C++ implementation of a vector would include a pointer for the array, a length field, and (if it is used sequentially) a "used" field. In D, the length field is included in the fundamental type; I don't understand how that makes any allocation or management algorithms "second class." Maybe I'm just missing something huge here...please be patient with me :)
Sep 06 2001
prev sibling parent reply "Rui Ferreira" <t5rui hotmail.com> writes:
I absolutely concur, there is no single paradigm that fits every need and
this applies here.

Dynamic arrays and associate ones are very good tools, but not necessarily
language features. We need to distinguish between the foundation layer and
the ones above it.

We have integer and floating point numbers, why ? Because they are provided
by the machine. There is a natural need for them to be present in the
language itself. They are data units. What else can we do after this on a
mechanical continuous memory world ? Perhaps place some of these units
together one after another, that way we can index them by memory location,
sounds right doesn't it ? Mathematicians calls this a vector, bah, lets just
call it an array and get on with it. Now we have a one-to-one logic
representation of the machine. This is what C was going after with moderate
success.

Data units must exist and vectors of these must exist too or it would be a
very short memory circuit die. So, the bottom layer is set. Dynamic arrays
are built on top of it, they use indirection to access a block of memory
outside the fixed memory environment where the program is running. One
indirection away from the machine, one indirection slower, but yes, one
indirection more flexible. The associate array follows a much more fun and
didactic indirection graph.

I already gave my opinion on the need for concrete types precisely because
of this. Polymorphism needs indirection, fixed memory access doesn't. The
way we organize blocks of memory beyond linear space is what makes our
programs tick. Faster or slower. Flexibly or statically. Effectively or
sub-optimally. I would like to have a choice on this basic organization.
After all, it is my program, not the compiler's one.

The language specs of these built-in types are sound and have a good dose of
common sense, but they should be more useful as a basis for either a
foundation library or as part of a much broader and fundamental major
feature of the language capable of reflection properties. Dan suggested to
work at the parse tree/symbol table level, well, I think this is a much
better approach to pursue than to try to enforce a way of thinking. That is
either a job for domain specific script languages or for ones coming from a
less than stellar Rapid Application Development world.

To choose D as a name for this language and totally abandon the systems
programming level instead of building layers of abstraction around it is not
exactly paying an homage to C.

Avoid the Kitchen Sink allure.

-Rui Ferreira
Sep 06 2001
parent reply "Walter" <walter digitalmars.com> writes:
"Rui Ferreira" <t5rui hotmail.com> wrote in message
news:9n85lo$k2$1 digitaldaemon.com...
 To choose D as a name for this language and totally abandon the systems
 programming level instead of building layers of abstraction around it is
not
 exactly paying an homage to C.
C arrays are implemented in D - they have a fixed length and are not resizeable. You lose nothing by going to D. D dynamic arrays are a superset of static arrays. int a[3]; // static array, implemented just like in C int b[]; // dynamic array, implemented as a layer over static arrays Arrays are *such* a basic data structure, I feel that a great deal is gained by building resizable arrays into the language as a primitive. A lot of my code deals with arrays, and all the fiddling to manage their memory eats up much of my time and is lots of code that has bug potential. My experiments show that using D dynamic arrays cleans up a lot of code. Things just get a lot simpler, with no sacrifice in performance. Note that D dynamic arrays can be used for: 1) a layer over C static arrays 2) provides a string data type essentially "for free" 3) implicitly provides a stack data type In fact, many uses for linked lists goes away and become arrays. D associative arrays add to the mix a built in symbol table handling capability. Most of the time, there's no need to go beyond that.
Sep 06 2001
next sibling parent reply "Bradeeoh" <bradeeoh crosswinds.net> writes:
Oh, certainly, no doubt would dynamic arrays as the spec described and as
we're ironing out here be INCREDIBLY useful.  I think the question that
started this thread, however, and a concern of mine would be how do you
resize the array?  Is it by changing a variable such as ".length", or should
it be by calling some function?

Once again, forgive my ignorance to the ways of compilers and languages and
such, but how can the code know that the instant the variable gets a new
value, realloc() style stuff should be done on the array?

Isn't a function more in order?

int[] array1 = {3,3,3};        // at this point, any references to
array1.length will return 3, but it's a read only variable
array1.resize( 10 );   // array1.length will now be 10 and indices 0, 1, and
2 are 3, 3-9 are 0.
array1.resize( 2 );   // array1.length will now be 2, indices 2-9 are lost


-Brady

 Arrays are *such* a basic data structure, I feel that a great deal is
gained
 by building resizable arrays into the language as a primitive. A lot of my
 code deals with arrays, and all the fiddling to manage their memory eats
up
 much of my time and is lots of code that has bug potential. My experiments
 show that using D dynamic arrays cleans up a lot of code. Things just get
a
 lot simpler, with no sacrifice in performance.
Sep 06 2001
parent Russ Lewis <russ deming-os.org> writes:
Bradeeoh wrote:

 Isn't a function more in order?

 int[] array1 = {3,3,3};        // at this point, any references to
 array1.length will return 3, but it's a read only variable
 array1.resize( 10 );   // array1.length will now be 10 and indices 0, 1, and
 2 are 3, 3-9 are 0.
 array1.resize( 2 );   // array1.length will now be 2, indices 2-9 are lost
Somebody, earlier in this thread, made a passing reference that setting .length is like using a gettor; what looks like setting a simple parameter actually expands to a function call. So, to use your syntax, it would work like: array1.length = 10; /* internally, what happens is array1.resize(10); */
Sep 06 2001
prev sibling parent reply "Rui Ferreira" <t5rui hotmail.com> writes:
Walter, I understand that D provides strings, dynamic and associative arrays
with an added benefit in terms of syntax, but my point is that you should
provide them as standard library containers.

The added syntactic sugar could be achieved with some form of meta-language
definition feature. In this case, I'm proposing a major feature of the D
language that allows the user to build himself these kinds of data
structures.

For example, if I want to build a, say, red-black tree container. How am I
supposed to do that in D ? Can I add new keywords to support it, overload
operators ? More importantly can I do it on a type safe way ?

This is why major language features are more important than minor syntactic
issues. Templates in c++ have more uses than even Bjarne Stroustrup himself
would thought possible! It serves more than one use. It is a generic
programming supporting tool instead of being a dedicated problem solver.
Major features allow for extensions and encourage a generic programming
style.

With these specs, I really don't think this is a systems programming
language. Built-in data structures, heap allocated data, garbage collection,
no generic programming facilities. All this is more consistent with a
language oriented to services programming. Perhaps you should consider
calling D something more closely to the Java family. I expect a much larger
degree of success if it is targeted to this area.

-Rui
Sep 07 2001
parent reply "Walter" <walter digitalmars.com> writes:
"Rui Ferreira" <t5rui hotmail.com> wrote in message
news:9nb494$1mg4$1 digitaldaemon.com...
 Walter, I understand that D provides strings, dynamic and associative
arrays
 with an added benefit in terms of syntax, but my point is that you should
 provide them as standard library containers.
These facilities are not implementable in C without ugly syntax, and implementing them in C++ requires a vast and complex language to support meta programming (STL). Furthermore, the C++ way allows one to implement dynamic arrays in 64000 different and incompatible ways. Providing a builtin dynamic array facility that covers 95% of the needs for such means that your array code is portable from programmer Bob to programmer Fred. (So what I'm addressing is not simply portability from compiler to compiler, but from *programmer* to programmer.)
 This is why major language features are more important than minor
syntactic
 issues.
With every data type, the language designer must decide if it is built in or if it's part of a runtime library. I feel the advantages of dynamic arrays outweigh the disadvantages of them being fixed by the language implementation. Dynamic arrays are a regular feature of my C++ coding, and I'm tired of the tedium, bugs, etc., involved in writing implementation after implementation of them. I'm tired of messing about with strings. I'm tired of buffer overflows. Building dymanic arrays into the language just chucks all that. C's support for strings is just plain inadequate. Java has halfway builtin arrays, and halfway builtin strings. Java strings are not Java arrays. The way Java strings are done is a serious performance hit. D's design makes strings a special case of arrays. They should be much faster than C arrays and require less memory. They're easier to write, the syntax does what you'd expect, and the possibility for bugs is greatly reduced.
 Templates in c++ have more uses than even Bjarne Stroustrup himself
 would thought possible! It serves more than one use. It is a generic
 programming supporting tool instead of being a dedicated problem solver.
 Major features allow for extensions and encourage a generic programming
 style.
I am consistently amazed by what people manage to do with C++ templates. I consider it a defect in C++, however, that a massive template library and an enormously complex language is required just to implement a string type.
 With these specs, I really don't think this is a systems programming
 language. Built-in data structures, heap allocated data, garbage
collection,
 no generic programming facilities. All this is more consistent with a
 language oriented to services programming. Perhaps you should consider
 calling D something more closely to the Java family. I expect a much
larger
 degree of success if it is targeted to this area.
D still allows the programmer to get "down and dirty", after all, it supports pointers and arbitrary casts. That capability is what distinguishes it from service langauges like Java, which go to great lengths to prevent that. Down and dirty capability makes it a systems programming language. What makes it better than C or C++ is that it is not necessary to get down and dirty for the vast majority of programming chores. For example, in D one can "map" a bit array across an int: int foo; bit[32] flags = *(bit[32] *)&foo; Try that in Java.
Sep 07 2001
parent reply Axel Kittenberger <axel dtone.org> writes:
 D still allows the programmer to get "down and dirty", after all, it
 supports pointers and arbitrary casts. That capability is what
 distinguishes it from service langauges like Java, which go to great
 lengths to prevent that. Down and dirty capability makes it a systems
 programming language. What makes it better than C or C++ is that it is not
 necessary to get down and dirty for the vast majority of programming
 chores. For example, in D one can "map" a bit array across an int:
Well but you know that in operating systems kernel you don't have a malloc or a free? So for beeing systems language, the idea C was invented for, what you do with dynamic arrays there? Or how do you make instances after all if creation on stack is not allowed? I know linux in example has a kmalloc and a kfree, that behave up to 90% the same, but the 10% difference are important to know to make good kernel code. (ie. the roundings that occour due to the buddy algorithmn). Even more criticial are things during the boot phase, well at first instance you don't have a stack at all, okay there all systems require assembler in the first steps. Okay then you've a stack but for long absolute no heap. In example linux has as next step a prelimarary memory managment, needed and available only temporary until later phase, where the buddy system is ready to go up. And even in the final kernel phase you sometimes want to get you data through other techniques like valloc() instead of malloc, because you need it physical constant, etc. this all managmentable in C, beeing a systems language. A language that creates from itself calls to malloc and free during creation is at least in my eyes not suitable to write kernels, a libc library (which implements malloc after all), or some os-less embedded systems. This features are great to have in a pure user-space language, but this is against the idea what I've of a system language, and the original intention behind C. - Axel
Sep 07 2001
next sibling parent Russ Lewis <russ deming-os.org> writes:
Axel Kittenberger wrote:

 A language that creates from itself calls to malloc and free during
 creation is at least in my eyes not suitable to write kernels, a libc
 library (which implements malloc after all), or some os-less embedded
 systems. This features are great to have in a pure user-space language, but
 this is against the idea what I've of a system language, and the original
 intention behind C.
It seems like it should be possible to write a D program without using any dynamic arrays. If so, then you could implement a compiler switch that disabled them altogether. You'd probably need to disable the garbage collector, as well. If the two were possible (in some future version of the compiler), would you think D was kernel-ready?
Sep 07 2001
prev sibling parent reply "Walter" <walter digitalmars.com> writes:
Axel Kittenberger wrote in message <9nbaf7$1q6m$1 digitaldaemon.com>...
Well but you know that in operating systems kernel you don't have a malloc
or a free?
So don't use dynamic arrays for such code. Nothing prevents you from using my_malloc() and my_free().
Sep 07 2001
parent reply Axel Kittenberger <axel dtone.org> writes:
Walter wrote:

 
 Axel Kittenberger wrote in message <9nbaf7$1q6m$1 digitaldaemon.com>...
Well but you know that in operating systems kernel you don't have a malloc
or a free?
So don't use dynamic arrays for such code. Nothing prevents you from using my_malloc() and my_free().
However beeing able to create objects on stack is essential in some tougher cases :/
Sep 08 2001
parent reply "Walter" <walter digitalmars.com> writes:
You can still create struct's on the stack.

Axel Kittenberger wrote in message <9ncq4u$2mof$1 digitaldaemon.com>...
Walter wrote:

 Axel Kittenberger wrote in message <9nbaf7$1q6m$1 digitaldaemon.com>...
Well but you know that in operating systems kernel you don't have a malloc
or a free?
So don't use dynamic arrays for such code. Nothing prevents you from using my_malloc() and my_free().
However beeing able to create objects on stack is essential in some tougher cases :/
Sep 08 2001
parent reply Axel Kittenberger <axel dtone.org> writes:
Walter wrote:

 You can still create struct's on the stack.
Oh sorry, then I took it up wrong from another tread :/ Thought you mentioned that all objects are created on the heap, no more stack objects.
Sep 08 2001
parent reply "Walter" <walter digitalmars.com> writes:
Axel Kittenberger wrote in message <9ndjvd$4fa$1 digitaldaemon.com>...
Walter wrote:
 You can still create struct's on the stack.
Oh sorry, then I took it up wrong from another tread :/ Thought you
mentioned that all objects are created on the heap, no more stack objects.
Structs can be created on the heap, the static data segment, or on the stack. Classes, however, can only be created on the garbage collected heap. The reason for the latter is to avoid all the complications with copy constructors, assignment operators, trying to hang the destructors on all exits from scope, etc.
Sep 08 2001
parent reply Axel Kittenberger <axel dtone.org> writes:
 Structs can be created on the heap, the static data segment, or on the
 stack. Classes, however, can only be created on the garbage collected
 heap.
 
 The reason for the latter is to avoid all the complications with copy
 constructors, assignment operators, trying to hang the destructors on all
 exits from scope, etc.
Isn't the guaranteed destruction calls advertised as a major feature of C++? A lot of people even wrap certain resource binding into classes just to be sure they get freed again with destruction, when the caller leaves the scope.
Sep 08 2001
parent reply "Walter" <walter digitalmars.com> writes:
Axel Kittenberger wrote in message <9ndn49$5ve$1 digitaldaemon.com>...
Isn't the guaranteed destruction calls advertised as a major feature of
C++? A lot of people even wrap certain resource binding into classes just
to be sure they get freed again with destruction, when the caller leaves
the scope.
Yes, that is the C++ paradigm. Most of the resource freeing is simply memory deallocation, which is handled by the garbage collector in D. The rest can be handled with a finally block.
Sep 08 2001
next sibling parent reply Axel Kittenberger <axel dtone.org> writes:
Walter wrote:

 
 Axel Kittenberger wrote in message <9ndn49$5ve$1 digitaldaemon.com>...
Isn't the guaranteed destruction calls advertised as a major feature of
C++? A lot of people even wrap certain resource binding into classes just
to be sure they get freed again with destruction, when the caller leaves
the scope.
Yes, that is the C++ paradigm. Most of the resource freeing is simply memory deallocation, which is handled by the garbage collector in D. The rest can be handled with a finally block.
Okay I understand. Well but on question, let's take in example a File stream class. Say I created for local use only like { File a("cork"); try { a.open(); } catch FileNotFoundException() { printf("File 'cork' not found\n"); exit(-1); } a.write("bork"); } So the file descriptior a uses is a (limited) resource. No matter what will happen, sooner or later when the code moves out of context the resource is freed. Now I guess the file descriptior for 'a' will then stay open, right? Normally C++ classes close it's file descriptor if they were forgotten to left open. Other question if the close fails, a FileIOException should be raised, so are finalizers allowed raise exceptions? I think in combination with a GC this is nearly impossibile, since the exception would be raised you anywhere from where the code currently executes. - Axel
Sep 08 2001
next sibling parent a <a b.c> writes:
Axel Kittenberger wrote:
 
 Walter wrote:
 
 Axel Kittenberger wrote in message <9ndn49$5ve$1 digitaldaemon.com>...
Isn't the guaranteed destruction calls advertised as a major feature of
C++? A lot of people even wrap certain resource binding into classes just
to be sure they get freed again with destruction, when the caller leaves
the scope.
Yes, that is the C++ paradigm. Most of the resource freeing is simply memory deallocation, which is handled by the garbage collector in D. The rest can be handled with a finally block.
Okay I understand. Well but on question, let's take in example a File stream class. Say I created for local use only like { File a("cork"); try { a.open(); } catch FileNotFoundException() { printf("File 'cork' not found\n"); exit(-1); } a.write("bork"); } So the file descriptior a uses is a (limited) resource. No matter what will happen, sooner or later when the code moves out of context the resource is freed. Now I guess the file descriptior for 'a' will then stay open, right? Normally C++ classes close it's file descriptor if they were forgotten to left open.
I would assume that the file would be closed whenever garbage collection runs. If you need the guarantee that it will be when you leave a given scope, then close it in a finally block.
 Other question if the close fails, a FileIOException should be raised, so
 are finalizers allowed raise exceptions? I think in combination with a GC
 this is nearly impossibile, since the exception would be raised you
 anywhere from where the code currently executes.
C++ really couldn't deal with exceptions in destructors either since an exception could trigger an exception and the language would have to decide with exception was more important. The C++ solution was to bomb. You had to call uncaught_exception() in the destructor to determine if it was safe to throw an exception. I suppose you wouldn't want to let the finalizer do anything that you had to verify happened, or that you have to guarantee the timing of. I am very fond of the C++ paradigm, but I don't think the lack of it is a show stopper. Some might argue that using destructors to run code is bad for one reason or another, but I'm not one of them. Dan
Sep 08 2001
prev sibling next sibling parent "Walter" <walter digitalmars.com> writes:
Axel Kittenberger wrote in message <9ne3ak$c9g$1 digitaldaemon.com>...
So the file descriptior a uses is a (limited) resource. No matter what will
happen, sooner or later when the code moves out of context the resource is
freed. Now I guess the file descriptior for 'a' will then stay open, right?
Normally C++ classes close it's file descriptor if they were forgotten to
left open.
This is not a huge problem because a (good) operating system will reclaim any resources left dangling by an aborted app. Some notorious operating systems do not, like Win95. Oops. How this is dealt with is to force finalizers to all get run on exit.
Other question if the close fails, a FileIOException should be raised, so
are finalizers allowed raise exceptions? I think in combination with a GC
this is nearly impossibile, since the exception would be raised you
anywhere from where the code currently executes.
That's a great question. I don't have a great answer <g>. I can think of several possibilities, but this clearly needs more work.
Sep 08 2001
prev sibling parent "Walter" <walter digitalmars.com> writes:
Axel Kittenberger wrote in message <9ne3ak$c9g$1 digitaldaemon.com>...
So the file descriptior a uses is a (limited) resource. No matter what will
happen, sooner or later when the code moves out of context the resource is
freed. Now I guess the file descriptior for 'a' will then stay open, right?
Normally C++ classes close it's file descriptor if they were forgotten to
left open.
This is not a huge problem because a (good) operating system will reclaim any resources left dangling by an aborted app. Some notorious operating systems do not, like Win95. Oops. How this is dealt with is to force finalizers to all get run on exit.
Other question if the close fails, a FileIOException should be raised, so
are finalizers allowed raise exceptions? I think in combination with a GC
this is nearly impossibile, since the exception would be raised you
anywhere from where the code currently executes.
That's a great question. I don't have a great answer <g>. I can think of several possibilities, but this clearly needs more work. My first thought is design your destructors so they don't throw exceptions. My second thought is go ahead and let them throw exceptions. My third thought is use finalizers to free up resources reliably rather than destructors. I agree that the whole "finalize on gc" approach suffers from some intractable problems in trying to deal with it perfectly. But in normal use and with a little care, these problems shouldn't be disruptive in practice.
Sep 08 2001
prev sibling parent reply "Kent Sandvik" <sandvik excitehome.net> writes:
"Walter" <walter digitalmars.com> wrote in message
news:9ndu2o$9ud$1 digitaldaemon.com...

 Yes, that is the C++ paradigm. Most of the resource freeing is simply
memory
 deallocation, which is handled by the garbage collector in D. The rest can
 be handled with a finally block.
Would this be a crazy feature, you could allocate objects on the heap based on a closure, maybe with some syntactic sugar that indicates that when the closure ends, the object's destructor is automatically called. This would indeed make it possible to write small objects that save and restore state, those are really handy (the constructor saves state, the destructor restores it). --Kent
Sep 10 2001
parent reply "Walter" <walter digitalmars.com> writes:
Kent Sandvik wrote in message <9nj752$6li$1 digitaldaemon.com>...
Would this be a crazy feature, you could allocate objects on the heap based
on a closure, maybe with some syntactic sugar that indicates that when the
closure ends, the object's destructor is automatically called. This would
indeed make it possible to write small objects that save and restore state,
those are really handy (the constructor saves state, the destructor
restores
it). --Kent
Then it would be C++ <g>.
Sep 10 2001
next sibling parent reply "Kent Sandvik" <sandvik excitehome.net> writes:
"Walter" <walter digitalmars.com> wrote in message
news:9njsqc$iis$1 digitaldaemon.com...
 Kent Sandvik wrote in message <9nj752$6li$1 digitaldaemon.com>...
Would this be a crazy feature, you could allocate objects on the heap
based
on a closure, maybe with some syntactic sugar that indicates that when
the
closure ends, the object's destructor is automatically called. This would
indeed make it possible to write small objects that save and restore
state,
those are really handy (the constructor saves state, the destructor
restores
it). --Kent
Then it would be C++ <g>.
But the diff is that the object is placed on the heap, i.e. none of those stack related issues. Actually even something like MyClass class; //rather than using new would indicate that this object will we wiped out, the destructor is called, when the closure ends. --Kent
Sep 12 2001
parent "Walter" <walter digitalmars.com> writes:
Kent Sandvik wrote in message <9nobih$f9$1 digitaldaemon.com>...
But the diff is that the object is placed on the heap, i.e. none of those
stack related issues. Actually even something like

MyClass class; //rather than using new

would indicate that this object will we wiped out, the destructor is
called,
when the closure ends. --Kent
That is an interesting thought. -Walter
Sep 12 2001
prev sibling parent "Sean L. Palmer" <spalmer iname.com> writes:
It will be extremely nice to make non-virtual methods on structs anyway, and
you could then make ctors and dtors for structs and put said structs on the
stack... which would then get cleaned up on leaving scope, run the dtors,
etc.  That way if you want a small class that just manages a resource, you
make it a struct instead.

I can't imagine a language that provides properties, gettors, settors, etc
on arrays, and doesn't let you add similar things to structs.

Sean

"Walter" <walter digitalmars.com> wrote in message
news:9njsqc$iis$1 digitaldaemon.com...
 Kent Sandvik wrote in message <9nj752$6li$1 digitaldaemon.com>...
Would this be a crazy feature, you could allocate objects on the heap
based
on a closure, maybe with some syntactic sugar that indicates that when
the
closure ends, the object's destructor is automatically called. This would
indeed make it possible to write small objects that save and restore
state,
those are really handy (the constructor saves state, the destructor
restores
it). --Kent
Then it would be C++ <g>.
Nov 04 2001
prev sibling parent reply "Bradeeoh" <bradeeoh crosswinds.net> writes:
I just want to ask Walter how this would work if in deed .length were a
property that could be directly changed.

These chunks of code -

int[] array1 = { 3,3,3 };

int[] array2 = new int[3];
for( int i=0;i<array2.length;i++)
    array2[i] = 3;

Are array1 and array2 now virtually identical?

Now -

array2.length = 298374;    //  What exactly happens here?

for( int i=0; i<array2.length; i++)
    array2[i] = 3;

The step where you change the length of the array - how much work actually
takes place there?  That seems to be quite a complicated process, not nearly
as simple as just changing a "length" variable, but rather allocating new
memory, copying the old elements to the new space, and perhaps some other
administrative stuff.

Correct me if I'm wrong on that...

But if I'm right, should that really be something that's automated?

-Brady


"Russ Lewis" <russ deming-os.org> wrote in message
news:3B96A34F.DABE45E5 deming-os.org...
 I'm assuming that the .length property of a dynamic array can be set,
 causing the code to change the size, right?  This is not specified in
 the spec, that I can see.

 Also, I assume that such a resize operation can (if expanding) result in
 an out-of-memory exception being thrown, just like operator new.  I
 don't see specs for either of those...
Sep 06 2001
parent "Walter" <walter digitalmars.com> writes:
"Bradeeoh" <bradeeoh crosswinds.net> wrote in message
news:9n8e1g$59t$1 digitaldaemon.com...
 The step where you change the length of the array - how much work actually
 takes place there?  That seems to be quite a complicated process, not
nearly
 as simple as just changing a "length" variable, but rather allocating new
 memory, copying the old elements to the new space, and perhaps some other
 administrative stuff.
Assigning to the .length property essentially does a realloc() on the array data.
Sep 06 2001