www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - const?? When and why? This is ugly!

reply hasen <hasan.aljudy gmail.com> writes:
I haven't been following D for over a year .. now I notice there's a const!!

In C++, in my experience, the only time I need const is when I pass 
temporary objects by reference and the compiler refuses, so I make the 
parameter const to make the compiler happy.

void my_func( const SomeType& obj ) { ... }

This is annoying because now const propagates like a virus! any function 
that I call on `obj` must also be changed to accept a `const` reference. 
any  method on obj which doesn't change it must also be marked as 
`const` in order for it to be callable from inside this function.

This whole stupid process wouldn't even be needed in the first place if 
C++ had a garbage collector, because then I would always "new" them (as 
per Java, C#, and D)

SomeType *obj = new SomeType();

but because there's no garbage collector, I have to create the object 
not as a reference.

SomeType obj();

Again, this is all stupid C++ stuff that shouldn't even be needed in the 
first place.

However, with all that being said, that's just my opinion, maybe over 
the time some people found some actually useful uses for const, great, 
so they can use it if they want.

What really annoys me is the viral nature of const.

Yesterday I was reading this: http://www.digitalmars.com/d/2.0/const3.html

(btw, this page is empty: http://www.digitalmars.com/d/2.0/const.html )

and, to my surprise, I see:

char[] p = "world"; // error, cannot implicitly convert invariant
		    // to mutable


and all I can think of is: WHAT - THE - HELL??!!!!!!

invariant(char)[] is ugly! might as well be saying std::vector<char> 
(ok, not the best example of stupidity, but I hope you get my point).
(and, is invariant(char)[] the correct type? or must it be 
invariant(char)[5]??)

This is not the D that I loved. What's going on?

P.S. look here 
http://stackoverflow.com/questions/557011/d-programming-language-char-arrays/

I know you can use "auto" and all that, but still .. I don't feel good 
about this.
Mar 01 2009
next sibling parent reply dsimcha <dsimcha yahoo.com> writes:
== Quote from hasen (hasan.aljudy gmail.com)'s article
 I haven't been following D for over a year .. now I notice there's a const!!
 In C++, in my experience, the only time I need const is when I pass
 temporary objects by reference and the compiler refuses, so I make the
 parameter const to make the compiler happy.
 void my_func( const SomeType& obj ) { ... }
 This is annoying because now const propagates like a virus! any function
 that I call on `obj` must also be changed to accept a `const` reference.
 any  method on obj which doesn't change it must also be marked as
 `const` in order for it to be callable from inside this function.
 This whole stupid process wouldn't even be needed in the first place if
 C++ had a garbage collector, because then I would always "new" them (as
 per Java, C#, and D)
 SomeType *obj = new SomeType();
 but because there's no garbage collector, I have to create the object
 not as a reference.
 SomeType obj();
 Again, this is all stupid C++ stuff that shouldn't even be needed in the
 first place.
 However, with all that being said, that's just my opinion, maybe over
 the time some people found some actually useful uses for const, great,
 so they can use it if they want.
 What really annoys me is the viral nature of const.
 Yesterday I was reading this: http://www.digitalmars.com/d/2.0/const3.html
 (btw, this page is empty: http://www.digitalmars.com/d/2.0/const.html )
 and, to my surprise, I see:
 char[] p = "world"; // error, cannot implicitly convert invariant
 		    // to mutable
 and all I can think of is: WHAT - THE - HELL??!!!!!!
 invariant(char)[] is ugly! might as well be saying std::vector<char>
 (ok, not the best example of stupidity, but I hope you get my point).
 (and, is invariant(char)[] the correct type? or must it be
 invariant(char)[5]??)
 This is not the D that I loved. What's going on?
 P.S. look here
 http://stackoverflow.com/questions/557011/d-programming-language-char-arrays/
 I know you can use "auto" and all that, but still .. I don't feel good
 about this.

Uhh, that's what aliases are for. The string alias is defined automatically in object, and string is an alias for immutable(char)[]. Also, modulo a few library functions that use strings/immutable(char)[]s, when they should be using const(char)[]s, one can avoid const by simply not using it if one doesn't like it or doesn't need it for the program they're writing.
Mar 01 2009
next sibling parent reply grauzone <none example.net> writes:
dsimcha wrote:
 == Quote from hasen (hasan.aljudy gmail.com)'s article
 I haven't been following D for over a year .. now I notice there's a const!!
 In C++, in my experience, the only time I need const is when I pass
 temporary objects by reference and the compiler refuses, so I make the
 parameter const to make the compiler happy.
 void my_func( const SomeType& obj ) { ... }
 This is annoying because now const propagates like a virus! any function
 that I call on `obj` must also be changed to accept a `const` reference.
 any  method on obj which doesn't change it must also be marked as
 `const` in order for it to be callable from inside this function.
 This whole stupid process wouldn't even be needed in the first place if
 C++ had a garbage collector, because then I would always "new" them (as
 per Java, C#, and D)
 SomeType *obj = new SomeType();
 but because there's no garbage collector, I have to create the object
 not as a reference.
 SomeType obj();
 Again, this is all stupid C++ stuff that shouldn't even be needed in the
 first place.
 However, with all that being said, that's just my opinion, maybe over
 the time some people found some actually useful uses for const, great,
 so they can use it if they want.
 What really annoys me is the viral nature of const.
 Yesterday I was reading this: http://www.digitalmars.com/d/2.0/const3.html
 (btw, this page is empty: http://www.digitalmars.com/d/2.0/const.html )
 and, to my surprise, I see:
 char[] p = "world"; // error, cannot implicitly convert invariant
 		    // to mutable
 and all I can think of is: WHAT - THE - HELL??!!!!!!
 invariant(char)[] is ugly! might as well be saying std::vector<char>
 (ok, not the best example of stupidity, but I hope you get my point).
 (and, is invariant(char)[] the correct type? or must it be
 invariant(char)[5]??)
 This is not the D that I loved. What's going on?
 P.S. look here
 http://stackoverflow.com/questions/557011/d-programming-language-char-arrays/
 I know you can use "auto" and all that, but still .. I don't feel good
 about this.

Uhh, that's what aliases are for. The string alias is defined automatically in object, and string is an alias for immutable(char)[].

That Phobos introduces this alias is not really an argument that speaks in favor of the syntax. Also, I don't quite understand yet what constness is good for. While it seems to be a good idea, it seems to be more an annoyance in practice. It doesn't seem to pay off. What is this additional complexity for? And really, what was wrong with not having constness? All I hear is something about threading, but I didn't see anything convincing yet. No real examples, not even a full concept. Only some loose arguments. Come on, the newest compiler releases can do const, now convince me already that it's a good feature! Regarding pure functions: isn't CTFE already enough?
 Also, modulo a few library functions that use strings/immutable(char)[]s, when
 they should be using const(char)[]s, one can avoid const by simply not using
it if
 one doesn't like it or doesn't need it for the program they're writing.

Mar 02 2009
parent reply Jason House <jason.james.house gmail.com> writes:
grauzone Wrote:

 dsimcha wrote:
 == Quote from hasen (hasan.aljudy gmail.com)'s article
 Uhh, that's what aliases are for.  The string alias is defined automatically in
 object, and string is an alias for immutable(char)[].

That Phobos introduces this alias is not really an argument that speaks in favor of the syntax. Also, I don't quite understand yet what constness is good for. While it seems to be a good idea, it seems to be more an annoyance in practice. It doesn't seem to pay off. What is this additional complexity for? And really, what was wrong with not having constness? All I hear is something about threading, but I didn't see anything convincing yet. No real examples, not even a full concept. Only some loose arguments. Come on, the newest compiler releases can do const, now convince me already that it's a good feature!

Given the tone of your messages, I assume convincing you is impossible. The biggest help I can offer is to tell you that "the D you loved" still exists as D 1.0... Walter still maintains the compiler for it and Tango, Descent, GDC, LDC, and many other things all support D1.
 Regarding pure functions: isn't CTFE already enough?

The big driver of D2 is provably safe multithreading without locks. Pure functions are the embodiment of that, and immutable data is required for that. Const is used to handle either mutable or immutable data. Does that help?
Mar 02 2009
next sibling parent reply grauzone <none example.net> writes:
Jason House wrote:
 grauzone Wrote:
 
 dsimcha wrote:
 == Quote from hasen (hasan.aljudy gmail.com)'s article
 Uhh, that's what aliases are for.  The string alias is defined automatically in
 object, and string is an alias for immutable(char)[].

in favor of the syntax. Also, I don't quite understand yet what constness is good for. While it seems to be a good idea, it seems to be more an annoyance in practice. It doesn't seem to pay off. What is this additional complexity for? And really, what was wrong with not having constness? All I hear is something about threading, but I didn't see anything convincing yet. No real examples, not even a full concept. Only some loose arguments. Come on, the newest compiler releases can do const, now convince me already that it's a good feature!

Given the tone of your messages, I assume convincing you is impossible. The biggest help I can offer is to tell you that "the D you loved" still exists as D 1.0... Walter still maintains the compiler for it and Tango, Descent, GDC, LDC, and many other things all support D1.

Forgive me, I always get the tone wrong. As for the "D you loved", please don't assume things. I think D2.0 is a huge improvement over D1.0. But of course, there are always some issues. Nothing is perfect, after all. And actually, I'm not opposed to these new (actually old) ideas. I just want more information. And yes, I don't like the current const mechanism, because I think it introduces complexity for no gain. That's why I'd like to know more in the first place. And I think I'm not the only one who would prefer to see ast macros to be implemented rather than const.
 Regarding pure functions: isn't CTFE already enough?

The big driver of D2 is provably safe multithreading without locks. Pure functions are the embodiment of that, and immutable data is required for that. Const is used to handle either mutable or immutable data.

You probably mean that data shared between threads has to be immutable. Then all threads can access that data without synchronization. Immutability will sure be useful here: the type system guarantees, that data can never be modified. But how does this work for complex types like objects? Is there an idup for objects? Does it do a deep copy of an object graph? How is communication between threads supposed to work? Shouldn't all global variables be immutable then? Please, where can I find complete, thought-through concepts? Does this approach fit D at all? D is a C based system programming language. Does it work to demand from everyone to obey the const rules? Couldn't all this be done manually, instead of bothering the programmer with a complex type system? Sometimes, you have to leave the more spiffy features to languages like Erlang or Haskell which are suited better for this. For example, Erlang doesn't share any state by default, and in Haskell, everything is immutable. But they use very special mechanisms to make up for the problems caused by this, and that's why you can't just pick the cherries: it won't fit, it will feel unnatural, and everything will be a mess. It's a good idea to copy good features from other languages, but never forget where you come from. Regarding pureness: I don't think it has anything do to with locking. A function could just take const arguments, and everything is safe. It can't write to shared data either, because shared data is supposed to be immutable, right? In this context, it doesn't matter if the function writes to anything else, because that data will be thread local. This rather seems to have to do with optimization by caching results, and with automatic parallelization. Well then, I want to see how this can be applied in D! Again, forgive me my tone. I mean, it's not like I'm threatening anyone or that I want to start flamewars, I just want to know more about this.
 Does that help?

Not really. I just wasted time by writing this post, and probably the time of people who read this post. It's a shame.
Mar 02 2009
next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
grauzone wrote:
 You probably mean that data shared between threads has to be immutable. 
 Then all threads can access that data without synchronization. 
 Immutability will sure be useful here: the type system guarantees, that 
 data can never be modified. But how does this work for complex types 
 like objects? Is there an idup for objects? Does it do a deep copy of an 
 object graph? How is communication between threads supposed to work? 
 Shouldn't all global variables be immutable then? Please, where can I 
 find complete, thought-through concepts?

You cannot find them yet because the thinking-through process is still ongoing.
 Does this approach fit D at all? D is a C based system programming 
 language. Does it work to demand from everyone to obey the const rules? 
 Couldn't all this be done manually, instead of bothering the programmer 
 with a complex type system?

C is still having trouble removing those pesky buffer overruns. Writing a large manycore application in C will be anything but casual programming.
 Sometimes, you have to leave the more spiffy features to languages like 
 Erlang or Haskell which are suited better for this. For example, Erlang 
 doesn't share any state by default, and in Haskell, everything is 
 immutable. But they use very special mechanisms to make up for the 
 problems caused by this, and that's why you can't just pick the 
 cherries: it won't fit, it will feel unnatural, and everything will be a 
 mess. It's a good idea to copy good features from other languages, but 
 never forget where you come from.

We plan to add the necessary mechanisms.
 Regarding pureness: I don't think it has anything do to with locking. A 
 function could just take const arguments, and everything is safe. It 
 can't write to shared data either, because shared data is supposed to be 
 immutable, right? In this context, it doesn't matter if the function 
 writes to anything else, because that data will be thread local.

Not all shared data is immutable. Data marked as "shared" is shared. The cool thing is that D switches the default to the "right" default. The style of programming in which you create a new thread that joyously sees and can modify *all* of the memory space available to every other thread will go the way of the dinosaur. It's just not tenable anymore, and I predict today's mainstream programming languages abiding to that model are facing major troubles in the near future. Andrei
Mar 02 2009
next sibling parent reply bearophile <bearophileHUGS lycos.com> writes:
Andrei Alexandrescu:
 Not all shared data is immutable. Data marked as "shared" is shared. The 
 cool thing is that D switches the default to the "right" default.
 
 The style of programming in which you create a new thread that joyously 
 sees and can modify *all* of the memory space available to every other 
 thread will go the way of the dinosaur. It's just not tenable anymore, 
 and I predict today's mainstream programming languages abiding to that 
 model are facing major troubles in the near future.

I agree. Also, take a look at Clojure, one of the very few languages designed to manage multi-core CPUs. In Clojure you can use mutable data and data structures, but the default is immutable data. They argue that's the "right" default if you want to program for multi-core CPUs. If this and the Clojure experiment turn out as true/right, D2/D3 may have to change more :-) In the close future D std lib may enjoy to grow several immutable data structures (finger trees, etc), even if the D2 language & community on the whole has not embraced the immutability much yet. Such data structures and other features in the std lib can't hurt. We'll surely talk more about this topic. Bye, bearophile
Mar 02 2009
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
bearophile wrote:
 Andrei Alexandrescu:
 Not all shared data is immutable. Data marked as "shared" is
 shared. The cool thing is that D switches the default to the
 "right" default.
 
 The style of programming in which you create a new thread that
 joyously sees and can modify *all* of the memory space available to
 every other thread will go the way of the dinosaur. It's just not
 tenable anymore, and I predict today's mainstream programming
 languages abiding to that model are facing major troubles in the
 near future.

I agree. Also, take a look at Clojure, one of the very few languages designed to manage multi-core CPUs. In Clojure you can use mutable data and data structures, but the default is immutable data. They argue that's the "right" default if you want to program for multi-core CPUs. If this and the Clojure experiment turn out as true/right, D2/D3 may have to change more :-)

Or Clojure. (I'm not even kidding. D has a very compelling computation model that beats the pants off traditional functional approaches.) The thing is, in a few short years "if you want to program for multi-core CPUs" will sound as funny as "if you want to program for CPUs with more than 16-bit addressing" sounds today. Yet it was a valid qualification to add in the past, when 32- and 64-bit systems were a rarity.
 In the close future D std lib may enjoy to grow several immutable
 data structures (finger trees, etc), even if the D2 language &
 community on the whole has not embraced the immutability much yet.
 Such data structures and other features in the std lib can't hurt.
 We'll surely talk more about this topic.

Looking forward to your contributions to Phobos. Just drop pass-by-delegate like a bad habit. :o) Andrei
Mar 02 2009
prev sibling next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Jarrett Billingsley wrote:
 On Mon, Mar 2, 2009 at 12:25 PM, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> wrote:
 The style of programming in which you create a new thread that joyously sees
 and can modify *all* of the memory space available to every other thread
 will go the way of the dinosaur. It's just not tenable anymore, and I
 predict today's mainstream programming languages abiding to that model are
 facing major troubles in the near future.

Eheh, sounds like the dawn of protected memory 20 years ago ;)

Absolutely. The industry has cycles and a lot of its history rhymes. Things like multitasking, client-server computing, flat memory addressing, virtual memory, machine virtualization... they've all come and went a couple of times over decades. As for my bet, I'm pretty confident in it. The default-isolated model is gaining traction in newer languages, in older languages that are seeing a new youth with the advent of manycores, and even in applications. Google Chrome figured that it must use OS-provided memory isolation for its tabs. D is positioned very well, probably uniquely, to take advantage of a default-isolated model within a largely mutative language, and that is in no small part due to const and immutable. Other languages are struggling, see http://tinyurl.com/4apat7. I'm very glad that the tide on this group has effectively reversed with regard to the general opinion about const and immutable. Andrei
Mar 02 2009
next sibling parent downs <default_357-line yahoo.de> writes:
Andrei Alexandrescu wrote:
 D is positioned very well, probably uniquely, to take advantage of a
 default-isolated model within a largely mutative language, and that is
 in no small part due to const and immutable. Other languages are
 struggling, see http://tinyurl.com/4apat7. I'm very glad that the tide
 on this group has effectively reversed with regard to the general
 opinion about const and immutable.
 
 
 Andrei

I'm not convinced, I'm just withholding judgment until there's a stable 2.0 implemented with an open-source compiler. I suspect I'm not the only one here who thinks that way :)
Mar 02 2009
prev sibling parent reply grauzone <none example.net> writes:
 struggling, see http://tinyurl.com/4apat7. I'm very glad that the tide 
 on this group has effectively reversed with regard to the general 
 opinion about const and immutable.

I think they got annoyed and tired by the weekly (daily?) new const proposal threads and went silent.
Mar 02 2009
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
grauzone wrote:
 struggling, see http://tinyurl.com/4apat7. I'm very glad that the 
 tide on this group has effectively reversed with regard to the 
 general opinion about const and immutable.

I think they got annoyed and tired by the weekly (daily?) new const proposal threads and went silent.

and in another post:
 I mean, it's not like I'm threatening anyone or that I want to start
 flamewars, I just want to know more about this.

I was wondering how one goes with the other. Andrei
Mar 02 2009
prev sibling parent reply grauzone <none example.net> writes:
 Sometimes, you have to leave the more spiffy features to languages 
 like Erlang or Haskell which are suited better for this. For example, 
 Erlang doesn't share any state by default, and in Haskell, everything 
 is immutable. But they use very special mechanisms to make up for the 
 problems caused by this, and that's why you can't just pick the 
 cherries: it won't fit, it will feel unnatural, and everything will be 
 a mess. It's a good idea to copy good features from other languages, 
 but never forget where you come from.

We plan to add the necessary mechanisms.

What mechanisms will these be? I'm sure others are curious too.
Mar 02 2009
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
grauzone wrote:
 Sometimes, you have to leave the more spiffy features to languages 
 like Erlang or Haskell which are suited better for this. For example, 
 Erlang doesn't share any state by default, and in Haskell, everything 
 is immutable. But they use very special mechanisms to make up for the 
 problems caused by this, and that's why you can't just pick the 
 cherries: it won't fit, it will feel unnatural, and everything will 
 be a mess. It's a good idea to copy good features from other 
 languages, but never forget where you come from.

We plan to add the necessary mechanisms.

What mechanisms will these be? I'm sure others are curious too.

Still under discussion. We're considering for example message-passing queues a la Erlang. Andrei
Mar 02 2009
next sibling parent bearophile <bearophileHUGS lycos.com> writes:
Andrei Alexandrescu:
 We're considering for example message-passing queues a la Erlang.<

Actors, like in Erlang and Scala? (Please ignore this comment if it misses the point of this discussion). Bye, bearophile
Mar 02 2009
prev sibling next sibling parent dennis luehring <dl.soluz gmx.net> writes:
 Still under discussion. We're considering for example message-passing 
 queues a la Erlang.

yes yes yes ...
Mar 02 2009
prev sibling parent Christopher Wright <dhasenan gmail.com> writes:
Andrei Alexandrescu wrote:
 grauzone wrote:
 Sometimes, you have to leave the more spiffy features to languages 
 like Erlang or Haskell which are suited better for this. For 
 example, Erlang doesn't share any state by default, and in Haskell, 
 everything is immutable. But they use very special mechanisms to 
 make up for the problems caused by this, and that's why you can't 
 just pick the cherries: it won't fit, it will feel unnatural, and 
 everything will be a mess. It's a good idea to copy good features 
 from other languages, but never forget where you come from.

We plan to add the necessary mechanisms.

What mechanisms will these be? I'm sure others are curious too.

Still under discussion. We're considering for example message-passing queues a la Erlang. Andrei

A library-level feature, I hope, but I'd be quite interested in seeing how this would be implemented as a pure function.
Mar 03 2009
prev sibling parent reply Walter Bright <newshound1 digitalmars.com> writes:
grauzone wrote:
 Does this approach fit D at all? D is a C based system programming 
 language. Does it work to demand from everyone to obey the const rules? 
 Couldn't all this be done manually, instead of bothering the programmer 
 with a complex type system?

Doing it manually is how it's done in C. And the results are it is a massive failure. It's just impractical to write reliable, portable, inspectable, and maintainable multithreaded code in C. Even the experts can't get the trivial cases right, as there was a famous recent example in Dr. Dobb's (forgot the name of the article at the moment).
Mar 02 2009
parent reply grauzone <none example.net> writes:
Walter Bright wrote:
 grauzone wrote:
 Does this approach fit D at all? D is a C based system programming 
 language. Does it work to demand from everyone to obey the const 
 rules? Couldn't all this be done manually, instead of bothering the 
 programmer with a complex type system?

Doing it manually is how it's done in C. And the results are it is a massive failure. It's just impractical to write reliable, portable, inspectable, and maintainable multithreaded code in C. Even the experts can't get the trivial cases right, as there was a famous recent example in Dr. Dobb's (forgot the name of the article at the moment).

I didn't mean going back to programming with locks. Instead you could use the new ideas without extending the type system. As far as I understand, the language extensions are only needed for verification (so far).
Mar 02 2009
parent reply Walter Bright <newshound1 digitalmars.com> writes:
grauzone wrote:
 I didn't mean going back to programming with locks. Instead you could 
 use the new ideas without extending the type system. As far as I 
 understand, the language extensions are only needed for verification (so 
 far).

Without verification, it's programming by hopeful convention. If you want a reliable system, you need more than hope <g>.
Mar 02 2009
parent reply hasen <hasan.aljudy gmail.com> writes:
Walter Bright wrote:
 grauzone wrote:
 I didn't mean going back to programming with locks. Instead you could 
 use the new ideas without extending the type system. As far as I 
 understand, the language extensions are only needed for verification 
 (so far).

Without verification, it's programming by hopeful convention. If you want a reliable system, you need more than hope <g>.

Well .. if you think about OOP and private/public .. Dynamic languages like python and smalltalk don't enforce private/public, and that never was a problem. And, smalltalk is *the* OO language (AFAIK) (this is not really an argument against const per se, it's just an argument against an argument for const)
Mar 03 2009
parent reply Lutger <lutger.blijdestijn gmail.com> writes:
hasen wrote:

 Walter Bright wrote:
 grauzone wrote:
 I didn't mean going back to programming with locks. Instead you could 
 use the new ideas without extending the type system. As far as I 
 understand, the language extensions are only needed for verification 
 (so far).

Without verification, it's programming by hopeful convention. If you want a reliable system, you need more than hope <g>.

Well .. if you think about OOP and private/public .. Dynamic languages like python and smalltalk don't enforce private/public, and that never was a problem. And, smalltalk is *the* OO language (AFAIK) (this is not really an argument against const per se, it's just an argument against an argument for const)

If you have a dynamic language you have a different way of programming. In D when I make a typo, the compiler catches it. When I do the same in Ruby, I have a unit test that spits out a method missing exception with a trace. Suppose D doesn't catch my typo and then my application crashes at runtime without such a trace, that will be a nightmare.
Mar 04 2009
parent reply bearophile <bearophileHUGS lycos.com> writes:
Lutger:
 If you have a dynamic language you have a different way of programming. In D 
 when I make a typo, the compiler catches it. When I do the same in Ruby, I 
 have a unit test that spits out a method missing exception with a trace. 
 Suppose D doesn't catch my typo and then my application crashes at runtime 
 without such a trace, that will be a nightmare. 

This is a complex and long debated topic. In my D programs I put almost as many unittests as I put in Python programs, because experience shows me the type system of D doesn't catch that many bugs. The result seems strong enough D programs. While I debug I use the 'Phobos hack' to add something like those traces to D (I don't understand why such feature isn't built-in yet, it's essential when I debug D programs). Bye, bearophile
Mar 04 2009
next sibling parent reply Christopher Wright <dhasenan gmail.com> writes:
bearophile wrote:
 Lutger:
 If you have a dynamic language you have a different way of programming. In D 
 when I make a typo, the compiler catches it. When I do the same in Ruby, I 
 have a unit test that spits out a method missing exception with a trace. 
 Suppose D doesn't catch my typo and then my application crashes at runtime 
 without such a trace, that will be a nightmare. 

This is a complex and long debated topic. In my D programs I put almost as many unittests as I put in Python programs, because experience shows me the type system of D doesn't catch that many bugs. The result seems strong enough D programs. While I debug I use the 'Phobos hack' to add something like those traces to D (I don't understand why such feature isn't built-in yet, it's essential when I debug D programs).

Agreed on testing, and agreed on stack traces. However, how do you test the unit test system?
Mar 04 2009
parent reply bearophile <bearophileHUGS lycos.com> writes:
Christopher Wright:
However, how do you test the unit test system?<

I don't understand the question. Bye, bearophile
Mar 04 2009
parent Christopher Wright <dhasenan gmail.com> writes:
bearophile wrote:
 Christopher Wright:
 However, how do you test the unit test system?<

I don't understand the question. Bye, bearophile

If you have a system that runs unittests, how do you make sure that it is not buggy? You need to devise another test system. It's not a question that most people should care about.
Mar 04 2009
prev sibling parent reply Lutger <lutger.blijdestijn gmail.com> writes:
bearophile wrote:

 Lutger:
 If you have a dynamic language you have a different way of programming. 


 when I make a typo, the compiler catches it. When I do the same in Ruby, 


 have a unit test that spits out a method missing exception with a trace. 
 Suppose D doesn't catch my typo and then my application crashes at 


 without such a trace, that will be a nightmare. 

This is a complex and long debated topic. In my D programs I put almost as many unittests as I put in Python

that many bugs. The result seems strong enough D programs.
 While I debug I use the 'Phobos hack' to add something like those traces 

when I debug D programs).
 
 Bye,
 bearophile

I didn't mean to imply that with D the type system unit tests and stack traces are obsolete or that D is better / worse. When you say 'not that many bugs', how often does you code compile with errors? Because every compile time error you encounter is a bug in a dynamic language, and within that perspective I think it's quite a lot. Now, that doesn't mean dynamic languages are more bug prone, just that the way you program with them is different. Different enough that you can't compare type systems of static and dynamic languages that easily.
Mar 04 2009
parent reply bearophile <bearophileHUGS lycos.com> writes:
Lutger:

When you say 'not that many bugs', how often does you code compile with errors?<

I am not able to give you a good answer, I am sorry, so I can just chat a little. What I can tell you is that I now know both Python and D (I know Python more, but my experience of D is getting sufficient), and I am usually able to write correct programs in quite less time in Python. "correct programs" includes unit tests, debugging, global testing, etc too. It's not easy to tell when a program is "debugged enough", it's an art. To write a "correct" program in C I need even more time and sometimes at the end I am not sure yet the program is debugged enough (despite I know C for far more time than D). This is what I care of.
Because every compile time error you encounter is a bug in a dynamic language,
and within that perspective I think it's quite a lot.<

The situation isn't so linear. In Python I often don't put many bugs in the first place, because syntax and semantics is less bug prone or more flexible, etc. In Python I have the shell, where I can try out single lines of code or whole functions, that helps both in writing correct code and in debugging it (and later you can even copy&paste such interactive sessions, with small changes, to use them as doctests).
Now, that doesn't mean dynamic languages are more bug prone, just that the way
you program with them is different. Different enough that you can't compare
type systems of static and dynamic languages that easily.<

I agree. Yet, I have often written the same small programs in both D and Python so I can compare the whole programming time, how much long they are, how much reliable they are, etc. I have adopted in my D coding some of the good practices I have developed in Python (regarding unit testing, functional-style programming, using higher-level functions, using templates to make more flexible functions), and the results seems good enough :-) Bye, bearophile
Mar 04 2009
parent Walter Bright <newshound1 digitalmars.com> writes:
bearophile wrote:
 What I can tell you is that I now know both Python and
 D (I know Python more, but my experience of D is getting sufficient),
 and I am usually able to write correct programs in quite less time in
 Python. "correct programs" includes unit tests, debugging, global
 testing, etc too. It's not easy to tell when a program is "debugged
 enough", it's an art. To write a "correct" program in C I need even
 more time and sometimes at the end I am not sure yet the program is
 debugged enough (despite I know C for far more time than D).

This is definitely strongly related to experience. I find that over time coding in any language, I gradually write fewer and fewer bugs. I essentially learn how to avoid the ones peculiar to that particular language. A lot of influence on D comes from trying to design out of existence particular bugs in C/C++ that cost me a lot of time and effort to track down. I tend to not make those errors anymore in my C/C++ code, but the taste is still bitter and the learning curve is long. Others shouldn't have to follow the same path.
Mar 04 2009
prev sibling parent hasen <hasan.aljudy gmail.com> writes:
Jason House wrote:
 Given the tone of your messages, I assume convincing you is impossible. The
biggest help I can offer is to tell you that "the D you loved" still exists as
D 1.0... Walter still maintains the compiler for it and Tango, Descent, GDC,
LDC, and many other things all support D1.
  

Just a quick note, grauzone is not the OP, it's me :)
Mar 02 2009
prev sibling parent Jarrett Billingsley <jarrett.billingsley gmail.com> writes:
On Mon, Mar 2, 2009 at 12:25 PM, Andrei Alexandrescu
<SeeWebsiteForEmail erdani.org> wrote:
 The style of programming in which you create a new thread that joyously sees
 and can modify *all* of the memory space available to every other thread
 will go the way of the dinosaur. It's just not tenable anymore, and I
 predict today's mainstream programming languages abiding to that model are
 facing major troubles in the near future.

Eheh, sounds like the dawn of protected memory 20 years ago ;)
Mar 02 2009
prev sibling next sibling parent BCS <none anon.com> writes:
Hello hasen,

 I haven't been following D for over a year .. now I notice there's a
 const!!
 

 
 This is annoying because now const propagates like a virus!

Yes const is viral (that can't be avoided)
 This whole stupid process wouldn't even be needed in the first place
 if C++ had a garbage collector, because then I would always "new" them
 (as per Java, C#, and D)
 
 SomeType *obj = new SomeType();
 
 but because there's no garbage collector, I have to create the object
 not as a reference.
 
 SomeType obj();
 
 Again, this is all stupid C++ stuff that shouldn't even be needed in
 the first place.
 

IIRC const has exactly zero to do with new/reference/value stuff. It is totaly about knowing if somthing will get changed out from under you. This is needed to make unsable large scale libraries. And has a HUGE impact on parallel code.
 However, with all that being said, that's just my opinion, maybe over
 the time some people found some actually useful uses for const, great,
 so they can use it if they want.
 

 
 char[] p = "world"; // error, cannot implicitly convert invariant
 // to mutable
 and all I can think of is: WHAT - THE - HELL??!!!!!!

That's totally correct. On linux under D1.0 (that would work BTW) if you then try to alter p you get an access violation. String literals can't be modified and that what const/invariant says.
Mar 01 2009
prev sibling next sibling parent "Denis Koroskin" <2korden gmail.com> writes:
On Mon, 02 Mar 2009 06:28:24 +0300, hasen <hasan.aljudy gmail.com> wrote:

 I haven't been following D for over a year .. now I notice there's a  
 const!!

 In C++, in my experience, the only time I need const is when I pass  
 temporary objects by reference and the compiler refuses, so I make the  
 parameter const to make the compiler happy.

 void my_func( const SomeType& obj ) { ... }

 This is annoying because now const propagates like a virus! any function  
 that I call on `obj` must also be changed to accept a `const` reference.  
 any  method on obj which doesn't change it must also be marked as  
 `const` in order for it to be callable from inside this function.

 This whole stupid process wouldn't even be needed in the first place if  
 C++ had a garbage collector, because then I would always "new" them (as  
 per Java, C#, and D)

 SomeType *obj = new SomeType();

 but because there's no garbage collector, I have to create the object  
 not as a reference.

 SomeType obj();

 Again, this is all stupid C++ stuff that shouldn't even be needed in the  
 first place.

 However, with all that being said, that's just my opinion, maybe over  
 the time some people found some actually useful uses for const, great,  
 so they can use it if they want.

 What really annoys me is the viral nature of const.

 Yesterday I was reading this:  
 http://www.digitalmars.com/d/2.0/const3.html

 (btw, this page is empty: http://www.digitalmars.com/d/2.0/const.html )

 and, to my surprise, I see:

 char[] p = "world"; // error, cannot implicitly convert invariant
 		    // to mutable


 and all I can think of is: WHAT - THE - HELL??!!!!!!

 invariant(char)[] is ugly! might as well be saying std::vector<char>  
 (ok, not the best example of stupidity, but I hope you get my point).
 (and, is invariant(char)[] the correct type? or must it be  
 invariant(char)[5]??)

 This is not the D that I loved. What's going on?

 P.S. look here  
 http://stackoverflow.com/questions/557011/d-programming-language-char-arrays/

 I know you can use "auto" and all that, but still .. I don't feel good  
 about this.

I you don't understand something, it doesn't mean something is wrong with the language. Perhaps, something wrong with you. Regarding this exaple: char[] p = "world"; It is rejected for a reason. Modifying the "world" through p will cause a segfault anyway. So it *must* be const. In case it won't, it will cause bugs that are even worse to track: // file 1 char[] a = "hello"; a[4] = '!'; // file 2 writefln("hello"); // prints 'hell!'
Mar 02 2009
prev sibling parent reply hasen <hasan.aljudy gmail.com> writes:
hasen wrote:
 I haven't been following D for over a year .. now I notice there's a 
 const!!
 
 [...]

It seems the argument is centered around making "pure functions" possible. But, surely there's a better way of doing this than borrowing const from C++. Just like import is a better approach than #include and `namespace` Yesterday I noticed this page http://www.digitalmars.com/d/2.0/const-faq.html which I haven't seen before posting the topic yesterday. Argument #2 reads: "It makes for interfaces that can be relied upon, which becomes increasingly important the more people that are involved with the code. In other words, it scales very well." I think this is not worth the complexity, but then again, Argument#4 renders #2 as insiginificant, so I won't bother too much arguing against #2. #4 reads: "The future of programming will be multicore, multithreaded. Languages that make it easy to program them will supplant languages that don't." So, this is driven by the need to popularize D as a very good tool for multicore applications! "Transitive const is key to bringing D into this paradigm." Really? have you considered other possibilities? How about, adding a new attribute to functions: `pure` pure real sin( real x ) { ... } and design the rest around this concept. The compiler must make sure that this function is really pure: - native types must be passed by value, not by reference - doesn't accept pointers - <insert some condition for objects and arrays> If these requirements aren't met, the compiler will spit some error message "in function <F>: doing <X> voilates the `pure` attribute" objects and arrays will need some special treatment or requirements in order to be passed to pure functions. What are those requirements? I have given it a very deep thought yet(*), but I'm sure this approach is better than `const`. Also, make `string` a builtin type that's immutable (like python), and discourage the use of char[] as a type for strings, (unless used to implement a special string class). The need for a special string type also stems from the fact that char[a..b] slices bytes, not characters! (*) A quick idea might be: - For arrays, any statement of the type `a[b] = c` will be illegal inside a pure function. and pure functions can only call pure functions. - For objects, any statement of the form `a.b = c` is illegal, and there must be a way to know if a method call will change the object or not. (It would be best if the compiler could detect this automatically if it's possible). - Another approach, is to prohibit passing objects all together, and introduce some new construct that's immutable (such as a tuple, again, like python). `pure` will probably have the same viral effects as `const`, in that any function called from a pure function must also be pure, and this viral nature will propagate to classes/objects as well. However, the advantage is not complicating the type system more than is needed. Also, what's the deal with const pointers?? Why should `pure` function be able to use pointers at all? Is there any real-life use case where a pure function needs to access memory instead of some abstract concept like a variable/array/tuple? If you think about it, CTFE (compile time function execution) are `pure` already, and they're detected automatically by the compiler, with no need for explicitly marking them as such.
Mar 02 2009
next sibling parent bearophile <bearophileHUGS lycos.com> writes:
hasen:
 Really? have you considered other possibilities?
 How about, adding a new attribute to functions: `pure`

D2 already implements of plans to implement both transitive immutability, pure functions and to make by default data not accessible between threads :-) See pure here: http://www.digitalmars.com/d/2.0/function.html (And in the future it will probably adopt even more immutability-related idioms and data structures). Bye, bearophile
Mar 02 2009
prev sibling next sibling parent Jarrett Billingsley <jarrett.billingsley gmail.com> writes:
On Mon, Mar 2, 2009 at 1:32 PM, hasen <hasan.aljudy gmail.com> wrote:

 How about, adding a new attribute to functions: `pure`

 pure real sin( real x ) { ... }

 and design the rest around this concept.

 The compiler must make sure that this function is really pure:
 - native types must be passed by value, not by reference
 - doesn't accept pointers
 - <insert some condition for objects and arrays>

 If these requirements aren't met, the compiler will spit some error message
 "in function <F>: doing <X> voilates the `pure` attribute"

Umm.. maybe you didn't read far enough, but D2 already has pure functions. http://www.digitalmars.com/d/2.0/function.html
 Also, make `string` a builtin type that's immutable (like python), and
 discourage the use of char[] as a type for strings, (unless used to
 implement a special string class).

 The need for a special string type also stems from the fact that char[a..b]
 slices bytes, not characters!

Again, 'string' is defined as an alias to invariant(char)[]. It's an immutable builtin type. It still has the problem of slicing/indexing on bytes rather than characters, but the alias is already there, Phobos already uses it extensively, and if it were changed to a struct in the future it would probably cause few to no problems.
Mar 02 2009
prev sibling next sibling parent BCS <ao pathlink.com> writes:
Reply to hasen,

 "Transitive const is key to bringing D into this paradigm."
 
 Really? have you considered other possibilities?
 
 How about, adding a new attribute to functions: `pure`
 
 pure real sin( real x ) { ... }
 
 and design the rest around this concept.

A lot of the current const system IS designed around plans to add pure functions. You can almost read immutable as "valid as an arg for a pure function call."
 
 The compiler must make sure that this function is really pure:
 - native types must be passed by value, not by reference
 - doesn't accept pointers
 - <insert some condition for objects and arrays>
 If these requirements aren't met, the compiler will spit some error
 message "in function <F>: doing <X> voilates the `pure` attribute"
 

Um... that would be even more restrictive than const. Outside pointers const is more or less irrelevant with regards to function arguments so you might as well have said "pure functions can't take anything that is const or CAN be const"
 objects and arrays will need some special treatment or requirements in
 order to be passed to pure functions.

Const is a lot of very smart peoples best effort to do that special treatment.
 (*) A quick idea might be:
 - For arrays, any statement of the type `a[b] = c` will be illegal
 inside a pure function. and pure functions can only call pure
 functions.

pure int fn() { int[5] foo; foo[0] = 5; /// why ban this return foo[0]; }
 However, the advantage is not complicating the type system more than
 is needed.
 
 Also, what's the deal with const pointers?? Why should `pure` function
 be able to use pointers at all? Is there any real-life use case where
 a pure function needs to access memory instead of some abstract
 concept like a variable/array/tuple?

Say I have several pre computed multi-MB tables that need to be used by a function. The tables never change. The function is still pure but I really can't pass the table on the stack. The same thing to a lesser degree happens with any reference type that is much larger than a pointer.
Mar 02 2009
prev sibling parent Lutger <lutger.blijdestijn gmail.com> writes:
hasen wrote:

 hasen wrote:
 I haven't been following D for over a year .. now I notice there's a 
 const!!
 
 [...]

It seems the argument is centered around making "pure functions" possible. But, surely there's a better way of doing this than borrowing const from C++.

Reading the docs you must have noticed the difference between C++ const and D. In D, const and immutable are transitive, in C++ they are not. D has immutable, C++ does not. These two are the most important concepts and make the D design that much different, you can't seriously claim it is borrowed from C++. Const in C++ is (merely) a compiler aided documentation tool, whereas const+immutable in D are the basis of a functional programming niche inside D.
Mar 02 2009