www.digitalmars.com         C & C++   DMDScript  

D - D Artifacts from C and C++

reply Garen <garen_nospam_ wsu.edu> writes:
What is the rationale for retaining the use of the * operator for pointers
(if any)?   It introduces another meaning for * besides multiplication that
is context dependant.  I personally have always found it rather
unintuitive, and prefer the semantics of a reference but without it's
declarator syntax. 

So instead of "int* p;"  Why not just simply use "ref p;"?  Which behaves
like: "int& p;"?  I've noticed that people get easily confused by more than
one level of indirection.

Also, why does D bother using the keyword "template"?  Instead of:

template Foo(T) { }

Why not:

Foo(type T) { } // Kind of the opposite of void. C++ uses typename.

The syntax for specialization also seems a bit unintuitive to me.  I would
think this is more clear:

Foo(type T) { ... }   // Function Foo for any arbitrary type
Foo(type T[]) { ... } // Function Foo for any arbitrary array type
Foo(char C) { ... }   // Function Foo for the type char
Foo(char C[]) { ... } // Function Foo for an array of type char

That makes it clear that it's just like an ordinary function, but it's input
is for arbitrary types and is less typing.  Any C programmer could probably
pick that up in an instant and not even have to ever hear the word
"template." 

The problem then, is that they have to be explicitly instantiated.  How
come?
Jan 21 2003
next sibling parent reply "Mike Wynn" <mike.wynn l8night.co.uk> writes:
I have often wondered what would happen if you change
unary & in C to unary  
and unary * to $

would remove the

int func( int * p, int * q ) {
    return *p/*q;  /* compiles but buggy :) */
}

bug ( only returns *p ?)

"Garen" <garen_nospam_ wsu.edu> wrote in message
news:b0l0sf$fcn$1 digitaldaemon.com...
 What is the rationale for retaining the use of the * operator for pointers
 (if any)?   It introduces another meaning for * besides multiplication

 is context dependant.  I personally have always found it rather
 unintuitive, and prefer the semantics of a reference but without it's
 declarator syntax.

 So instead of "int* p;"  Why not just simply use "ref p;"?  Which behaves
 like: "int& p;"?  I've noticed that people get easily confused by more

 one level of indirection.

 Also, why does D bother using the keyword "template"?  Instead of:

 template Foo(T) { }

 Why not:

 Foo(type T) { } // Kind of the opposite of void. C++ uses typename.

 The syntax for specialization also seems a bit unintuitive to me.  I would
 think this is more clear:

 Foo(type T) { ... }   // Function Foo for any arbitrary type
 Foo(type T[]) { ... } // Function Foo for any arbitrary array type
 Foo(char C) { ... }   // Function Foo for the type char
 Foo(char C[]) { ... } // Function Foo for an array of type char

 That makes it clear that it's just like an ordinary function, but it's

 is for arbitrary types and is less typing.  Any C programmer could

 pick that up in an instant and not even have to ever hear the word
 "template."

 The problem then, is that they have to be explicitly instantiated.  How
 come?

Jan 21 2003
parent reply Antti Sykari <jsykari gamma.hut.fi> writes:
"Mike Wynn" <mike.wynn l8night.co.uk> writes:

 I have often wondered what would happen if you change
 unary & in C to unary  
 and unary * to $

 would remove the

 int func( int * p, int * q ) {
     return *p/*q;  /* compiles but buggy :) */
 }

 bug ( only returns *p ?)

Actually, doesn't compile (missing semicolon...) But I see, _that's_ why every style guide recommends that you leave a space around the arithmetic operators, as in (*p / *q), and _not_ because of the increased readability? Right? :) -Antti
Jan 22 2003
parent "Mike Wynn" <mike.wynn l8night.co.uk> writes:
"Antti Sykari" <jsykari gamma.hut.fi> wrote in message
news:864r81o6mr.fsf hoastest1-8c.hoasnet.inet.fi...
 "Mike Wynn" <mike.wynn l8night.co.uk> writes:

 I have often wondered what would happen if you change
 unary & in C to unary  
 and unary * to $

 would remove the

 int func( int * p, int * q ) {
     return *p/*q;  /* compiles but buggy :) */
 }

 bug ( only returns *p ?)

Actually, doesn't compile (missing semicolon...)

o.k. yes I forgot to put a ; after the comment, still it can take hours to work out why things like that don't compiler even experianced programmers get into those situations when you can't see the wood for the trees, when a missing ';' causes the compiler to report an error 1 or 2 lines past the missing ';' and yes my syntax highlighting editor displays it correctly, but not everyone uses one, and if you are generating your code then you can introduce this without realising it.
 But I see, _that's_ why every style guide recommends that you leave a
 space around the arithmetic operators, as in (*p / *q), and _not_
 because of the increased readability? Right? :)

'/' do not require spaces, so it should be valid to not put a space under all conditions style should not be required for correct function. (unless your using python) int func( int * p, int * q ) { return *p/*q; /* compiles but buggy :) */; }
Jan 22 2003
prev sibling next sibling parent reply "Sean L. Palmer" <seanpalmer directvinternet.com> writes:
"Garen" <garen_nospam_ wsu.edu> wrote in message
news:b0l0sf$fcn$1 digitaldaemon.com...
 What is the rationale for retaining the use of the * operator for pointers
 (if any)?   It introduces another meaning for * besides multiplication

 is context dependant.  I personally have always found it rather
 unintuitive, and prefer the semantics of a reference but without it's
 declarator syntax.

 So instead of "int* p;"  Why not just simply use "ref p;"?  Which behaves
 like: "int& p;"?  I've noticed that people get easily confused by more

 one level of indirection.

Because how do you tell the difference between manipulating the pointer and manipulating what it's pointing to? We'd need some kind of way to differentiate.
 Also, why does D bother using the keyword "template"?  Instead of:

 template Foo(T) { }

 Why not:

 Foo(type T) { } // Kind of the opposite of void. C++ uses typename.

Because that looks just like a K&R function definition, and very similar to a function call. I like Burton Radon's syntax better.
 The syntax for specialization also seems a bit unintuitive to me.  I would
 think this is more clear:

 Foo(type T) { ... }   // Function Foo for any arbitrary type
 Foo(type T[]) { ... } // Function Foo for any arbitrary array type
 Foo(char C) { ... }   // Function Foo for the type char
 Foo(char C[]) { ... } // Function Foo for an array of type char

 That makes it clear that it's just like an ordinary function, but it's

 is for arbitrary types and is less typing.  Any C programmer could

 pick that up in an instant and not even have to ever hear the word
 "template."

I agree that genericism should be at the core of the language, not a bolt-on. Burton Radon's syntax is closer to being ideal.
 The problem then, is that they have to be explicitly instantiated.  How
 come?

I'll let Walter field that one. Sean
Jan 22 2003
parent reply Garen Parham <garen_nospam_ wsu.edu> writes:
Sean L. Palmer wrote:
 
 Because how do you tell the difference between manipulating the pointer 
 and manipulating what it's pointing to?  We'd need some kind of way to
 differentiate.
 

Most of the time someone wants to manipulate what it's pointing to I think. To manipulate the "pointer" itself, you could just use the address-of operator &, or perhaps even treat it as a property of a reference like e.g.: ref int a; a.addr++; Which I'd think is much clearer than: *p++; Which then to make sense of, requies that one knows the precedence of the operators * and ++. Not good form, IMO.
 Also, why does D bother using the keyword "template"?  Instead of:

 template Foo(T) { }

 Why not:

 Foo(type T) { } // Kind of the opposite of void. C++ uses typename.

Because that looks just like a K&R function definition, and very similar to a function call. I like Burton Radon's syntax better.

K&R function definitions were much uglier: void Foo(a,b,c) int a; char b; float c; { ... } The more concise form and prototyping them came from C++. Seems more readable to me than writing out the keyword template all over. ...
 Burton Radon's syntax is closer to being ideal.

Why?
Jan 22 2003
parent reply "Sean L. Palmer" <seanpalmer directvinternet.com> writes:
"Garen Parham" <garen_nospam_ wsu.edu> wrote in message
news:b0m3fu$12af$1 digitaldaemon.com...
 Sean L. Palmer wrote:
 Because how do you tell the difference between manipulating the pointer
 and manipulating what it's pointing to?  We'd need some kind of way to
 differentiate.

Most of the time someone wants to manipulate what it's pointing to I

 To manipulate the "pointer" itself, you could just use the address-of
 operator &,

Bzzt... &address-of generates a rvalue pointer; you can't change it.
 or perhaps even treat it as a property of a reference like
 e.g.:
 ref int a;

 a.addr++;

 Which I'd think is much clearer than:
 *p++;

But it's not clearer than the actual C equivalent, p++; Myself I'd use ++p; instead.
 Which then to make sense of, requies that one knows the precedence of the
 operators * and ++.  Not good form, IMO.

Of course you have to know the precedence table. In order to be able to call yourself a programmer of a given language, you must demonstrate having learned the precedence table.
 Also, why does D bother using the keyword "template"?  Instead of:

 template Foo(T) { }

 Why not:

 Foo(type T) { } // Kind of the opposite of void. C++ uses typename.

Because that looks just like a K&R function definition, and very similar to a function call. I like Burton Radon's syntax better.

K&R function definitions were much uglier: void Foo(a,b,c) int a; char b; float c; { ... } The more concise form and prototyping them came from C++. Seems more readable to me than writing out the keyword template all over. ...
 Burton Radon's syntax is closer to being ideal.

Why?

It integrates the types in where they're used. Something like: void Swap(inout $T a, inout $T b) { $T temp = a; a = b; b = temp; } P.S. why is there no swap, min, max, abs builtin to D? These are so common and basic you might as well make operators for them.
Jan 22 2003
parent Garen Parham <garen_nospam_ wsu.edu> writes:
Sean L. Palmer wrote:
 
 Bzzt... &address-of generates a rvalue pointer;   you can't change it.
 

Sure you can, you just..do it. :) Though, maybe it's not a good idea but it wasn't what I was getting at.
 
 But it's not clearer than the actual C equivalent,
 p++;
 
 Myself I'd use
 ++p;
 instead.
 

I do that too, but I think thats another unnecessary artifact (difference between postfix and prefix -- only one needed I think.)
 
 Of course you have to know the precedence table.  In order to be able to
 call yourself a programmer of a given language, you must demonstrate 
 having learned the precedence table.
 

I'd expect just about anyone to be able to know the precedence between the basic arithmetic operators (*, /, +, -) since it's taught in gradeschool (I should hope) but * and ++ or -- are language idiosyncracies. Why raise an artificial barrier where none is needed? (Granted, it may not seem that significant.) The built-in property of addr seems pretty straightforward to me.
 
 It integrates the types in where they're used.  Something like:
 
 void Swap(inout $T a, inout $T b)
 {
     $T temp = a; a = b; b = temp;
 }
 

Looks similar in form to the suggestion I had with using a keyword like "type" except here it's $. I don't think I saw anything like that on the web page though.. Something floating around here in the NG I missed?
 P.S. why is there no swap, min, max, abs builtin to D?  These are so 
 common and basic you might as well make operators for them. 

Hmm.. e.g. min(a,b)? Wonder if a built-in swap might allow some optimizations not as easily done by using a template or basic function.
Jan 22 2003
prev sibling parent reply "Walter" <walter digitalmars.com> writes:
"Garen" <garen_nospam_ wsu.edu> wrote in message
news:b0l0sf$fcn$1 digitaldaemon.com...
 What is the rationale for retaining the use of the * operator for pointers
 (if any)?   It introduces another meaning for * besides multiplication

 is context dependant.  I personally have always found it rather
 unintuitive, and prefer the semantics of a reference but without it's
 declarator syntax.

 So instead of "int* p;"  Why not just simply use "ref p;"?  Which behaves
 like: "int& p;"?  I've noticed that people get easily confused by more

 one level of indirection.

D retains the * notation for pointers so that use of pointers will stand out in the code. Most D code will not need to use pointers at all. D doesn't support the int& reference notation, because references are handled by other methods.
 Also, why does D bother using the keyword "template"?  Instead of:

 template Foo(T) { }

 Why not:

 Foo(type T) { } // Kind of the opposite of void. C++ uses typename.

 The syntax for specialization also seems a bit unintuitive to me.  I would
 think this is more clear:

 Foo(type T) { ... }   // Function Foo for any arbitrary type
 Foo(type T[]) { ... } // Function Foo for any arbitrary array type
 Foo(char C) { ... }   // Function Foo for the type char
 Foo(char C[]) { ... } // Function Foo for an array of type char

 That makes it clear that it's just like an ordinary function, but it's

 is for arbitrary types and is less typing.  Any C programmer could

 pick that up in an instant and not even have to ever hear the word
 "template."

Templates in D are more than just functions. An entire group of declarations can be wrapped in a template block, conceptually like wrapping a group in a class block.
 The problem then, is that they have to be explicitly instantiated.  How
 come?

Explicit instantiation is an enormous simplification, both conceptually and practically.
Jan 22 2003
parent reply Garen Parham <garen_nospam_ wsu.edu> writes:
Walter wrote:
 
 D retains the * notation for pointers so that use of pointers will stand 
 out in the code. Most D code will not need to use pointers at all. D 
 doesn't support the int& reference notation, because references are 
 handled by other methods.

Dereferencing pointers using * stands out, but the way they are declared is still confusing I think. A hybrid approach of: ref int a; *a = whatever Could retain the easier-to-spot use of * for dereferencing. Seems a bit non-orthogonal to 'alias' though..
 
 Templates in D are more than just functions. An entire group of 
 declarations can be wrapped in a template block, conceptually like 
 wrapping a group in a class block.
 

I only chose functions there as an illustrate example. With a "block" are you thinking of something like: type T { .. // all code in here parameterized by T } ?
 
 Explicit instantiation is an enormous simplification, both conceptually 
 and practically.
 

In ADA I didn't find it of much value and liked it being implicit in C++. In what sense is it simpler? Easier to implement? Btw I think D looks really neat, save for the declarator syntax. Way to go. :)
Jan 22 2003
parent reply "Walter" <walter digitalmars.com> writes:
"Garen Parham" <garen_nospam_ wsu.edu> wrote in message
news:b0n25h$1m0u$1 digitaldaemon.com...
 Templates in D are more than just functions. An entire group of
 declarations can be wrapped in a template block, conceptually like
 wrapping a group in a class block.

are you thinking of something like: type T { .. // all code in here parameterized by T } ?

No, like a class declaration can enclose variables, functions, enums, etc.
 Explicit instantiation is an enormous simplification, both conceptually
 and practically.

In what sense is it simpler? Easier to implement?

Yes, it's easier to implement, easier to write, and easier to read the code.
 Btw I think D looks really neat, save for the declarator syntax.  Way to

 :)

Thanks!
Jan 22 2003
parent Garen Parham <garen_nospam_ wsu.edu> writes:
Walter wrote:


 
 No, like a class declaration can enclose variables, functions, enums, etc.
 

Ok, cool!
 
 Yes, it's easier to implement, easier to write, and easier to read the 
 code.
 

Ok, but still only agree with the first reason.
 
 Thanks!
 

yw! :)
Jan 25 2003