www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Herb Sutter briefly discusses D during interview

reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
There's a question related to D and Go within the first eight minutes:

http://channel9.msdn.com/Shows/Going+Deep/Herb-Sutter-C-Questions-and-Answers


Andrei
Jun 07 2011
next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
I'm not sure what he means when he says that D doesn't simplify syntax.
Jun 07 2011
prev sibling next sibling parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On 2011-06-07 17:53, Andrej Mitrovic wrote:
 I'm not sure what he means when he says that D doesn't simplify syntax.
He talked just before that about simplifying declaration syntax so that it reads left-to-right instead of right-to-left, and D didn't do that. For instance, int[4][3] a; declares a static array of length three where each element of that array is a static array of length 4 where each of those arrays holds an integer. It's read right-to-left and throws people off at least some of the time. Because, when you go to index it, it's used left-to-right auto a = i[3]; //out-of-bounds Herb Sutter was suggesting that it would be a big improvement to order declaration syntax such that it's read left-to-right (which apparently is what Pascal did, and apparently is what Go has done). D stayed closer to C and C++ and kept the right-to-left declaration synax. That's what he was referring to. - Jonathan M Davis
Jun 07 2011
next sibling parent reply "Vladimir Panteleev" <vladimir thecybershadow.net> writes:
On Wed, 08 Jun 2011 04:30:15 +0300, Jonathan M Davis <jmdavisProg gmx.com>  
wrote:

 On 2011-06-07 17:53, Andrej Mitrovic wrote:
 I'm not sure what he means when he says that D doesn't simplify syntax.
He talked just before that about simplifying declaration syntax so that it reads left-to-right instead of right-to-left, and D didn't do that. For instance, int[4][3] a; declares a static array of length three where each element of that array is a static array of length 4 where each of those arrays holds an integer. It's read right-to-left and throws people off at least some of the time. Because, when you go to index it, it's used left-to-right auto a = i[3]; //out-of-bounds Herb Sutter was suggesting that it would be a big improvement to order declaration syntax such that it's read left-to-right (which apparently is what Pascal did, and apparently is what Go has done). D stayed closer to C and C++ and kept the right-to-left declaration synax. That's what he was referring to. - Jonathan M Davis
I'm really confused by this post. // Old, C/C++-like syntax - I understand this is pending deprecation int a[3][4]; static assert(a.length == 3); static assert(a[0].length == 4); // New D syntax int[4][3] b; static assert(b.length == 3); static assert(b[0].length == 4); -- Best regards, Vladimir mailto:vladimir thecybershadow.net
Jun 07 2011
parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On 2011-06-07 23:43, Vladimir Panteleev wrote:
 On Wed, 08 Jun 2011 04:30:15 +0300, Jonathan M Davis <jmdavisProg gmx.com>
 
 wrote:
 On 2011-06-07 17:53, Andrej Mitrovic wrote:
 I'm not sure what he means when he says that D doesn't simplify syntax.
He talked just before that about simplifying declaration syntax so that it reads left-to-right instead of right-to-left, and D didn't do that. For instance, int[4][3] a; declares a static array of length three where each element of that array is a static array of length 4 where each of those arrays holds an integer. It's read right-to-left and throws people off at least some of the time. Because, when you go to index it, it's used left-to-right auto a = i[3]; //out-of-bounds Herb Sutter was suggesting that it would be a big improvement to order declaration syntax such that it's read left-to-right (which apparently is what Pascal did, and apparently is what Go has done). D stayed closer to C and C++ and kept the right-to-left declaration synax. That's what he was referring to. - Jonathan M Davis
I'm really confused by this post. // Old, C/C++-like syntax - I understand this is pending deprecation int a[3][4]; static assert(a.length == 3); static assert(a[0].length == 4); // New D syntax int[4][3] b; static assert(b.length == 3); static assert(b[0].length == 4);
Declarations are read outward from the variable name. That's generally right- to-left. Putting the array dimensions on the right side results in it being left-to-right, but that's not the norm. int* a; //A pointer to an int int** b; //A pointer to a pointer to an int. Left-to-right would end up being something more like this: a *int; or maybe *int a; The D syntax for static array sizes just underlines the fact that declarations are generally read right-to-left because in that particular case, it's not what people expect. Herb Sutter is positing that the syntax would be easier to grok and result in fewer errors if it were all left-to-right instead of right- to-left. Yes, there are a few cases where you end up with left-to-right in C- based languages, because declarations are typically read outward from the variable name, and if that includes stuff to the right of the variable name, then that part is read left-to-right, but that's the exception. - Jonathan M Davis
Jun 07 2011
next sibling parent =?ISO-8859-1?Q?Ali_=C7ehreli?= <acehreli yahoo.com> writes:
On 06/07/2011 11:59 PM, Jonathan M Davis wrote:
 On 2011-06-07 23:43, Vladimir Panteleev wrote:
 // Old, C/C++-like syntax - I understand this is pending deprecation
 int a[3][4];
 static assert(a.length == 3);
 static assert(a[0].length == 4);

 // New D syntax
 int[4][3] b;
 static assert(b.length == 3);
 static assert(b[0].length == 4);
Declarations are read outward from the variable name. That's
generally right-
 to-left.
The important word there is "generally". How can we say that there is any rule when right-to-left is only "generally"?
 Putting the array dimensions on the right side results in it being
 left-to-right, but that's not the norm.

 int* a; //A pointer to an int
No. The type is int* (I read it as "int pointer"), and the variable name is a. I don't have to read it at one breath.
 int** b; //A pointer to a pointer to an int.
No. The type is int** (I read it consistently as "int pointer pointer"), and the variable name is b.
 Left-to-right would end up being something more like this:

 a *int;

 or maybe

 *int a;

 The D syntax for static array sizes just underlines the fact that 
declarations
 are generally read right-to-left because in that particular case, 
it's not
 what people expect.
I don't read them that way. Perhaps we should say that the English speakers may read right-to-left? Perhaps only when they need to understand a very complicated declaration?
 Herb Sutter is positing that the syntax would be easier to
 grok and result in fewer errors if it were all left-to-right instead 
of right-
 to-left.
D has left-to-right: Type on the left, variable on the right. Consistent.
 Yes, there are a few cases where you end up with left-to-right in C-
 based languages, because declarations are typically read outward from the
 variable name, and if that includes stuff to the right of the 
variable name,
 then that part is read left-to-right, but that's the exception.
I can't remember such exceptions in D? (Well, 'alias this' comes to mind.) Multi-dimensional array declarations and function pointer declarations are corrected in D. That is consistent.
 - Jonathan M Davis
Ali
Jun 08 2011
prev sibling parent Trass3r <un known.com> writes:
Am 08.06.2011, 08:59 Uhr, schrieb Jonathan M Davis <jmdavisProg gmx.com>:
 Left-to-right would end up being something more like this:

 a *int;

 or maybe

 *int a;
Yeah, like that improved anything. People who want the type to be to the right of the variable name should go use Pascal. Really, one of the first things I read when I learned D was that declarations are read right-to-left and I immediately started to think that way. I'd even say it was intuitive to me. It's consistent and fixes C's crappy behavior of splitting the type around the variable name. And if you keep breaking down the type in your mind like "a is an array of 3 elements being arrays of 5 ints" even the indexing discrepancy isn't a problem anymore. Add qualifiers like const, maybe mix pointers, arrays etc. and C declarations become an even bigger mess while D ones are still consistent and easily readable cause of right-to-left. A real problem might be the syntax for creating dynamic arrays: auto arr = new int[][](4,5)
Jun 08 2011
prev sibling parent reply =?ISO-8859-1?Q?Ali_=C7ehreli?= <acehreli yahoo.com> writes:
On 06/07/2011 06:30 PM, Jonathan M Davis wrote:
 On 2011-06-07 17:53, Andrej Mitrovic wrote:
 I'm not sure what he means when he says that D doesn't simplify syntax.
He talked just before that about simplifying declaration syntax so
that it
 reads left-to-right instead of right-to-left, and D didn't do that.
I don't think D could use right-to-left. Like this?: a int; p *int; That would be too strange for its heritage.
 For
 instance,

 int[4][3] a;

 declares a static array of length three where each element of that 
array is a
 static array of length 4 where each of those arrays holds an integer. 
It's
 read right-to-left
Note that D's syntax fixes the horribly broken one of C. And contrary to popular belief, only some of C's syntax is right-to-left; notably, pointers to arrays and pointers to functions are outside-to-inside. I never read declarations from right to left. I doubt that anybody does that. "Code is not Literature". (I stole the title of tomorrow's Silicon Valley ACCU talk: http://accu.org/index.php/accu_branches/accu_usa/upcoming) Reading declarations from right-to-left is cute but there is no value in doing so. Besides, there are no "array of"s in that declaration at all. It is a coincidence that the C syntax can be read that way with the added "is a"s and "of"s. In D, type is on the left and the variable name is on the right: int i; int[4] array; int[4][3] array_of_array; That is consistent.
 and throws people off at least some of the time.
It must have thrown only the people who could bend their minds to somehow accept C's array syntax.
 Because,
 when you go to index it, it's used left-to-right
What is left-to-right? Indexing does one thing: it provides access to the element with the given number. There is no left nor right in array indexing.
 auto a = i[3]; //out-of-bounds
i[3] accesses the element number 3 of i (yes, with the indicated bug). There is nothing else. The type of that element is int[4] as it has been declared. This has nothing to do with left and right.
 D stayed closer to C and C++
 and kept the right-to-left declaration synax. That's what he was 
referring to. I agree. I can't understand how D's array syntax is not seen as fixing C's broken one. Ali
Jun 08 2011
parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On 2011-06-08 00:54, Ali =C7ehreli wrote:
 On 06/07/2011 06:30 PM, Jonathan M Davis wrote:
  > On 2011-06-07 17:53, Andrej Mitrovic wrote:
  >> I'm not sure what he means when he says that D doesn't simplify synta=
x.
  >=20
  > He talked just before that about simplifying declaration syntax so
=20
 that it
=20
  > reads left-to-right instead of right-to-left, and D didn't do that.
=20
 I don't think D could use right-to-left. Like this?:
=20
 a int;
 p *int;
=20
 That would be too strange for its heritage.
=20
  > For
  > instance,
  >=20
  > int[4][3] a;
  >=20
  > declares a static array of length three where each element of that
=20
 array is a
=20
  > static array of length 4 where each of those arrays holds an integer.
=20
 It's
=20
  > read right-to-left
=20
 Note that D's syntax fixes the horribly broken one of C. And contrary to
 popular belief, only some of C's syntax is right-to-left; notably,
 pointers to arrays and pointers to functions are outside-to-inside.
=20
 I never read declarations from right to left. I doubt that anybody does
 that. "Code is not Literature". (I stole the title of tomorrow's Silicon
 Valley  ACCU talk:
 http://accu.org/index.php/accu_branches/accu_usa/upcoming) Reading
 declarations from right-to-left is cute but there is no value in doing
 so. Besides, there are no "array of"s in that declaration at all. It is
 a coincidence that the C syntax can be read that way with the added "is
 a"s and "of"s.
=20
 In D, type is on the left and the variable name is on the right:
=20
 int i;
 int[4] array;
 int[4][3] array_of_array;
=20
 That is consistent.
=20
  > and throws people off at least some of the time.
=20
 It must have thrown only the people who could bend their minds to
 somehow accept C's array syntax.
=20
  > Because,
  > when you go to index it, it's used left-to-right
=20
 What is left-to-right? Indexing does one thing: it provides access to
 the element with the given number. There is no left nor right in array
 indexing.
=20
  > auto a =3D i[3]; //out-of-bounds
=20
 i[3] accesses the element number 3 of i (yes, with the indicated bug).
 There is nothing else. The type of that element is int[4] as it has been
 declared. This has nothing to do with left and right.
=20
  > D stayed closer to C and C++
  > and kept the right-to-left declaration synax. That's what he was
=20
 referring to.
=20
 I agree. I can't understand how D's array syntax is not seen as fixing
 C's broken one.
No, people don't normally look at declarations such as int* a; as being right to left. But from the compiler's perspective, they are. The= =20 compiler doesn't look at the type of a as being an int pointer. It looks at= it=20 as being a pointer to an int. The * comes first and then the int.=20 Understanding how the compiler does it helps with reading stuff like=20 complicated function pointers in C, but particularly with simple declaratio= ns,=20 people just don't look at it that way. However, the compiler itself is=20 deciphering the type outward from the variable name, and that's almost alwa= ys=20 from right to left. The exceptions are when declaring static arrays (which = go=20 on the right and thus read left-to-right) and when declaring C-style functi= on=20 pointers, where it ends up going from _both_ right-to-left and left-to-righ= t,=20 because the name is in the middle. So, in both C and D, variable declaratio= ns=20 almost always read right-to-left. As for static arrays in D, the problem is the disjoint between declarations= =20 and indexing. They're flipped between the two. Most people expect that the= =20 dimensions read left to right for both the declaration and the indexing, bu= t=20 they don't. They think that int[4][3] a; auto b =3D a[3][2]; is legal, because they view the left dimension in the declaration as being = the=20 left when indexing. But it's not. If you used the C syntax, int a[4][3]; auto b =3D a[3][2]; then the dimensions _do_ match. Quite a few people in the past have request= ed=20 that int[4][3] a; and int a[4][3]; be the same in D. But because the compiler reads types outward from the=20 variable, that doesn't work. So, D's syntax fixes the broken C syntax in th= e=20 sense that the dimensions go with the type instead of the variable name (as= =20 they should), but it makes it worse in the sense that it means that the=20 dimensions are in the opposite order of what most people expect. But fixing= =20 the dimensions so that they're in the order that most people expect wouldhm= nv =2D Jonathan M Davis
Jun 08 2011
next sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
Jonathan M Davis wrote:
 ...
 No, people don't normally look at declarations such as

 int* a;

 as being right to left. But from the compiler's perspective, they are. The

 compiler doesn't look at the type of a as being an int pointer. It looks at it
 as being a pointer to an int. The * comes first and then the int.
 [snip.]
It is more convenient for the compiler to read the declaration left to right to construct the type. (just like for people) Timon
Jun 08 2011
next sibling parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On 2011-06-08 08:38, Timon Gehr wrote:
 Jonathan M Davis wrote:
 ...
 No, people don't normally look at declarations such as
 
 int* a;
 
 as being right to left. But from the compiler's perspective, they are.
 The
 
 compiler doesn't look at the type of a as being an int pointer. It looks
 at it as being a pointer to an int. The * comes first and then the int.
 [snip.]
It is more convenient for the compiler to read the declaration left to right to construct the type. (just like for people)
I'm sorry, but no. Yes, the compiler lexes/scans the code left-to-right, but in terms of how the type gets deciphered when parsing and using the resulting abstract syntax tree, the compiler is effectively processing the type outward from the variable, which almost always means right-to-left. The compiler has no concept of stuff like int pointer or int pointer pointer. It knows about pointer to int and pointer to pointer to int. And when you start looking at it that way, it's clearly right-to-left. The compiler is _not_ looking at it the way that a human normally does. - Jonathan M Davis
Jun 08 2011
parent Timon Gehr <timon.gehr gmx.ch> writes:
Jonathan M Davis wrote:
 On 2011-06-08 08:38, Timon Gehr wrote:
 Jonathan M Davis wrote:
 ...
 No, people don't normally look at declarations such as

 int* a;

 as being right to left. But from the compiler's perspective, they are.
 The

 compiler doesn't look at the type of a as being an int pointer. It looks
 at it as being a pointer to an int. The * comes first and then the int.
 [snip.]
It is more convenient for the compiler to read the declaration left to right to construct the type. (just like for people)
I'm sorry, but no. Yes, the compiler lexes/scans the code left-to-right, but in terms of how the type gets deciphered when parsing and using the resulting abstract syntax tree, the compiler is effectively processing the type outward from the variable, which almost always means right-to-left. The compiler has no concept of stuff like int pointer or int pointer pointer. It knows about pointer to int and pointer to pointer to int. And when you start looking at it that way, it's clearly right-to-left. The compiler is _not_ looking at it the way that a human normally does. - Jonathan M Davis
I'm sorry but yes. You are free to lay out your AST in any way you may please, but when the compiler has to parse and build a type involving pointers, it will proceed left-to-right. (and naturally so) Walter Bright wrote:
 Type *Parser::parseBasicType2(Type *t)
 {
     //printf("parseBasicType2()\n");
     while (1)
     {
         switch (token.value)
         {
             case TOKmul:
                 t = new TypePointer(t);
                 nextToken();
                 continue;
         ....
         }
     ...
     }
Of course, afterwards the compiler reasons from right to left. But parsing left to right _is_ more convenient. Timon
Jun 08 2011
prev sibling next sibling parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On 2011-06-08 08:57, Jonathan M Davis wrote:
 On 2011-06-08 08:38, Timon Gehr wrote:
 Jonathan M Davis wrote:
 ...
 No, people don't normally look at declarations such as
 
 int* a;
 
 as being right to left. But from the compiler's perspective, they are.
 The
 
 compiler doesn't look at the type of a as being an int pointer. It
 looks at it as being a pointer to an int. The * comes first and then
 the int. [snip.]
It is more convenient for the compiler to read the declaration left to right to construct the type. (just like for people)
I'm sorry, but no. Yes, the compiler lexes/scans the code left-to-right, but in terms of how the type gets deciphered when parsing and using the resulting abstract syntax tree, the compiler is effectively processing the type outward from the variable, which almost always means right-to-left. The compiler has no concept of stuff like int pointer or int pointer pointer. It knows about pointer to int and pointer to pointer to int. And when you start looking at it that way, it's clearly right-to-left. The compiler is _not_ looking at it the way that a human normally does.
Sight correction (I was in too much of a hurry when I typed that). The parsing is done left-to-right just like the lexing/scanning is (it has to be). However, the processing of the AST is effectively done outward from the variable name. That is, the semantic analysis of the type is done outward from the variable name and thus left-to-right. So, as far as the compiler getting any meaning out of the type and figuring out what to do with it goes, it reads right-to-left, _not_ left-to-right. And if you try and read it like a compiler does - e.g. pointer to pointer to int, not int pointer pointer - then you'll end up reading it right-to-left too. - Jonathan M Davis
Jun 08 2011
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
Jonathan M Davis wrote:
 Sight correction (I was in too much of a hurry when I typed that). The parsing
 is done left-to-right just like the lexing/scanning is (it has to be).
 However, the processing of the AST is effectively done outward from the
 variable name. That is, the semantic analysis of the type is done outward from
 the variable name and thus left-to-right. So, as far as the compiler getting
 any meaning out of the type and figuring out what to do with it goes, it reads
 right-to-left, _not_ left-to-right. And if you try and read it like a compiler
 does - e.g. pointer to pointer to int, not int pointer pointer - then you'll
 end up reading it right-to-left too.

 - Jonathan M Davis
Seems like we are agreeing perfectly. As to pointer to pointer to int vs int pointer pointer, the only difference is: pointer to pointer to int <=> pointer -> pointer -> int int pointer pointer <=> int <- pointer <- pointer Both describe the same AST. Therefore both describe the way the compiler handles it. I prefer int pointer pointer for the same reason the compiler prefers it. Timon
Jun 08 2011
parent "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On 2011-06-08 09:33, Timon Gehr wrote:
 Jonathan M Davis wrote:
 Sight correction (I was in too much of a hurry when I typed that). The
 parsing is done left-to-right just like the lexing/scanning is (it has
 to be). However, the processing of the AST is effectively done outward
 from the variable name. That is, the semantic analysis of the type is
 done outward from the variable name and thus left-to-right. So, as far
 as the compiler getting any meaning out of the type and figuring out
 what to do with it goes, it reads right-to-left, _not_ left-to-right.
 And if you try and read it like a compiler does - e.g. pointer to
 pointer to int, not int pointer pointer - then you'll end up reading it
 right-to-left too.
 
 - Jonathan M Davis
Seems like we are agreeing perfectly. As to pointer to pointer to int vs int pointer pointer, the only difference is: pointer to pointer to int <=> pointer -> pointer -> int int pointer pointer <=> int <- pointer <- pointer Both describe the same AST. Therefore both describe the way the compiler handles it. I prefer int pointer pointer for the same reason the compiler prefers it.
Except that it _does_ matter. The compiler _must_ look at types in a particular way to decipher the correctly. For instance, it's why int[10][3] a; can't be indexed with a[9][2]. That's why int[10][3] a; and int a[3][10] a; are equivalent. It has a huge impact on understanding C-style function pointers. It is _not_ interchangeable. The compiler must read types in a specific way to decipher them correctly, and that's outward from the variable name, which generally means right-to-left. - Jonathan M Davis
Jun 08 2011
prev sibling next sibling parent Sean Kelly <sean invisibleduck.org> writes:
I don't read the declaration right to left or left to right so much as insid=
e out, ie. (int[4])[3]

Sent from my iPhone

On Jun 8, 2011, at 8:38 AM, Timon Gehr <timon.gehr gmx.ch> wrote:

 Jonathan M Davis wrote:
 ...
 No, people don't normally look at declarations such as
=20
 int* a;
=20
 as being right to left. But from the compiler's perspective, they are. Th=
e
=20
 compiler doesn't look at the type of a as being an int pointer. It looks a=
t it
 as being a pointer to an int. The * comes first and then the int.
 [snip.]
=20 It is more convenient for the compiler to read the declaration left to rig=
ht to
 construct the type. (just like for people)
=20
=20
 Timon
Jun 08 2011
prev sibling parent reply Kagamin <spam here.lot> writes:
Timon Gehr Wrote:

 It is more convenient for the compiler to read the declaration left to right to
 construct the type. (just like for people)
a real example in the go language :) hello := []byte("hello, world\n")
Jun 08 2011
next sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
Kagamin wrote:
 Timon Gehr Wrote:

 It is more convenient for the compiler to read the declaration left to right to
 construct the type. (just like for people)
a real example in the go language :) hello := []byte("hello, world\n")
In your example the compiler has to parse the type "[]byte" from right to left, not left to right, to make sense out of it. That is not an example for what I was referring to. Timon
Jun 08 2011
parent reply "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On 2011-06-08 12:03, Timon Gehr wrote:
 Kagamin wrote:
 Timon Gehr Wrote:
 It is more convenient for the compiler to read the declaration left to
 right to construct the type. (just like for people)
a real example in the go language :) hello := []byte("hello, world\n")
In your example the compiler has to parse the type "[]byte" from right to left, not left to right, to make sense out of it.
Does it really? It's an array of bytes, not a byte of arrays. I fully expect that it looks at it from left-to-right. But I don't know how they implemented it. - Jonathan M Davis
Jun 08 2011
parent Timon Gehr <timon.gehr gmx.ch> writes:
Jonathan M Davis wrote:
 On 2011-06-08 12:03, Timon Gehr wrote:
 Kagamin wrote:
 Timon Gehr Wrote:
 It is more convenient for the compiler to read the declaration left to
 right to construct the type. (just like for people)
a real example in the go language :) hello := []byte("hello, world\n")
In your example the compiler has to parse the type "[]byte" from right to left, not left to right, to make sense out of it.
Does it really? It's an array of bytes, not a byte of arrays. I fully expect that it looks at it from left-to-right. But I don't know how they implemented it. - Jonathan M Davis
True, I think the input is consumed left-to-right. But as they are using a standard recursive descent parser, it will go like this: Find [] ("look" at []) -> Recursively parse another type ("look" at byte) Create [] Expression and link it to the parsed type. ("look" at []) So actually the parser looks at them in _both_ orders =). Timon
Jun 08 2011
prev sibling parent reply "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On 2011-06-08 11:48, Kagamin wrote:
 Timon Gehr Wrote:
 It is more convenient for the compiler to read the declaration left to
 right to construct the type. (just like for people)
a real example in the go language :) hello := []byte("hello, world\n")
That seems so unnatural, though I expect that you'd get used to it. I find it more horrifying that a string is typed as an array of bytes. - Jonathan M Davis
Jun 08 2011
parent Walter Bright <newshound2 digitalmars.com> writes:
On 6/8/2011 12:00 PM, Jonathan M Davis wrote:
 I find it
 more horrifying that a string is typed as an array of bytes.
Yeah, I separated chars from byte types in D because in C it was always irksome to conflate the two.
Jun 08 2011
prev sibling parent reply =?ISO-8859-1?Q?Ali_=C7ehreli?= <acehreli yahoo.com> writes:
On 06/08/2011 01:49 AM, Jonathan M Davis wrote:

 No, people don't normally look at declarations such as

 int* a;

 as being right to left. But from the compiler's perspective, they are.
I will go a little bit off topic here. If we need to think about what the compiler does or how a specific language feature is implemented, that language is a failed abstraction. D is not. There shouldn't be any need to get into implementation details to describe a language feature. This used to happen with D slices: some people would point to pictures of slices where .ptr pointed to the beginning of some elements in memory. That way of describing slices would not work on beginners who have no idea on what a pointer is, especially in a language where pointers can be avoided for a long time.
 As for static arrays in D, the problem is the disjoint between 
declarations
 and indexing.
That's very normal: declaration and indexing are separate. Why should they have any resemblance? Perhaps they both use the [] characters. That is unfortunate, similar to '*' being used in declaration and dereferencing; very different things.
 They're flipped between the two. Most people expect that the
 dimensions read left to right for both the declaration and the 
indexing, but
 they don't.
I am not one of those people. I am used to C's weird inside-out array syntax since 1989. I've always cringed at that and I've always introduced typedefs to remedy the problem. // C code #include <stdio.h> int main() { char a[4][3]; printf("%zu\n", sizeof(a[0])); // prints 3 } // C code with typedef #include <stdio.h> int main() { typedef char Row[4]; Row a[3]; printf("%zu\n", sizeof(a[0])); // NOW PRINTS 4! TIME BOMB? } The problem there is the necessity to know that Row is a typedef of some other array, so that we should now "see" 'a' as a definition of char a[3][4]. I am very happy that D solved that problem: import std.stdio; void main() { char[4][3] a; writeln(typeof(a[0]).sizeof); // prints 4 } import std.stdio; void main() { alias char[4] Row; Row[3] a; writeln(typeof(a[0]).sizeof); // STILL PRINTS 4! } I call that consistency.
 They think that

 int[4][3] a;
 auto b = a[3][2];

 is legal, because they view the left dimension in the declaration as 
being the
 left when indexing. But it's not. If you used the C syntax,

 int a[4][3];
 auto b = a[3][2];

 then the dimensions _do_ match.
They match in that way, but it is inconsistent. The following declaration is in the order of type, size, name: T[3] a; And indexing is always array[index]: a[2]; // a reference to T Now I am going to replace T with int[4]. It is still in the order of type, size, name (I am putting inserting a space to distinguish): int[4] [3] a; And indexing is still array[index]: a[2]; // a reference to int[4]; Since a[2] is a reference to int[4], now I can further index it: a[2][3]; Consistent. What I don't agree is seeing [2][3] as a single operation. They are two separate indexing operations. That's how I think to be happy. :) Ali
Jun 08 2011
next sibling parent =?ISO-8859-1?Q?Ali_=C7ehreli?= <acehreli yahoo.com> writes:
On 06/08/2011 10:38 AM, Ali Çehreli wrote:

 If we need to think about what
 the compiler does or how a specific language feature is implemented,
 that language is a failed abstraction. D is not. There shouldn't be any
 need to get into implementation details to describe a language feature.

 This used to happen with D slices: some people would point to pictures
 of slices where .ptr pointed to the beginning of some elements in
 memory. That way of describing slices would not work on beginners who
 have no idea on what a pointer is, especially in a language where
 pointers can be avoided for a long time.
Allow me to contradict myself: I've tried to pinpoint the semantics of D's slices in the past, but have failed. I remember focusing on "discretionary sharing semantics." The apparent non-deterministic behavior related to non-stomping makes it hard ("impossible" for me) to describe the semantics of slices. Steve had to get into implementation details in his "D Slices" article to describe that non-determinism. I think that strengthens my view that slices cannot be fully described without getting into implementation details. Ali
Jun 08 2011
prev sibling parent "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On 2011-06-08 10:38, Ali Çehreli wrote:
 On 06/08/2011 01:49 AM, Jonathan M Davis wrote:
 No, people don't normally look at declarations such as
 
 int* a;
 
 as being right to left. But from the compiler's perspective, they are.
I will go a little bit off topic here. If we need to think about what the compiler does or how a specific language feature is implemented, that language is a failed abstraction. D is not. There shouldn't be any need to get into implementation details to describe a language feature.
It's not really a matter of understanding how the compiler implements a specific feature so much as understanding type semantics. But yes, type declarations can be hard to read, and understanding fully does pretty much require understanding how the compiler looks at them. It's like operotor associativity and precedence. You need to understand that auto i = 7 + 12 * 2; gives i a value of 31, not 38. Type declarations are the same. You need to understand how they're constructed. They're just a more complicated example and one which you can actually misunderstand on some level but generally understand well enough to program just fine. It's more complicated type declarations (such as C-style function pointers, const pointers in C/C++, and to some extent static array declarations in D) which tend to force you to have a better understanding of type declaration semantics. Complicated type declarations are complicated, and so deciphering them can be complicated. - Jonathan M Davis
Jun 08 2011
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
I happen to like right-to-left, but that's just me.
Jun 07 2011
prev sibling parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On 2011-06-07 17:32, Andrei Alexandrescu wrote:
 There's a question related to D and Go within the first eight minutes:
=20
 http://channel9.msdn.com/Shows/Going+Deep/Herb-Sutter-C-Questions-and-Ans=
we
 rs
I find it interesting that C++0x's noexcept is still a runtime feature like= =20 exception specifications rather than going the static route that D's nothro= w=20 does. It'll be easier to implement that way, I expect, given that C++=20 compilers are already implementing exception specifications, but having it = be=20 statically-checked definitely has advantages. At least it's an improvement= =20 over exception specifications regardless. =46rom what he said about D, it definitely sounds like D is trying to go wh= ere=20 he expects a systems programming language which could challenge C++ needs t= o=20 go, though the only thing he really said in specific about D was that he=20 thinks that we missed out on not improving the declaration and expression=20 syntax such that it's left-to-right instead of right-to-left. That would be= a=20 pretty mind-bending change though, even if it were ultimately better. It=20 wouldn't surprise me if it never even occurred to Walter or anyone else=20 working on early D1 to go that route. It certainly wouldn't have ever occur= red=20 to me - particularly for the expression syntax. Thinking about it, I guess= =20 that Haskell and Scheme that way, so I've programmed in languages which wer= e=20 like that before, but they're functional, so they're already a huge paradig= m=20 shift, whereas C/C++ to D really isn't that big a shift. So, having a C-bas= ed=20 language which was left-to-right would definitely throw me off, at least=20 initially. =2D Jonathan M Davis
Jun 07 2011
parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Tue, 07 Jun 2011 22:31:20 -0400, Jonathan M Davis <jmdavisProg gmx.com>  
wrote:

 On 2011-06-07 17:32, Andrei Alexandrescu wrote:
 There's a question related to D and Go within the first eight minutes:

 http://channel9.msdn.com/Shows/Going+Deep/Herb-Sutter-C-Questions-and-Answe
 rs
I find it interesting that C++0x's noexcept is still a runtime feature like exception specifications rather than going the static route that D's nothrow does. It'll be easier to implement that way, I expect, given that C++ compilers are already implementing exception specifications, but having it be statically-checked definitely has advantages. At least it's an improvement over exception specifications regardless.
IIRC, there is already a way to statically declare that a function doesn't throw any exceptions. I think you do it with throws(). I could be wrong though, haven't used C++ in a while, and even when I did use it, I stayed away from exception specifications, having a bad experience with them. -Steve
Jun 07 2011
parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On 2011-06-07 19:41, Steven Schveighoffer wrote:
 On Tue, 07 Jun 2011 22:31:20 -0400, Jonathan M Davis <jmdavisProg gmx.com>
 
 wrote:
 On 2011-06-07 17:32, Andrei Alexandrescu wrote:
 There's a question related to D and Go within the first eight minutes:
 
 http://channel9.msdn.com/Shows/Going+Deep/Herb-Sutter-C-Questions-and-An
 swe rs
I find it interesting that C++0x's noexcept is still a runtime feature like exception specifications rather than going the static route that D's nothrow does. It'll be easier to implement that way, I expect, given that C++ compilers are already implementing exception specifications, but having it be statically-checked definitely has advantages. At least it's an improvement over exception specifications regardless.
IIRC, there is already a way to statically declare that a function doesn't throw any exceptions. I think you do it with throws(). I could be wrong though, haven't used C++ in a while, and even when I did use it, I stayed away from exception specifications, having a bad experience with them.
No, those are the exception specifications that he was talking about. It's all done at runtime, and if your function violates them, it kills your program. That's why it's generally considered good practice to only ever use throws() (which indicates that nothing is thrown), and even that isn't necessarily used much. Otherwise, if anything unexpected is ever thrown, it kills your program. noexcept is essentially identical to throws(). C++ has no features for statically verifying which exceptions are or are not thrown. - Jonathan M Davis
Jun 07 2011