www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Does D have too many features?

reply Walter Bright <newshound2 digitalmars.com> writes:
Andrei and I had a fun discussion last night about this question. The idea was 
which features in D are redundant and/or do not add significant value?

A couple already agreed upon ones are typedef and the cfloat, cdouble and creal 
types.

What's your list?
Apr 28 2012
next sibling parent reply deadalnix <deadalnix gmail.com> writes:
Le 28/04/2012 20:47, Walter Bright a écrit :
 Andrei and I had a fun discussion last night about this question. The
 idea was which features in D are redundant and/or do not add significant
 value?

 A couple already agreed upon ones are typedef and the cfloat, cdouble
 and creal types.

 What's your list?
I think many D features come from the lack of AOP in D. I already mentioned that in some other thread. I would also mention the is expression which does way too many stuffs and many of them are not usefull or counter intuitive and may be replaced by lib support in std.traits .
Apr 28 2012
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 04/28/2012 09:11 PM, deadalnix wrote:
 Le 28/04/2012 20:47, Walter Bright a écrit :
 Andrei and I had a fun discussion last night about this question. The
 idea was which features in D are redundant and/or do not add significant
 value?

 A couple already agreed upon ones are typedef and the cfloat, cdouble
 and creal types.

 What's your list?
I think many D features come from the lack of AOP in D. I already mentioned that in some other thread.
Many times, actually. But you have *never* sketched how support for AOP would look like.
 I would also mention the is expression which does way too many stuffs
 and many of them are not usefull or counter intuitive and may be
 replaced by lib support in std.traits .
Apr 28 2012
parent reply deadalnix <deadalnix gmail.com> writes:
Le 28/04/2012 22:25, Timon Gehr a écrit :
 On 04/28/2012 09:11 PM, deadalnix wrote:
 Le 28/04/2012 20:47, Walter Bright a écrit :
 Andrei and I had a fun discussion last night about this question. The
 idea was which features in D are redundant and/or do not add significant
 value?

 A couple already agreed upon ones are typedef and the cfloat, cdouble
 and creal types.

 What's your list?
I think many D features come from the lack of AOP in D. I already mentioned that in some other thread.
Many times, actually. But you have *never* sketched how support for AOP would look like.
Off topic. I discussed several proposals, and I invest time ever since to come up with a good solution. Introducing a whole new paradigm in a language isn't something light. AST manipulation at compile time is the key.
Apr 28 2012
parent Jacob Carlborg <doob me.com> writes:
On 2012-04-29 00:02, deadalnix wrote:

 Off topic. I discussed several proposals, and I invest time ever since
 to come up with a good solution. Introducing a whole new paradigm in a
 language isn't something light.

 AST manipulation at compile time is the key.
This would be awesome to have. -- /Jacob Carlborg
Apr 29 2012
prev sibling next sibling parent reply "Nick Sabalausky" <SeeWebsiteToContactMe semitwist.com> writes:
"Walter Bright" <newshound2 digitalmars.com> wrote in message 
news:jnhe1i$2vcm$1 digitalmars.com...
 Andrei and I had a fun discussion last night about this question. The idea 
 was which features in D are redundant and/or do not add significant value?

 A couple already agreed upon ones are typedef and the cfloat, cdouble and 
 creal types.

 What's your list?
Off the top of my head: - Using function stubs so the implementation can be provided in a separate source and linked in. (Outside of .di files anyway.) - Comma operator - Version blocks: They should be replaced with something that utilizes "static if".
Apr 28 2012
parent reply "SomeDude" <lovelydear mailmetrash.com> writes:
On Saturday, 28 April 2012 at 19:21:51 UTC, Nick Sabalausky wrote:
 "Walter Bright" <newshound2 digitalmars.com> wrote in message

 - Version blocks: They should be replaced with something that 
 utilizes
 "static if".
Version could be replaced with "static if", but I like them, it makes code more readable, so I don't think they should go. We don't want to have a "static if hell", where templating code is mixed with version configuration. I think the version keyword is very good. I think instead of thinking about removing features, the more important thing is polishing the existing ones so that they work properly. D is a big language because it tries to span a broad range of uses. Removing complexity from the core language often means adding complexity in the user code, and that's what we don't want.
Apr 28 2012
parent reply "q66" <quaker66 gmail.com> writes:
On Saturday, 28 April 2012 at 20:05:30 UTC, SomeDude wrote:
 On Saturday, 28 April 2012 at 19:21:51 UTC, Nick Sabalausky 
 wrote:
 "Walter Bright" <newshound2 digitalmars.com> wrote in message

 - Version blocks: They should be replaced with something that 
 utilizes
 "static if".
Version could be replaced with "static if", but I like them, it makes code more readable, so I don't think they should go. We don't want to have a "static if hell", where templating code is mixed with version configuration. I think the version keyword is very good. I think instead of thinking about removing features, the more important thing is polishing the existing ones so that they work properly. D is a big language because it tries to span a broad range of uses. Removing complexity from the core language often means adding complexity in the user code, and that's what we don't want.
There are minimalistic languages that don't add too much complexity, instead it results in code being kept simple. D needs to do something it does really well and concentrate on that. Otherwise the language will remain being rather vague and doing "a bit of everything, but nothing truly well". Instead of adding more and more features into a rigid language, it needs to be made more flexible and extensible, both syntactically and semantically.
Apr 28 2012
parent reply "SomeDude" <lovelydear mailmetrash.com> writes:
On Saturday, 28 April 2012 at 20:09:50 UTC, q66 wrote:
 On Saturday, 28 April 2012 at 20:05:30 UTC, SomeDude wrote:

 There are minimalistic languages that don't add too much 
 complexity, instead it results in code being kept simple.
I appreciate minimalistic languages. I love the simplicity of Scheme and the design of Lua. Lua and Python are extensible language, but truth be told, they cannot handle large scale programming. In fact, I don't know of any minimalistic language that can scale from hundreds of thousands to millions of lines of code. When you reach these sizes, their simple design becomes a drawback. You start missing lots of features. When you reach large scale programming, you want really powerful tools. That's basically what the Java designers discovered after experience. The original language was simple and easy, but that simplicity translated into way too much boilerplate code. So they kept adding features from version to version, generics, then annotations, a means to create new keywords. And now they would like to add delegates. These are all needed in large programs.
 D needs to do something it does really well and concentrate on 
 that. Otherwise the language will remain being rather vague and 
 doing "a bit of everything, but nothing truly well".
It does a lot of things well already. Our point of comparison Ocaml, i.e languages that are designed to develop large systems. But most of all it needs to stabilize and polish, not change all the time. I think its feature set is very good already. We are far from having explored all its possibilities.
 Instead of adding more and more features into a rigid language, 
 it needs to be made more flexible and extensible, both 
 syntactically and semantically.
Apr 28 2012
parent reply "q66" <quaker66 gmail.com> writes:
On Saturday, 28 April 2012 at 20:35:40 UTC, SomeDude wrote:
 On Saturday, 28 April 2012 at 20:09:50 UTC, q66 wrote:
 On Saturday, 28 April 2012 at 20:05:30 UTC, SomeDude wrote:

 There are minimalistic languages that don't add too much 
 complexity, instead it results in code being kept simple.
I appreciate minimalistic languages. I love the simplicity of Scheme and the design of Lua. Lua and Python are extensible language, but truth be told, they cannot handle large scale programming. In fact, I don't know of any minimalistic language that can scale from hundreds of thousands to millions of lines of code. When you reach these sizes, their simple design becomes a drawback. You start missing lots of features. When you reach large scale programming, you want really powerful tools. That's basically what the Java designers discovered after experience. The original language was simple and easy, but that simplicity translated into way too much boilerplate code. So they kept adding features from version to version, generics, then annotations, a means to create new keywords. And now they would like to add delegates. These are all needed in large programs.
 D needs to do something it does really well and concentrate on 
 that. Otherwise the language will remain being rather vague 
 and doing "a bit of everything, but nothing truly well".
It does a lot of things well already. Our point of comparison Ocaml, i.e languages that are designed to develop large systems. But most of all it needs to stabilize and polish, not change all the time. I think its feature set is very good already. We are far from having explored all its possibilities.
 Instead of adding more and more features into a rigid 
 language, it needs to be made more flexible and extensible, 
 both syntactically and semantically.
This kind of attitude "we need big fat bullshit like Java and heavy use of OO and idioms and EH and all that other crap" is broken and false. And you have no way to prove that Python for example wouldn't scale for large projects; its main fault is that the default implementation is rather slow, but it's not pretty much missing anything required for a large project.
Apr 28 2012
next sibling parent reply "SomeDude" <lovelydear mailmetrash.com> writes:
On Saturday, 28 April 2012 at 20:59:48 UTC, q66 wrote:
 This kind of attitude "we need big fat bullshit like Java and 
 heavy use of OO and idioms and EH and all that other crap" is 
 broken and false. And you have no way to prove that Python for 
 example wouldn't scale for large projects; its main fault is 
 that the default implementation is rather slow, but it's not 
 pretty much missing anything required for a large project.
Python has two big drawbacks for large projects: - it's too slow - it's a dynamically-typed language The fact that it's flexible is because it uses duck typing, and AFAIK you can't do duck typing in a statically typed language. So it's cool for small programs, but it can't handle large ones because it's not statically typed. And this opinion doesn't come just out of thin air, I speak from my own professional experience.
Apr 28 2012
next sibling parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Sat, Apr 28, 2012 at 11:12:38PM +0200, SomeDude wrote:
 On Saturday, 28 April 2012 at 20:59:48 UTC, q66 wrote:
This kind of attitude "we need big fat bullshit like Java and
heavy use of OO and idioms and EH and all that other crap" is
broken and false. And you have no way to prove that Python for
example wouldn't scale for large projects; its main fault is that
the default implementation is rather slow, but it's not pretty
much missing anything required for a large project.
Python has two big drawbacks for large projects: - it's too slow - it's a dynamically-typed language The fact that it's flexible is because it uses duck typing, and AFAIK you can't do duck typing in a statically typed language. So it's cool for small programs, but it can't handle large ones because it's not statically typed. And this opinion doesn't come just out of thin air, I speak from my own professional experience.
Who says D doesn't have duck-typing? template isADuck(T) { alias isADuck = is(typeof(T.quack())==bool); } void petADuck(T)(T duck) if (isADuck!T) { duck.quack(); } You can pass anything that has a quack() method to the function: struct CanadianDuck { void quack() { writeln("Quack, eh?"); } } class AmericanDuck { void quack() { writeln("Quack, yo!"); } } struct RubberDuck { void opDispatch!(string S)() { auto d = loadRuntimeDuckClass(); d.callMethod(S); } } struct Cow { void moo() { writeln("Mooo!"); } } void main() { CanadianDuck caddie; AmericanDuck quacker = new AmericanDuck; RubberDuck runtimeDuck; Cow orker; // Look, ma! I hez duck-taiping! petADuck(caddie); petADuck(quacker); petADuck(runtimeDuck); // Reject non-duck objects petADuck(orker); // compile error: orker is not a duck! } Not only D supports duck-typing, the compiler even checks type-safety for you at compile-time. ;-) Incidentally, this is what the Phobos range interface does. T -- My program has no bugs! Only undocumented features...
Apr 28 2012
parent "Nick Sabalausky" <SeeWebsiteToContactMe semitwist.com> writes:
"H. S. Teoh" <hsteoh quickfur.ath.cx> wrote in message 
news:mailman.67.1335651468.24740.digitalmars-d puremagic.com...
 On Sat, Apr 28, 2012 at 11:12:38PM +0200, SomeDude wrote:
 On Saturday, 28 April 2012 at 20:59:48 UTC, q66 wrote:
This kind of attitude "we need big fat bullshit like Java and
heavy use of OO and idioms and EH and all that other crap" is
broken and false. And you have no way to prove that Python for
example wouldn't scale for large projects; its main fault is that
the default implementation is rather slow, but it's not pretty
much missing anything required for a large project.
Python has two big drawbacks for large projects: - it's too slow - it's a dynamically-typed language The fact that it's flexible is because it uses duck typing, and AFAIK you can't do duck typing in a statically typed language. So it's cool for small programs, but it can't handle large ones because it's not statically typed. And this opinion doesn't come just out of thin air, I speak from my own professional experience.
Who says D doesn't have duck-typing?
Yea, templated code is structurally-typed (duck-typed) by default. Not a big fan of that personally, but I can live with it, and D is awesome enough that you can build nominal-typing out of it: http://www.semitwist.com/articles/EfficientAndFlexible/MultiplePages/Page5/
Apr 28 2012
prev sibling next sibling parent "Jonas Drewsen" <jdrewsen nospam.com> writes:
On Saturday, 28 April 2012 at 21:12:39 UTC, SomeDude wrote:
 On Saturday, 28 April 2012 at 20:59:48 UTC, q66 wrote:
 This kind of attitude "we need big fat bullshit like Java and 
 heavy use of OO and idioms and EH and all that other crap" is 
 broken and false. And you have no way to prove that Python for 
 example wouldn't scale for large projects; its main fault is 
 that the default implementation is rather slow, but it's not 
 pretty much missing anything required for a large project.
Python has two big drawbacks for large projects: - it's too slow - it's a dynamically-typed language The fact that it's flexible is because it uses duck typing, and AFAIK you can't do duck typing in a statically typed language. So it's cool for small programs, but it can't handle large ones because it's not statically typed. And this opinion doesn't come just out of thin air, I speak from my own professional experience.
Go is a static duck typed language (when using interfaces anyway) AFAIK. http://golang.org/doc/go_faq.html#implements_interface http://research.swtch.com/interfaces /Jonas
Apr 29 2012
prev sibling parent reply "David Nadlinger" <see klickverbot.at> writes:
On Saturday, 28 April 2012 at 21:12:39 UTC, SomeDude wrote:
 […] And this opinion doesn't come just out of thin air, I 
 speak from my own professional experience.
Regardless of the fact that I tend to agree with you on this one, isn't »my own professional experience« usually a synonym for »thin air«? ;) David
Apr 29 2012
parent "SomeDude" <lovelydear mailmetrash.com> writes:
On Sunday, 29 April 2012 at 09:52:21 UTC, David Nadlinger wrote:
 On Saturday, 28 April 2012 at 21:12:39 UTC, SomeDude wrote:
 […] And this opinion doesn't come just out of thin air, I 
 speak from my own professional experience.
Regardless of the fact that I tend to agree with you on this one, isn't »my own professional experience« usually a synonym for »thin air«? ;) David
Well yes and no. It's the difference between "I think that", and "I've experienced in real projects that". And well, discussing in another forum, I've had other similar echos and experiences. Basically, with Python and other dynamically typed languages, the time you gain writing code, you lose testing it and correcting bugs that a compiler would have found for you.
Apr 29 2012
prev sibling next sibling parent "SomeDude" <lovelydear mailmetrash.com> writes:
On Saturday, 28 April 2012 at 20:59:48 UTC, q66 wrote:
 On Saturday, 28 April 2012 at 20:35:40 UTC, SomeDude wrote:

 This kind of attitude "we need big fat bullshit like Java and 
 heavy use of OO and idioms and EH and all that other crap" is 
 broken and false. And you have no way to prove that Python for 
 example wouldn't scale for large projects; its main fault is 
 that the default implementation is rather slow, but it's not 
 pretty much missing anything required for a large project.
BTW, look at Scala for another language that's designed for large scale programming (as its name implies). Scala is a very good design, some even think it's the Java killer. But I think it's even more complex than D.
Apr 28 2012
prev sibling parent reply Paulo Pinto <pjmlp progtools.org> writes:
Am 28.04.2012 22:59, schrieb q66:
 On Saturday, 28 April 2012 at 20:35:40 UTC, SomeDude wrote:
 On Saturday, 28 April 2012 at 20:09:50 UTC, q66 wrote:
 On Saturday, 28 April 2012 at 20:05:30 UTC, SomeDude wrote:

 There are minimalistic languages that don't add too much complexity,
 instead it results in code being kept simple.
I appreciate minimalistic languages. I love the simplicity of Scheme and the design of Lua. Lua and Python are extensible language, but truth be told, they cannot handle large scale programming. In fact, I don't know of any minimalistic language that can scale from hundreds of thousands to millions of lines of code. When you reach these sizes, their simple design becomes a drawback. You start missing lots of features. When you reach large scale programming, you want really powerful tools. That's basically what the Java designers discovered after experience. The original language was simple and easy, but that simplicity translated into way too much boilerplate code. So they kept adding features from version to version, generics, then annotations, a means to create new keywords. And now they would like to add delegates. These are all needed in large programs.
 D needs to do something it does really well and concentrate on that.
 Otherwise the language will remain being rather vague and doing "a
 bit of everything, but nothing truly well".
It does a lot of things well already. Our point of comparison should languages that are designed to develop large systems. But most of all it needs to stabilize and polish, not change all the time. I think its feature set is very good already. We are far from having explored all its possibilities.
 Instead of adding more and more features into a rigid language, it
 needs to be made more flexible and extensible, both syntactically and
 semantically.
This kind of attitude "we need big fat bullshit like Java and heavy use of OO and idioms and EH and all that other crap" is broken and false. And you have no way to prove that Python for example wouldn't scale for large projects; its main fault is that the default implementation is rather slow, but it's not pretty much missing anything required for a large project.
Python is my favorite scripting language, but I would never propose a dynamic language for programming on the large. My employer does consulting for big projects. The type of entreprise projects that require multi-site development scattered across the globe, sometimes with 300+ developers. There is no way a dynamic language would work in such scenarios, without having a constant broken build on the CI system. -- Paulo
Apr 28 2012
next sibling parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Sun, Apr 29, 2012 at 08:40:16AM +0200, Paulo Pinto wrote:
[...]
 My employer does consulting for big projects. The type of entreprise
 projects that require multi-site development scattered across the
 globe, sometimes with 300+ developers.
 
 There is no way a dynamic language would work in such scenarios,
 without having a constant broken build on the CI system.
[...] Yeah, at my work we have about 20-30 people working on a very large C/C++ codebase (one among many), and we already get broken builds every now and then, like bugs that completely break just about every feature in the system -- makes you wonder how any sane programmer could've checked in such a mess (and how said mess made it through the kangaroo code review process). Or blatant internal API breakages that make you wonder if anybody even *read* what they wrote. I cannot begin to imagine the horror of using a dynamic language in this setting. Static languages are already painful enough; throw in indeterminate typing at compile-time and it's a recipe for utter disaster, probably every single work day. And this is only 20-30 developers. The problem gets exponentially worse when that number goes up. At 300+ developers, the project would grind to a complete halt in less than a day (probably less than an hour). T -- Study gravitation, it's a field with a lot of potential.
Apr 29 2012
parent Paulo Pinto <pjmlp progtools.org> writes:
Am 29.04.2012 17:27, schrieb H. S. Teoh:
 On Sun, Apr 29, 2012 at 08:40:16AM +0200, Paulo Pinto wrote:
 [...]
At 300+ developers, the project would grind to a complete halt in
 less than a day (probably less than an hour).
Suffice to say, that on that specific project we had weeks without any working build, that had to be saved with hard code free rules until it got green again. This type of projects is what made me change my mind about static vs dynamic. Static languages with automatic type inference, and some type of dynamic dispatch like D's variant type/opDispatch, fullfil most use cases a dynamic language is good for, without sacrificing tooling or large scale development. -- Paulo
Apr 29 2012
prev sibling parent =?UTF-8?B?QWxleCBSw7hubmUgUGV0ZXJzZW4=?= <xtzgzorex gmail.com> writes:
On 29-04-2012 08:40, Paulo Pinto wrote:
 Am 28.04.2012 22:59, schrieb q66:
 On Saturday, 28 April 2012 at 20:35:40 UTC, SomeDude wrote:
 On Saturday, 28 April 2012 at 20:09:50 UTC, q66 wrote:
 On Saturday, 28 April 2012 at 20:05:30 UTC, SomeDude wrote:

 There are minimalistic languages that don't add too much complexity,
 instead it results in code being kept simple.
I appreciate minimalistic languages. I love the simplicity of Scheme and the design of Lua. Lua and Python are extensible language, but truth be told, they cannot handle large scale programming. In fact, I don't know of any minimalistic language that can scale from hundreds of thousands to millions of lines of code. When you reach these sizes, their simple design becomes a drawback. You start missing lots of features. When you reach large scale programming, you want really powerful tools. That's basically what the Java designers discovered after experience. The original language was simple and easy, but that simplicity translated into way too much boilerplate code. So they kept adding features from version to version, generics, then annotations, a means to create new keywords. And now they would like to add delegates. These are all needed in large programs.
 D needs to do something it does really well and concentrate on that.
 Otherwise the language will remain being rather vague and doing "a
 bit of everything, but nothing truly well".
It does a lot of things well already. Our point of comparison should languages that are designed to develop large systems. But most of all it needs to stabilize and polish, not change all the time. I think its feature set is very good already. We are far from having explored all its possibilities.
 Instead of adding more and more features into a rigid language, it
 needs to be made more flexible and extensible, both syntactically and
 semantically.
This kind of attitude "we need big fat bullshit like Java and heavy use of OO and idioms and EH and all that other crap" is broken and false. And you have no way to prove that Python for example wouldn't scale for large projects; its main fault is that the default implementation is rather slow, but it's not pretty much missing anything required for a large project.
Python is my favorite scripting language, but I would never propose a dynamic language for programming on the large. My employer does consulting for big projects. The type of entreprise projects that require multi-site development scattered across the globe, sometimes with 300+ developers. There is no way a dynamic language would work in such scenarios, without having a constant broken build on the CI system. -- Paulo
Wait, dynamic-language programmers use CI? *ducks and runs* -- - Alex
Apr 29 2012
prev sibling next sibling parent reply Dmitry Olshansky <dmitry.olsh gmail.com> writes:
On 28.04.2012 22:47, Walter Bright wrote:
 Andrei and I had a fun discussion last night about this question. The
 idea was which features in D are redundant and/or do not add significant
 value?

 A couple already agreed upon ones are typedef and the cfloat, cdouble
 and creal types.

 What's your list?
1. Drop is(...) feature entirely. Extend __traits where needed and move compile-time reflection to "magic" meta namespace completely. 2. "enum as manifest constant". Use static or immutable/global. Compiler should be smart enough to avoid putting immutable integers/doubles into object file as variables. 3. with statement (?). I kind of like it but bleh it's too boggy and it doesn't seem to pull its weight. (pointers? class references? a lot of stuff to go wrong) Fluent interfaces solve a good portion of its benefits to be specific. 4. foreach_reverse. Seriously let's kill this abomination. If it happens that foreach(x; retro(range)){...} is slower it just means compiler (inlining?) is no good and should be improved. 5. .tupleof looks like a hack. But I'd rather "refactor" than drop it. 6. Drop out arguments? There are tuples. And auto (a, b) = getMeTwoThings(); is cleanerthan <something> a, b; fillTheseTwoThings(a, b); // no indication whatsoever that a & b are modified heck even fn(&a, &b) in C is *better* (ok no tuple unpacking for now but you got the idea) 7. I can live without homogenous varaidics. Since most of the time they readily progress to full-blown variadics that detect common type & forward things to an array version of function. Also given that sometimes people do things like: this(int[] arr...)// ctor with cool syntax, yada-yada ;) { this.data = arr; //boom! (pointer to stack-allocated stuff) } 8. Something else. D is huge :) -- Dmitry Olshansky
Apr 28 2012
next sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 04/28/2012 09:22 PM, Dmitry Olshansky wrote:
 On 28.04.2012 22:47, Walter Bright wrote:
 Andrei and I had a fun discussion last night about this question. The
 idea was which features in D are redundant and/or do not add significant
 value?

 A couple already agreed upon ones are typedef and the cfloat, cdouble
 and creal types.

 What's your list?
1. Drop is(...) feature entirely. Extend __traits where needed and move compile-time reflection to "magic" meta namespace completely. 2. "enum as manifest constant". Use static or immutable/global.
static is not accessible at compile time, would you want to change that? immutable is not an option because it infects the type. Furthermore, I like 'enum' because it is concise. What is the issue with enum?
 Compiler should be smart enough
Smart compiler fallacy. It really cannot be that smart in this case.
 to avoid putting immutable integers/doubles into
 object file as variables.
Their address might be taken by code that is unavailable! Furthermore, many of my enums are strings or arrays.
 8. Something else. D is huge :)
I actually think D is not too large.
Apr 28 2012
parent reply Dmitry Olshansky <dmitry.olsh gmail.com> writes:
On 29.04.2012 0:57, Timon Gehr wrote:
 On 04/28/2012 09:22 PM, Dmitry Olshansky wrote:
 On 28.04.2012 22:47, Walter Bright wrote:
 Andrei and I had a fun discussion last night about this question. The
 idea was which features in D are redundant and/or do not add significant
 value?

 A couple already agreed upon ones are typedef and the cfloat, cdouble
 and creal types.

 What's your list?
1. Drop is(...) feature entirely. Extend __traits where needed and move compile-time reflection to "magic" meta namespace completely. 2. "enum as manifest constant". Use static or immutable/global.
static is not accessible at compile time, would you want to change that? immutable is not an option because it infects the type.
Oops, scratch that comment about static/immutable. But how about: alias thing = runSomeCtfe(); And bring the usual alias to new_name = <something>; form (even C++ finally got this right with C++11 aliases).
 Furthermore, I like 'enum' because it is concise.

 What is the issue with enum?

 Compiler should be smart enough
Smart compiler fallacy. It really cannot be that smart in this case.
 to avoid putting immutable integers/doubles into
 object file as variables.
Their address might be taken by code that is unavailable! Furthermore, many of my enums are strings or arrays.
 8. Something else. D is huge :)
I actually think D is not too large.
For what it does - surely not. But in general it's big. For one it's not smaller then C++. 8. synchronized. scope(exit) mutex.unlock(); is fine in cases where RAII is awkward. -- Dmitry Olshansky
Apr 28 2012
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 04/28/2012 11:04 PM, Dmitry Olshansky wrote:
 On 29.04.2012 0:57, Timon Gehr wrote:
 On 04/28/2012 09:22 PM, Dmitry Olshansky wrote:
 On 28.04.2012 22:47, Walter Bright wrote:
 Andrei and I had a fun discussion last night about this question. The
 idea was which features in D are redundant and/or do not add
 significant
 value?

 A couple already agreed upon ones are typedef and the cfloat, cdouble
 and creal types.

 What's your list?
1. Drop is(...) feature entirely. Extend __traits where needed and move compile-time reflection to "magic" meta namespace completely. 2. "enum as manifest constant". Use static or immutable/global.
static is not accessible at compile time, would you want to change that? immutable is not an option because it infects the type.
Oops, scratch that comment about static/immutable. But how about: alias thing = runSomeCtfe();
That would work in certain cases, where the initializer is not a single symbol. But then, I kinda like the way 'enum' is generalized in D: enum Foo{ member1, member2, member3, } => (allow non-integral enumerations) enum Foo{ member1 = "1", member2 = "2", member3 = "3", } => (anonymous enums) enum{ member1 = "1", member2 = "2", member3 = "3", } => (a single member is okay) enum{ member1 = "1", } => (syntactic sugar) enum member1 = "1";
 And bring the usual alias to new_name = <something>;
 form (even C++ finally got this right with C++11 aliases).
This is probably something that should be done.
 I actually think D is not too large.
For what it does - surely not. But in general it's big. For one it's not smaller then C++.
I am not sure how to compare, but D 'feels' smaller than C++ to me. Implementing a compiler is probably harder for D, because of the interplay of forward references, CTFE and compile time introspection.
Apr 28 2012
parent reply "Nick Sabalausky" <SeeWebsiteToContactMe semitwist.com> writes:
"Timon Gehr" <timon.gehr gmx.ch> wrote in message 
news:jnhpvv$ih4$1 digitalmars.com...
 On 04/28/2012 11:04 PM, Dmitry Olshansky wrote:
 But how about:
 alias thing = runSomeCtfe();
That would work in certain cases, where the initializer is not a single symbol. But then, I kinda like the way 'enum' is generalized in D: enum Foo{ member1, member2, member3, } => (allow non-integral enumerations) enum Foo{ member1 = "1", member2 = "2", member3 = "3", }
Those are good. They are essentially enumerations.
 => (anonymous enums)

 enum{
     member1 = "1",
     member2 = "2",
     member3 = "3",
 }
I don't think "anonymous enum" makes any sense at all. It's *not* an enumeration by any stretch of the term, it's just a series of manifest constants. The fact that they're grouped doesn't even have any semantic consequence, as far as I'm aware.
 => (a single member is okay)

 enum{
     member1 = "1",
 }

 => (syntactic sugar)

 enum member1 = "1";
Just simpler examples of the above, which isn't any form of enumeration at all.
 And bring the usual alias to new_name = <something>;
 form (even C++ finally got this right with C++11 aliases).
This is probably something that should be done.
Emphatic +1 I always have to stop and think carefully about the order when I write an alias.
 Implementing a compiler is probably harder for D, because of the interplay 
 of forward references, CTFE and compile time introspection.
Those make D more difficult to implement than many languages, but OTOH, AIUI, C++ has some real nightmarish details with templates and even just simply parsing. Probably some other bizarre cruft, too. IIRC, I think Walter's occasionally mentioned something about the...overload rules?
Apr 28 2012
next sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 04/29/2012 08:35 AM, Nick Sabalausky wrote:
 "Timon Gehr"<timon.gehr gmx.ch>  wrote in message
 news:jnhpvv$ih4$1 digitalmars.com...
 On 04/28/2012 11:04 PM, Dmitry Olshansky wrote:
 But how about:
 alias thing = runSomeCtfe();
That would work in certain cases, where the initializer is not a single symbol. But then, I kinda like the way 'enum' is generalized in D: enum Foo{ member1, member2, member3, } => (allow non-integral enumerations) enum Foo{ member1 = "1", member2 = "2", member3 = "3", }
Those are good. They are essentially enumerations.
 =>  (anonymous enums)

 enum{
      member1 = "1",
      member2 = "2",
      member3 = "3",
 }
I don't think "anonymous enum" makes any sense at all. It's *not* an enumeration by any stretch of the term,
enum{ member1, member2, member3, } static assert(member1+1==member2 && member2+1==member3);
 it's just a series of manifest
 constants. The fact that they're grouped doesn't even have any semantic
 consequence, as far as I'm aware.
The only differences are that they don't occupy their own namespace and they don't define their own type. But non-anonymous enums are _just a bunch of manifest constants_ as well! Therefore there are ways in which the generalisation makes sense.
 =>  (a single member is okay)

 enum{
      member1 = "1",
 }

 =>  (syntactic sugar)

 enum member1 = "1";
Just simpler examples of the above, which isn't any form of enumeration at all.
'enum' declares manifest constants whether or not it is anonymous. Afaik go uses 'const' for enumerations and manifest constants. 'const' means a different thing in D. (arguably, 'readonly' would be a better fit) I don't think that the exact keywords matter a huge deal here.
Apr 29 2012
parent reply "Nick Sabalausky" <SeeWebsiteToContactMe semitwist.com> writes:
"Timon Gehr" <timon.gehr gmx.ch> wrote in message 
news:jnj92m$306m$1 digitalmars.com...
 On 04/29/2012 08:35 AM, Nick Sabalausky wrote:

 it's just a series of manifest
 constants. The fact that they're grouped doesn't even have any semantic
 consequence, as far as I'm aware.
The only differences are that they don't occupy their own namespace and they don't define their own type. But non-anonymous enums are _just a bunch of manifest constants_ as well!
No, they're not. Non-anon enums *contain* a bunch of manifest constants. But what non-anon enums *are* is a type. Anon enums are not a type at all. I think that's a significant difference. Note this is in stark contrast to: - Classes: Anonymous or not, it's still a type. - Functions: Anonymous or not, it's still *not* a type. The syntaxes we have for anon enums and non-anon enums makes them *look* like they're basically the same thing, just with/without a name, but that's not actually the case. Of course, my biggest issue by far is with the name "enum". Non-anon enums can reasonably be thought of as enumerations (except for bitfields, but I think those should be handled differently from enums anyway). But anon-enums are just plain not enumerations, period. If we weren't calling them all "enum", then I would have much, much less problem with the syntax we have. And yea, I get the whole "What's in a name?", but "enum" is just a colossally *terrible* name for this. It's worse than when "immutable" was called "invariant".
Apr 29 2012
parent =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 04/29/2012 12:12 PM, Nick Sabalausky wrote:
 "Timon Gehr"<timon.gehr gmx.ch>  wrote in message
 news:jnj92m$306m$1 digitalmars.com...
 On 04/29/2012 08:35 AM, Nick Sabalausky wrote:

 it's just a series of manifest
 constants. The fact that they're grouped doesn't even have any semantic
 consequence, as far as I'm aware.
The only differences are that they don't occupy their own namespace and they don't define their own type. But non-anonymous enums are _just a bunch of manifest constants_ as well!
No, they're not. Non-anon enums *contain* a bunch of manifest
constants. But
 what non-anon enums *are* is a type. Anon enums are not a type at all. I
 think that's a significant difference.
I see that way as well. I have a section titled "enum values that are not of an enum type" at http://ddili.org/ders/d.en/enum.html: [quote] sometimes it may not be natural to come up with enum type names just to use named constants. Let's assume that a named constant is needed to represent the number of seconds per day. It should not be necessary to also define an enum type for this constant value. All that is needed is a constant value that can be referred to by its name. In such cases, the type of the enum and the value parentheses are not specified: enum secondsPerDay = 60 * 60 * 24; [/quote]
 Of course, my biggest issue by far is with the name "enum".
Agreed. It became a bad name as soon as any value other than a number could be an enum value (or "member").
 Non-anon enums
 can reasonably be thought of as enumerations (except for bitfields, but I
 think those should be handled differently from enums anyway). But 
anon-enums
 are just plain not enumerations, period. If we weren't calling them all
 "enum", then I would have much, much less problem with the syntax we 
have.
 And yea, I get the whole "What's in a name?", but "enum" is just a
 colossally *terrible* name for this. It's worse than when "immutable" was
 called "invariant".
Ali
Apr 30 2012
prev sibling parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Sun, Apr 29, 2012 at 02:35:07AM -0400, Nick Sabalausky wrote:
 "Timon Gehr" <timon.gehr gmx.ch> wrote in message 
 news:jnhpvv$ih4$1 digitalmars.com...
[...]
 Implementing a compiler is probably harder for D, because of the
 interplay of forward references, CTFE and compile time
 introspection.
Those make D more difficult to implement than many languages, but OTOH, AIUI, C++ has some real nightmarish details with templates and even just simply parsing. Probably some other bizarre cruft, too. IIRC, I think Walter's occasionally mentioned something about the...overload rules?
[...] It has been said that C++ cannot be lexed before it's parsed. Before C++11, for example, this is invalid: std::vector<std::vector<T>> nestedList; Instead, you have to write: std::vector<std::vector<T> > nestedList; Fortunately they fixed this in C++11. But now you have another problem: std::vector<myTemplate<T>>1> nestedList; Whether or not this is valid depends on whether T is a type name or a variable name (e.g., if myTemplate takes an int parameter). But how is the lexer even supposed to know whether the >> should be a right shift operator or two right angle brackets? It has to understand the _semantics_ of T before it can even lex the thing. I read somewhere that one of D's goals was to be able to lex the language without requiring semantic knowledge in the lexer. You have no idea how much such a seemingly-obvious concept can save hours, days, nay, months and years of frustration in compiler implementation. So you think D is hard to implement? We have barely even begun to delve into the insane convolutions of C++. You'll start to have some real hair-tearing sessions once you start getting into implicit conversion rules and template best-match algorithms. Be glad, be very glad that we have D instead of C++! T -- Designer clothes: how to cover less by paying more.
Apr 29 2012
next sibling parent "David Nadlinger" <see klickverbot.at> writes:
On Sunday, 29 April 2012 at 15:16:57 UTC, H. S. Teoh wrote:
 […] and template best-match algorithms. Be glad, be very glad 
 that we have D instead of C++!
To be fair, the template matching logic in D is quite complicated as well (at least I can recall several instances of stumbling over bugs in the implementation, would have to search Bugzilla for details) – the only thing is that we don't really have a formal spec for it yet… David
Apr 29 2012
prev sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 04/29/2012 05:17 PM, H. S. Teoh wrote:
 On Sun, Apr 29, 2012 at 02:35:07AM -0400, Nick Sabalausky wrote:
 "Timon Gehr"<timon.gehr gmx.ch>  wrote in message
 news:jnhpvv$ih4$1 digitalmars.com...
[...]
 Implementing a compiler is probably harder for D, because of the
 interplay of forward references, CTFE and compile time
 introspection.
Those make D more difficult to implement than many languages, but OTOH, AIUI, C++ has some real nightmarish details with templates and even just simply parsing. Probably some other bizarre cruft, too. IIRC, I think Walter's occasionally mentioned something about the...overload rules?
[...]
C++ implementation complexity is incidental.
 It has been said that C++ cannot be lexed before it's parsed.  Before
 C++11, for example, this is invalid:

 	std::vector<std::vector<T>>  nestedList;

 Instead, you have to write:

 	std::vector<std::vector<T>  >  nestedList;

 Fortunately they fixed this in C++11. But now you have another problem:

 	std::vector<myTemplate<T>>1>  nestedList;

 Whether or not this is valid depends on whether T is a type name or a
 variable name
I think it is never valid.
 (e.g., if myTemplate takes an int parameter). But how is
 the lexer even supposed to know whether the>>  should be a right shift
 operator or two right angle brackets? It has to understand the
 _semantics_ of T before it can even lex the thing.
A D compiler has to semantically analyse the code without full information about which symbols are declared, (getting the full set of declared symbols is actually an ill-defined problem because conditional compilation is Turing complete and can already depend on any declared symbol or even on the fact that a certain symbol has _not_ been declared). There might also be ambiguities or contradictions in the code that a compiler should detect. There is no mention of this issue or its (necessarily conservative and somewhat arbitrary) solution in the language documentation. DMD does not solve the problem, but just fails in funny ways when faced with a non-trivial instance of it. C++ does not have such issues at all because it disallows forward references! Don't get me wrong, I think this is rather awesome. But I predict it will be somewhat of a roadblock for getting the language into a stable state.
 I read somewhere that one of D's goals was to be able to lex the
 language without requiring semantic knowledge in the lexer.
This is required in order to have forward references.
 You have no idea
I do.
 how much such a seemingly-obvious concept can save hours, days,
 nay, months and years of frustration in compiler implementation.

 So you think D is hard to implement? We have barely even begun to delve
 into the insane convolutions of C++. You'll start to have some real
 hair-tearing sessions once you start getting into implicit conversion
 rules
Well, again, DMD does not get those right. And there is some black magic in that area, because the implicitly-converts-to-relation is from expressions to types instead of from types to types. (which is awesome of course, but it is complex to get right). Try this (this *should* compile). pragma(msg, typeof(1?[[]]:[[1]])); pragma(msg, typeof(1?1?[[]]:[[]]:[[1]])); pragma(msg, typeof([[[]],[[]],[[1]]])); class C{} static C[] c = [null]; pragma(msg, typeof([[null],[new C]]));
 and template best-match algorithms. Be glad, be very glad that we
 have D instead of C++!
static if(!is(typeof(foo))) enum bar = 1; static if(!is(typeof(bar))) enum foo = 1; In D, most of the complexity stems from its advanced features, while in C++ a lot of the complexity is merely incidental.
Apr 29 2012
prev sibling next sibling parent "jerro" <a a.com> writes:
 2. "enum as manifest constant". Use static or immutable/global. 
 Compiler should be smart enough to avoid putting immutable 
 integers/doubles into object file as variables.
But enums aren't only used for optimization. What if you want to use a constant at compile time, as a template parameter?
Apr 28 2012
prev sibling parent reply Robert Clipsham <robert octarineparrot.com> writes:
On 28/04/2012 20:22, Dmitry Olshansky wrote:
 3. with statement (?). I kind of like it but bleh it's too boggy and it
 doesn't seem to pull its weight. (pointers? class references? a lot of
 stuff to go wrong) Fluent interfaces solve a good portion of its
 benefits to be specific.
My primary use case for the with() statement is with final switch: final switch(something) with(MyEnumWithAPrettyLongName) { case A: // Save repeating myself everywhere break; . . . } -- Robert http://octarineparrot.com/
Apr 29 2012
next sibling parent =?ISO-8859-1?Q?Alex_R=F8nne_Petersen?= <xtzgzorex gmail.com> writes:
On 30-04-2012 02:40, Robert Clipsham wrote:
 On 28/04/2012 20:22, Dmitry Olshansky wrote:
 3. with statement (?). I kind of like it but bleh it's too boggy and it
 doesn't seem to pull its weight. (pointers? class references? a lot of
 stuff to go wrong) Fluent interfaces solve a good portion of its
 benefits to be specific.
My primary use case for the with() statement is with final switch: final switch(something) with(MyEnumWithAPrettyLongName) { case A: // Save repeating myself everywhere break; . . . }
Hah, clever! Never would've thought of that. -- - Alex
Apr 29 2012
prev sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2012-04-30 02:40, Robert Clipsham wrote:
 On 28/04/2012 20:22, Dmitry Olshansky wrote:
 3. with statement (?). I kind of like it but bleh it's too boggy and it
 doesn't seem to pull its weight. (pointers? class references? a lot of
 stuff to go wrong) Fluent interfaces solve a good portion of its
 benefits to be specific.
My primary use case for the with() statement is with final switch: final switch(something) with(MyEnumWithAPrettyLongName) { case A: // Save repeating myself everywhere break; . . . }
That's the only thing I used the with-statement for. -- /Jacob Carlborg
Apr 30 2012
next sibling parent reply simendsjo <simendsjo gmail.com> writes:
On Mon, 30 Apr 2012 09:39:15 +0200, Jacob Carlborg <doob me.com> wrote:

 On 2012-04-30 02:40, Robert Clipsham wrote:
 On 28/04/2012 20:22, Dmitry Olshansky wrote:
 3. with statement (?). I kind of like it but bleh it's too boggy and it
 doesn't seem to pull its weight. (pointers? class references? a lot of
 stuff to go wrong) Fluent interfaces solve a good portion of its
 benefits to be specific.
My primary use case for the with() statement is with final switch: final switch(something) with(MyEnumWithAPrettyLongName) { case A: // Save repeating myself everywhere break; . . . }
That's the only thing I used the with-statement for.
http://msdn.microsoft.com/en-us/library/bb384062.aspx
Apr 30 2012
parent reply "John Chapman" <johnch_atms hotmail.com> writes:
On Monday, 30 April 2012 at 07:49:48 UTC, simendsjo wrote:

 http://msdn.microsoft.com/en-us/library/bb384062.aspx

Ooh, nice - care to share?
Apr 30 2012
parent simendsjo <simendsjo gmail.com> writes:
On Mon, 30 Apr 2012 11:31:49 +0200, John Chapman <johnch_atms hotmail.com>  
wrote:

 On Monday, 30 April 2012 at 07:49:48 UTC, simendsjo wrote:

 http://msdn.microsoft.com/en-us/library/bb384062.aspx

Ooh, nice - care to share?
Basically just auto c = new C; with(c) { field = value; }
Apr 30 2012
prev sibling parent reply Manu <turkeyman gmail.com> writes:
On 30 April 2012 10:39, Jacob Carlborg <doob me.com> wrote:

 On 2012-04-30 02:40, Robert Clipsham wrote:

 On 28/04/2012 20:22, Dmitry Olshansky wrote:

 3. with statement (?). I kind of like it but bleh it's too boggy and it
 doesn't seem to pull its weight. (pointers? class references? a lot of
 stuff to go wrong) Fluent interfaces solve a good portion of its
 benefits to be specific.
My primary use case for the with() statement is with final switch: final switch(something) with(**MyEnumWithAPrettyLongName) { case A: // Save repeating myself everywhere break; . . . }
That's the only thing I used the with-statement for.
That's the only thing I was aware it did ;) .. are there other uses?
Apr 30 2012
parent Jacob Carlborg <doob me.com> writes:
On 2012-04-30 12:29, Manu wrote:
 On 30 April 2012 10:39, Jacob Carlborg <doob me.com
     That's the only thing I used the with-statement for.


 That's the only thing I was aware it did ;) .. are there other uses?
You can use it to access members without a receiver as well: class Foo { int x; int y; } auto foo = new Foo; with (foo) { x = 3; y = 4; } http://dlang.org/statement.html#WithStatement -- /Jacob Carlborg
Apr 30 2012
prev sibling next sibling parent reply "q66" <quaker66 gmail.com> writes:
On Saturday, 28 April 2012 at 18:48:18 UTC, Walter Bright wrote:
 Andrei and I had a fun discussion last night about this 
 question. The idea was which features in D are redundant and/or 
 do not add significant value?

 A couple already agreed upon ones are typedef and the cfloat, 
 cdouble and creal types.

 What's your list?
- AAs integrated in the language; you barely ever use AA literals and having them purely in Phobos would help get rid of the runtime fat, as well as better implementations - Phobos is too fat - it needs to shrink to just a few core modules, others being distributed via some system like CPAN for Perl - Properties - they're kinda broken at this point and the value is questionable - trusted system - Exception handling - a lot of runtime, questionable value - Versions - not redundant, but needs a better system (with AND/OR, possibility of de-versioning, the assignment op to set versions is kinda bad) I think I would find some more, but these are the ones I can recall now.
Apr 28 2012
next sibling parent reply "Nick Sabalausky" <SeeWebsiteToContactMe semitwist.com> writes:
"q66" <quaker66 gmail.com> wrote in message 
news:ihqjguujvoukhlqcwkyi forum.dlang.org...
 - Phobos is too fat - it needs to shrink to just a few core modules, 
 others being distributed via some system like CPAN for Perl
 - Properties - they're kinda broken at this point and the value is 
 questionable
 -  trusted  system
 - Exception handling - a lot of runtime, questionable value
That's just craziness!
Apr 28 2012
next sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 04/28/2012 09:39 PM, Nick Sabalausky wrote:
 "q66"<quaker66 gmail.com>  wrote in message
 news:ihqjguujvoukhlqcwkyi forum.dlang.org...
 - Phobos is too fat - it needs to shrink to just a few core modules,
 others being distributed via some system like CPAN for Perl
 - Properties - they're kinda broken at this point and the value is
 questionable
 -  trusted  system
 - Exception handling - a lot of runtime, questionable value
That's just craziness!
+1.
Apr 28 2012
prev sibling parent reply Marco Leise <Marco.Leise gmx.de> writes:
Am Sat, 28 Apr 2012 15:39:49 -0400
schrieb "Nick Sabalausky" <SeeWebsiteToContactMe semitwist.com>:

 "q66" <quaker66 gmail.com> wrote in message 
 news:ihqjguujvoukhlqcwkyi forum.dlang.org...
 - Phobos is too fat - it needs to shrink to just a few core modules, 
 others being distributed via some system like CPAN for Perl
 - Properties - they're kinda broken at this point and the value is 
 questionable
 -  trusted  system
 - Exception handling - a lot of runtime, questionable value
That's just craziness!
Madness even! AAs are soon mostly in the library and that's a good trade-off; trusted system needs to be there as long as there is safe; exception handling - some people rely on it heavily. See it as the easy way to error out of a function that doesn't normally return anything and cascade up several calls, while being able to release resources in each. I don't know about Phobos. Some batteries included are nice and help the popularity. When it comes to bindings to third party products with many alternatives, like databases, I'd say one should cut it there definitly. I can agree on the rest. -- Marco
Apr 28 2012
next sibling parent "Nick Sabalausky" <SeeWebsiteToContactMe semitwist.com> writes:
"Marco Leise" <Marco.Leise gmx.de> wrote in message 
news:20120429075404.121a5a46 marco-leise...
 I don't know about Phobos. Some batteries included are nice and help the 
 popularity. When it comes to bindings to third party products with many 
 alternatives, like databases, I'd say one should cut it there definitly.
Yea, it's a tradeoff either way. Once we have a mature "D CPAN", there will be less reason to pack things into Phobos. But until that actually happens, a "batteries included"-style std lib is necessary. And of course, like you say, there are likely things that just aren't appropriate for the std lib either way.
Apr 28 2012
prev sibling parent reply "SomeDude" <lovelydear mailmetrash.com> writes:
On Sunday, 29 April 2012 at 05:54:10 UTC, Marco Leise wrote:
 Am Sat, 28 Apr 2012 15:39:49 -0400
 schrieb "Nick Sabalausky" <SeeWebsiteToContactMe semitwist.com>:

 "q66" <quaker66 gmail.com> wrote in message 
 news:ihqjguujvoukhlqcwkyi forum.dlang.org...
 - Phobos is too fat - it needs to shrink to just a few core 
 modules, others being distributed via some system like CPAN 
 for Perl
 - Properties - they're kinda broken at this point and the 
 value is questionable
 -  trusted  system
 - Exception handling - a lot of runtime, questionable value
That's just craziness!
Madness even! AAs are soon mostly in the library and that's a good trade-off; trusted system needs to be there as long as there is safe; exception handling - some people rely on it heavily. See it as the easy way to error out of a function that doesn't normally return anything and cascade up several calls, while being able to release resources in each. I don't know about Phobos. Some batteries included are nice and help the popularity. When it comes to bindings to third party products with many alternatives, like databases, I'd say one should cut it there definitly. I can agree on the rest.
I don't want AA to be removed from the core language. That would be a big step backward in my opinion. Core language AAs are entirely adequate for a lot of applications, and they make for so much cleaner and easier to read/write code than template notation.
Apr 29 2012
parent reply "Nick Sabalausky" <SeeWebsiteToContactMe semitwist.com> writes:
"SomeDude" <lovelydear mailmetrash.com> wrote in message 
news:jrdmqmchgbibqmrwzwsk forum.dlang.org...
 On Sunday, 29 April 2012 at 05:54:10 UTC, Marco Leise wrote:
 Am Sat, 28 Apr 2012 15:39:49 -0400

 Madness even! AAs are soon mostly in the library and that's a good 
 trade-off;  trusted  system needs to be there as long as there is  safe; 
 exception handling - some people rely on it heavily. See it as the easy 
 way to error out of a function that doesn't normally return anything and 
 cascade up several calls, while being able to release resources in each.
 I don't know about Phobos. Some batteries included are nice and help the 
 popularity. When it comes to bindings to third party products with many 
 alternatives, like databases, I'd say one should cut it there definitly.
 I can agree on the rest.
I don't want AA to be removed from the core language. That would be a big step backward in my opinion. Core language AAs are entirely adequate for a lot of applications, and they make for so much cleaner and easier to read/write code than template notation.
There will still be sugar in the compiler so they appear to be builtins. When the switch happens, I'm sure it'll be transparent - average users probably won't even notice. It's just that "behind the scenes" their implementation will move from DMD to Druntime.
Apr 29 2012
next sibling parent "Nick Sabalausky" <SeeWebsiteToContactMe semitwist.com> writes:
"Nick Sabalausky" <SeeWebsiteToContactMe semitwist.com> wrote in message 
news:jnit81$29uh$1 digitalmars.com...
 "SomeDude" <lovelydear mailmetrash.com> wrote in message 
 news:jrdmqmchgbibqmrwzwsk forum.dlang.org...
 On Sunday, 29 April 2012 at 05:54:10 UTC, Marco Leise wrote:
 Am Sat, 28 Apr 2012 15:39:49 -0400

 Madness even! AAs are soon mostly in the library and that's a good 
 trade-off;  trusted  system needs to be there as long as there is  safe; 
 exception handling - some people rely on it heavily. See it as the easy 
 way to error out of a function that doesn't normally return anything and 
 cascade up several calls, while being able to release resources in each.
 I don't know about Phobos. Some batteries included are nice and help the 
 popularity. When it comes to bindings to third party products with many 
 alternatives, like databases, I'd say one should cut it there definitly.
 I can agree on the rest.
I don't want AA to be removed from the core language. That would be a big step backward in my opinion. Core language AAs are entirely adequate for a lot of applications, and they make for so much cleaner and easier to read/write code than template notation.
There will still be sugar in the compiler so they appear to be builtins. When the switch happens, I'm sure it'll be transparent - average users probably won't even notice. It's just that "behind the scenes" their implementation will move from DMD to Druntime.
In fact, don't regular arrays already work like this?
Apr 29 2012
prev sibling parent reply "SomeDude" <lovelydear mailmetrash.com> writes:
On Sunday, 29 April 2012 at 08:13:53 UTC, Nick Sabalausky wrote:
 There will still be sugar in the compiler so they appear to be 
 builtins.
 When the switch happens, I'm sure it'll be transparent - 
 average users
 probably won't even notice. It's just that "behind the scenes" 
 their
 implementation will move from DMD to Druntime.
Hmmm, sounds nice, but bolting the language with the standard library is very risky (and a rather bad idea imho). Unless there is a very lightweight minimalistic core for Phobos (something which I advocate), you bolt a heavyweight library to your language, and that's not good. I'd rather keep the integrated the AAs, which are fine for most applications, and have templated AAs in the library for heavier use. Even though it may seem redundant, it's just as redundant as having arrays in the core language and std.array. Noone would want to remove arrays from the core language, right ?
Apr 29 2012
next sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 04/29/2012 10:28 AM, SomeDude wrote:
 On Sunday, 29 April 2012 at 08:13:53 UTC, Nick Sabalausky wrote:
 There will still be sugar in the compiler so they appear to be builtins.
 When the switch happens, I'm sure it'll be transparent - average users
 probably won't even notice. It's just that "behind the scenes" their
 implementation will move from DMD to Druntime.
Hmmm, sounds nice, but bolting the language with the standard library is very risky (and a rather bad idea imho). Unless there is a very lightweight minimalistic core for Phobos (something which I advocate), you bolt a heavyweight library to your language, and that's not good.
druntime is the library it will be moved into, not Phobos.
Apr 29 2012
parent "SomeDude" <lovelydear mailmetrash.com> writes:
On Sunday, 29 April 2012 at 08:31:57 UTC, Timon Gehr wrote:
 druntime is the library it will be moved into, not Phobos.
Ah, that's ok, then.
Apr 29 2012
prev sibling parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Sun, Apr 29, 2012 at 10:28:47AM +0200, SomeDude wrote:
 On Sunday, 29 April 2012 at 08:13:53 UTC, Nick Sabalausky wrote:
There will still be sugar in the compiler so they appear to be
builtins.  When the switch happens, I'm sure it'll be transparent -
average users probably won't even notice. It's just that "behind the
scenes" their implementation will move from DMD to Druntime.
Hmmm, sounds nice, but bolting the language with the standard library is very risky (and a rather bad idea imho). Unless there is a very lightweight minimalistic core for Phobos (something which I advocate), you bolt a heavyweight library to your language, and that's not good.
[...] Please note that the AA implementation will be moving into druntime, NOT phobos. The compiler already depends on a bunch of stuff in druntime (the GC being a prime example, and the Object class being another). And every time you write 'typeid'? That's druntime code too. T -- It is widely believed that reinventing the wheel is a waste of time; but I disagree: without wheel reinventers, we would be still be stuck with wooden horse-cart wheels.
Apr 29 2012
prev sibling next sibling parent reply "SomeDude" <lovelydear mailmetrash.com> writes:
On Saturday, 28 April 2012 at 19:23:00 UTC, q66 wrote:
 - AAs integrated in the language; you barely ever use AA 
 literals and having them purely in Phobos would help get rid of 
 the runtime fat, as well as better implementations
 - Phobos is too fat - it needs to shrink to just a few core 
 modules, others being distributed via some system like CPAN for 
 Perl
 - Properties - they're kinda broken at this point and the value 
 is questionable
 -  trusted  system
 - Exception handling - a lot of runtime, questionable value
 - Versions - not redundant, but needs a better system (with 
 AND/OR, possibility of de-versioning, the assignment op to set 
 versions is kinda bad)

 I think I would find some more, but these are the ones I can 
 recall now.
I disagree with every single point here.
Apr 28 2012
parent reply "q66" <quaker66 gmail.com> writes:
On Saturday, 28 April 2012 at 19:57:08 UTC, SomeDude wrote:
 On Saturday, 28 April 2012 at 19:23:00 UTC, q66 wrote:
 - AAs integrated in the language; you barely ever use AA 
 literals and having them purely in Phobos would help get rid 
 of the runtime fat, as well as better implementations
 - Phobos is too fat - it needs to shrink to just a few core 
 modules, others being distributed via some system like CPAN 
 for Perl
 - Properties - they're kinda broken at this point and the 
 value is questionable
 -  trusted  system
 - Exception handling - a lot of runtime, questionable value
 - Versions - not redundant, but needs a better system (with 
 AND/OR, possibility of de-versioning, the assignment op to set 
 versions is kinda bad)

 I think I would find some more, but these are the ones I can 
 recall now.
I disagree with every single point here.
So you don't agree version() is horribly half assed without AND/OR (how do you generate the same code for two different versions without copying or creating a new version covering both cases then?) and that "version = FOO;" makes no sense?
Apr 28 2012
parent reply "SomeDude" <lovelydear mailmetrash.com> writes:
On Saturday, 28 April 2012 at 20:02:12 UTC, q66 wrote:
 On Saturday, 28 April 2012 at 19:57:08 UTC, SomeDude wrote:
 On Saturday, 28 April 2012 at 19:23:00 UTC, q66 wrote:
So you don't agree version() is horribly half assed without AND/OR (how do you generate the same code for two different versions without copying or creating a new version covering both cases then?) and that "version = FOO;" makes no sense?
Sorry, with that, I agree. Nick Sabalausky proposed to remove version entirely. But I agree there could be something like: version(LINUX|OSX){ ... } else { ... }
Apr 28 2012
next sibling parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Sat, Apr 28, 2012 at 10:08:29PM +0200, SomeDude wrote:
 On Saturday, 28 April 2012 at 20:02:12 UTC, q66 wrote:
On Saturday, 28 April 2012 at 19:57:08 UTC, SomeDude wrote:
On Saturday, 28 April 2012 at 19:23:00 UTC, q66 wrote:
So you don't agree version() is horribly half assed without AND/OR (how do you generate the same code for two different versions without copying or creating a new version covering both cases then?) and that "version = FOO;" makes no sense?
Sorry, with that, I agree. Nick Sabalausky proposed to remove version entirely. But I agree there could be something like: version(LINUX|OSX){ ... } else { ... }
But if you're gonna do that, might as well just fold the feature into static if. The point of having a separate version construct was to provide a very basic, simple, easy-to-implement and easy-to-use way of versioning stuff. I don't think it was ever intended to be a full-fledged versioning system. T -- What doesn't kill me makes me stranger.
Apr 28 2012
parent "SomeDude" <lovelydear mailmetrash.com> writes:
On Saturday, 28 April 2012 at 20:51:54 UTC, H. S. Teoh wrote:
 On Sat, Apr 28, 2012 at 10:08:29PM +0200, SomeDude wrote:
 On Saturday, 28 April 2012 at 20:02:12 UTC, q66 wrote:
On Saturday, 28 April 2012 at 19:57:08 UTC, SomeDude wrote:
On Saturday, 28 April 2012 at 19:23:00 UTC, q66 wrote:
So you don't agree version() is horribly half assed without AND/OR (how do you generate the same code for two different versions without copying or creating a new version covering both cases then?) and that "version = FOO;" makes no sense?
Sorry, with that, I agree. Nick Sabalausky proposed to remove version entirely. But I agree there could be something like: version(LINUX|OSX){ ... } else { ... }
But if you're gonna do that, might as well just fold the feature into static if. The point of having a separate version construct was to provide a very basic, simple, easy-to-implement and easy-to-use way of versioning stuff. I don't think it was ever intended to be a full-fledged versioning system. T
I really don't care how it's implemented or what its syntax is. What I do want is begin able with a single glimpse, to see the different versions of the code, without having the impression to plunge into a "static if hell" with 5 levels of indentation. Having a different keyword helps for this. Besides, a specific keyword makes parsing code easier.
Apr 28 2012
prev sibling parent reply "Nick Sabalausky" <SeeWebsiteToContactMe semitwist.com> writes:
"SomeDude" <lovelydear mailmetrash.com> wrote in message 
news:sxzgfzztxfvsstwrqdiu forum.dlang.org...
 On Saturday, 28 April 2012 at 20:02:12 UTC, q66 wrote:
 On Saturday, 28 April 2012 at 19:57:08 UTC, SomeDude wrote:
 On Saturday, 28 April 2012 at 19:23:00 UTC, q66 wrote:
So you don't agree version() is horribly half assed without AND/OR (how do you generate the same code for two different versions without copying or creating a new version covering both cases then?) and that "version = FOO;" makes no sense?
Sorry, with that, I agree. Nick Sabalausky proposed to remove version entirely. But I agree there could be something like: version(LINUX|OSX){ ... } else { ... }
FWIW, one of the big wins I see in migrating "version" to "static if" is switching from the clumbsy "defined/undefined" model to a model of "true/false, undefined is an error". The current "undefined is not an error" stuff is just so...ActionScript 2.
Apr 28 2012
parent "SomeDude" <lovelydear mailmetrash.com> writes:
On Sunday, 29 April 2012 at 06:10:40 UTC, Nick Sabalausky wrote:
 "SomeDude" <lovelydear mailmetrash.com> wrote in message
 news:sxzgfzztxfvsstwrqdiu forum.dlang.org...
 On Saturday, 28 April 2012 at 20:02:12 UTC, q66 wrote:
 On Saturday, 28 April 2012 at 19:57:08 UTC, SomeDude wrote:
 On Saturday, 28 April 2012 at 19:23:00 UTC, q66 wrote:
So you don't agree version() is horribly half assed without AND/OR (how do you generate the same code for two different versions without copying or creating a new version covering both cases then?) and that "version = FOO;" makes no sense?
Sorry, with that, I agree. Nick Sabalausky proposed to remove version entirely. But I agree there could be something like: version(LINUX|OSX){ ... } else { ... }
FWIW, one of the big wins I see in migrating "version" to "static if" is switching from the clumbsy "defined/undefined" model to a model of "true/false, undefined is an error". The current "undefined is not an error" stuff is just so...ActionScript 2.
I don't mind changing the semantics of "version", but replacing the KEYWORD "version" with "static if" will make for code that is harder to read for the eye, harder to parse for the tools, and overall uglier. So I want to keep the keyword, which is a very good addition in my opinion.
Apr 29 2012
prev sibling next sibling parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Sat, Apr 28, 2012 at 09:22:59PM +0200, q66 wrote:
[...]
 - AAs integrated in the language; you barely ever use AA literals and
 having them purely in Phobos would help get rid of the runtime fat, as
 well as better implementations
On the contrary, AA's are a major reason I started programming in D. In this day and age, it's simply inexcusable to *not* have some kind of hash type available by default.
 - Phobos is too fat - it needs to shrink to just a few core modules,
 others being distributed via some system like CPAN for Perl
Um... that's what a *library* is supposed to be: a large collection of useful stuff from which you can pick the few that you need right now.
 - Properties - they're kinda broken at this point and the value is
 questionable
What kind of properties are you referring to?
 -  trusted  system
These are necessary.
 - Exception handling - a lot of runtime, questionable value
I completely disagree. No exception handling means lots and lots and lots of boilerplate code for checking error codes, return values, which are too tedious to write, which translates to many people leaving them out and ending up with unreliable code that fail silently or crash outright when a function call they assumed would work stopped working. If you've worked in large multi-person projects, you'll see very quickly why you *need* exception handling. No modern language can do without exception handling. Maybe you have a beef with how it's currently done in D, but regardless, you *need* exception handling of some kind.
 - Versions - not redundant, but needs a better system (with AND/OR,
 possibility of de-versioning, the assignment op to set versions is
 kinda bad)
[...] I find versions sorta neat... and they're simple enough that they don't add to much bloat to the language. (Whereas if you added AND and OR to them, then they start duplicating the function of static if, and that's when they become redundant.) T -- Your inconsistency is the only consistent thing about you! -- KD
Apr 28 2012
next sibling parent reply "q66" <quaker66 gmail.com> writes:
On Saturday, 28 April 2012 at 20:50:30 UTC, H. S. Teoh wrote:
 On Sat, Apr 28, 2012 at 09:22:59PM +0200, q66 wrote:
 [...]
 - AAs integrated in the language; you barely ever use AA 
 literals and
 having them purely in Phobos would help get rid of the runtime 
 fat, as
 well as better implementations
On the contrary, AA's are a major reason I started programming in D. In this day and age, it's simply inexcusable to *not* have some kind of hash type available by default.
Besides AA literals, library can handle this JUST FINE.
 - Phobos is too fat - it needs to shrink to just a few core 
 modules,
 others being distributed via some system like CPAN for Perl
Um... that's what a *library* is supposed to be: a large collection of useful stuff from which you can pick the few that you need right now.
Too large collection becomes too hard to manage. Separating it and distributing in style "you pay for what you use" is IMO the right approach.
 - Properties - they're kinda broken at this point and the 
 value is
 questionable
What kind of properties are you referring to?
The property crap. It's broken. If anything, it needs something
 -  trusted  system
These are necessary.
They're far from necessary.
 - Exception handling - a lot of runtime, questionable value
I completely disagree. No exception handling means lots and lots and lots of boilerplate code for checking error codes, return values, which are too tedious to write, which translates to many people leaving them out and ending up with unreliable code that fail silently or crash outright when a function call they assumed would work stopped working. If you've worked in large multi-person projects, you'll see very quickly why you *need* exception handling. No modern language can do without exception handling. Maybe you have a beef with how it's currently done in D, but regardless, you *need* exception handling of some kind.
The exception handling system via try/catch is as bad and tedious as error codes, except the added runtime. It all roots from the idea "catch everything that throws". This is broken, as you DON'T always need to handle all sorts of errors (letting it segfault or something sometimes simply proves to be better than trying to save the situation; or you can simply assert it). Also http://yosefk.com/c++fqa/exceptions.html#fqa-17.1
 - Versions - not redundant, but needs a better system (with 
 AND/OR,
 possibility of de-versioning, the assignment op to set 
 versions is
 kinda bad)
[...] I find versions sorta neat... and they're simple enough that they don't add to much bloat to the language. (Whereas if you added AND and OR to them, then they start duplicating the function of static if, and that's when they become redundant.)
They're nearly unusable now. And the syntax simply makes no sense.
 T
Apr 28 2012
next sibling parent reply "SomeDude" <lovelydear mailmetrash.com> writes:
On Saturday, 28 April 2012 at 21:05:12 UTC, q66 wrote:
 On Saturday, 28 April 2012 at 20:50:30 UTC, H. S. Teoh wrote:
 On Sat, Apr 28, 2012 at 09:22:59PM +0200, q66 wrote:
 [...]
 - AAs integrated in the language; you barely ever use AA 
 literals and
 having them purely in Phobos would help get rid of the 
 runtime fat, as
 well as better implementations
On the contrary, AA's are a major reason I started programming in D. In this day and age, it's simply inexcusable to *not* have some kind of hash type available by default.
Besides AA literals, library can handle this JUST FINE.
Yeah, but core language AA are so useful it would be a MAJOR mistake to remove them. In Python too, you could put the AA in the libraries. Yet everybody uses the AA that are in the language. Where I DO agree with you is, Phobos should be a two level library, i.e a minimalistic library, with about the same feature set as the standard C library + multithreading, and a superset with the full range of features (ranges, algorithms, etc). I've already advocated it somewhere else.
Apr 28 2012
parent reply =?UTF-8?B?QWxleCBSw7hubmUgUGV0ZXJzZW4=?= <xtzgzorex gmail.com> writes:
On 28-04-2012 23:18, SomeDude wrote:
 On Saturday, 28 April 2012 at 21:05:12 UTC, q66 wrote:
 On Saturday, 28 April 2012 at 20:50:30 UTC, H. S. Teoh wrote:
 On Sat, Apr 28, 2012 at 09:22:59PM +0200, q66 wrote:
 [...]
 - AAs integrated in the language; you barely ever use AA literals and
 having them purely in Phobos would help get rid of the runtime fat, as
 well as better implementations
On the contrary, AA's are a major reason I started programming in D. In this day and age, it's simply inexcusable to *not* have some kind of hash type available by default.
Besides AA literals, library can handle this JUST FINE.
Yeah, but core language AA are so useful it would be a MAJOR mistake to remove them. In Python too, you could put the AA in the libraries. Yet everybody uses the AA that are in the language. Where I DO agree with you is, Phobos should be a two level library, i.e a minimalistic library, with about the same feature set as the standard C library + multithreading, and a superset with the full range of features (ranges, algorithms, etc). I've already advocated it somewhere else.
Let's get a standard package manager that we either advocate on dlang.org or include in the releases before we start talking about reducing the amount of modules in Phobos. -- - Alex
Apr 29 2012
next sibling parent "SomeDude" <lovelydear mailmetrash.com> writes:
On Sunday, 29 April 2012 at 20:00:27 UTC, Alex Rønne Petersen 
wrote:
 Let's get a standard package manager that we either advocate on 
 dlang.org or include in the releases before we start talking 
 about reducing the amount of modules in Phobos.
Don't get me wrong. I don't want to reduce the amount of modules in Phobos. I think it's a great standard library. A little bit buggy in some places, and lacks a few important features (that are in the review queue), but great overall. I fear the risk with a package system is, having some parts of Phobos not being correctly maintained with time. And I want to be able to have the whole thing with a single download. No, my concern was, for smaller applications, in embedded systems for instance (Android, iOS, etc), there is not really a small basic library. So I would think of a two level standard library, one on top of the other. OTOH, Jonathan Davis made the remark that we can always use the C lib and its bindings, so this mostly satisfies my concern.
Apr 29 2012
prev sibling parent reply Manu <turkeyman gmail.com> writes:
On 29 April 2012 23:00, Alex R=C3=B8nne Petersen <xtzgzorex gmail.com> wrot=
e:

 On 28-04-2012 23:18, SomeDude wrote:

 Yeah, but core language AA are so useful it would be a MAJOR mistake to
 remove them. In Python too, you could put the AA in the libraries. Yet
 everybody uses the AA that are in the language.

 Where I DO agree with you is, Phobos should be a two level library, i.e
 a minimalistic library, with about the same feature set as the standard
 C library + multithreading, and a superset with the full range of
 features (ranges, algorithms, etc). I've already advocated it somewhere
 else.
Let's get a standard package manager that we either advocate on dlang.org=
or include in the releases before we start talking about reducing the
 amount of modules in Phobos.
Oh hell yes! I have exciting dreams of something like this every other night ;)
Apr 29 2012
parent reply Jacob Carlborg <doob me.com> writes:
On 2012-04-30 00:07, Manu wrote:
 On 29 April 2012 23:00, Alex Rønne Petersen <xtzgzorex gmail.com
 <mailto:xtzgzorex gmail.com>> wrote:
     Let's get a standard package manager that we either advocate on
     dlang.org <http://dlang.org> or include in the releases before we
     start talking about reducing the amount of modules in Phobos.


 Oh hell yes! I have exciting dreams of something like this every other
 night ;)
I'm working on this. Unfortunately I cannot work on this full-time so basically nothing gets done. https://github.com/jacob-carlborg/orbit/wiki/Orbit-Package-Manager-for-D https://github.com/jacob-carlborg/orbit -- /Jacob Carlborg
Apr 30 2012
parent reply simendsjo <simendsjo gmail.com> writes:
On Mon, 30 Apr 2012 09:24:44 +0200, Jacob Carlborg <doob me.com> wrote:

 On 2012-04-30 00:07, Manu wrote:
 On 29 April 2012 23:00, Alex R=C3=B8nne Petersen <xtzgzorex gmail.com=
 <mailto:xtzgzorex gmail.com>> wrote:
     Let's get a standard package manager that we either advocate on
     dlang.org <http://dlang.org> or include in the releases before we=
     start talking about reducing the amount of modules in Phobos.


 Oh hell yes! I have exciting dreams of something like this every othe=
r
 night ;)
I'm working on this. Unfortunately I cannot work on this full-time so =
=
 basically nothing gets done.

 https://github.com/jacob-carlborg/orbit/wiki/Orbit-Package-Manager-for=
-D
 https://github.com/jacob-carlborg/orbit
Vibe.d has its own: = https://github.com/rejectedsoftware/vibe.d/tree/master/source/vibe/vpm And we have dsss: https://github.com/apriori/dsss And it seems this might be related too: = https://github.com/dbuilder-developers/dbuilder Getting orbit up and running would have been great.
Apr 30 2012
parent Jacob Carlborg <doob me.com> writes:
On 2012-04-30 09:32, simendsjo wrote:

 Vibe.d has its own:
 https://github.com/rejectedsoftware/vibe.d/tree/master/source/vibe/vpm
 And we have dsss: https://github.com/apriori/dsss
"This project is currently on ice in favor of porting orbit from D1 to D2 and continue its implemention. Orbit will cover the same featureset as dsss and much more." BTW, Orbit is already ported to D2.
 And it seems this might be related too:
 https://github.com/dbuilder-developers/dbuilder
This seems to be a build tool and not a package manager.
 Getting orbit up and running would have been great.
-- /Jacob Carlborg
Apr 30 2012
prev sibling next sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 04/28/2012 11:05 PM, q66 wrote:
 On Saturday, 28 April 2012 at 20:50:30 UTC, H. S. Teoh wrote:
 On Sat, Apr 28, 2012 at 09:22:59PM +0200, q66 wrote:
 [...]
 - AAs integrated in the language; you barely ever use AA literals and
 having them purely in Phobos would help get rid of the runtime fat, as
 well as better implementations
On the contrary, AA's are a major reason I started programming in D. In this day and age, it's simply inexcusable to *not* have some kind of hash type available by default.
Besides AA literals, library can handle this JUST FINE.
That is why they should be a narrow wrapper around a library defined type.
 - Phobos is too fat - it needs to shrink to just a few core modules,
 others being distributed via some system like CPAN for Perl
Um... that's what a *library* is supposed to be: a large collection of useful stuff from which you can pick the few that you need right now.
Too large collection becomes too hard to manage. Separating it and distributing in style "you pay for what you use" is IMO the right approach.
This sounds reasonable.
 - Properties - they're kinda broken at this point and the value is
 questionable
What kind of properties are you referring to?
The property crap. It's broken. If anything, it needs something like in
As I understand it, the 'agreed upon' design is that property int foo() { return x; } property void foo(int v) { x = v; } int foo { set{ x = value; }; get{ return x; } } I think it is even perfectly fine to just allow function calls without parentheses, but I wouldn't mind seeing that feature gone.
 -  trusted  system
These are necessary.
They're far from necessary.
Why? Memory safety is generally considered to be important.
 - Exception handling - a lot of runtime, questionable value
I completely disagree. No exception handling means lots and lots and lots of boilerplate code for checking error codes, return values, which are too tedious to write, which translates to many people leaving them out and ending up with unreliable code that fail silently or crash outright when a function call they assumed would work stopped working. If you've worked in large multi-person projects, you'll see very quickly why you *need* exception handling. No modern language can do without exception handling. Maybe you have a beef with how it's currently done in D, but regardless, you *need* exception handling of some kind.
The exception handling system via try/catch is as bad and tedious as error codes, except the added runtime.
It can improve performance though, because the exceptional branches don't occur in the code that is normally executed.
 It all roots from the idea "catch everything that throws".
 This is broken, as you DON'T always need to
 handle all sorts of errors (letting it segfault or something sometimes
 simply proves to be better than trying to save the situation;
Except that it won't necessarily segfault. That is not how _reliable_ systems work. Robustness is an important property of critical systems. If your software might kill people if it behaves in the wrong way, you really really don't want to ignore error conditions.
 or you can simply assert it).
Certainly, if it is a consistency criterion internal to the program, then assertions should be used.
 Also http://yosefk.com/c++fqa/exceptions.html#fqa-17.1
 [snip.]
The part of this article relevant for D is this: "Still, in many cases, the benefits of exceptions are more important than their problems. For example, if your language manages memory automatically, the problem of releasing acquired resources becomes a small one (you only have to care about files, etc., which are a tiny part of the "resources" used by a program - most of the "resources" are memory). If your language throws exceptions when you violate its rules (for example, upon out-of-bounds array access), these exceptions will help you find lots of bugs, especially if you can get the call stack from an exception. If the purpose of an application is automated testing, and/or it's used as a quick-and-dirty internal tool as opposed to a product for an end user, this kind of exceptions is all you need to handle errors of almost all kinds. In some languages, you can even resume the execution from the point where the exception was raised after fixing the problem at the point where it was caught." Anyway, I generally avoid exceptions if they are not an obvious fit.
Apr 28 2012
parent reply =?UTF-8?B?QWxleCBSw7hubmUgUGV0ZXJzZW4=?= <xtzgzorex gmail.com> writes:
On 28-04-2012 23:41, Timon Gehr wrote:
 On 04/28/2012 11:05 PM, q66 wrote:
 On Saturday, 28 April 2012 at 20:50:30 UTC, H. S. Teoh wrote:
 On Sat, Apr 28, 2012 at 09:22:59PM +0200, q66 wrote:
 [...]
 - AAs integrated in the language; you barely ever use AA literals and
 having them purely in Phobos would help get rid of the runtime fat, as
 well as better implementations
On the contrary, AA's are a major reason I started programming in D. In this day and age, it's simply inexcusable to *not* have some kind of hash type available by default.
Besides AA literals, library can handle this JUST FINE.
That is why they should be a narrow wrapper around a library defined type.
 - Phobos is too fat - it needs to shrink to just a few core modules,
 others being distributed via some system like CPAN for Perl
Um... that's what a *library* is supposed to be: a large collection of useful stuff from which you can pick the few that you need right now.
Too large collection becomes too hard to manage. Separating it and distributing in style "you pay for what you use" is IMO the right approach.
This sounds reasonable.
 - Properties - they're kinda broken at this point and the value is
 questionable
What kind of properties are you referring to?
The property crap. It's broken. If anything, it needs something like in
As I understand it, the 'agreed upon' design is that property int foo() { return x; } property void foo(int v) { x = v; } int foo { set{ x = value; }; get{ return x; } }
Nope. First of all, you'd have to declare the setter like this in D: property int foo(int v) { return x = v; } so that you can write: Next up is the issue of op-assign operations. In D, you can't do: obj.foo += 1; obj.foo++; -> set, etc).
 I think it is even perfectly fine to just allow function calls without
 parentheses, but I wouldn't mind seeing that feature gone.

 -  trusted  system
These are necessary.
They're far from necessary.
Why? Memory safety is generally considered to be important.
 - Exception handling - a lot of runtime, questionable value
I completely disagree. No exception handling means lots and lots and lots of boilerplate code for checking error codes, return values, which are too tedious to write, which translates to many people leaving them out and ending up with unreliable code that fail silently or crash outright when a function call they assumed would work stopped working. If you've worked in large multi-person projects, you'll see very quickly why you *need* exception handling. No modern language can do without exception handling. Maybe you have a beef with how it's currently done in D, but regardless, you *need* exception handling of some kind.
The exception handling system via try/catch is as bad and tedious as error codes, except the added runtime.
It can improve performance though, because the exceptional branches don't occur in the code that is normally executed.
 It all roots from the idea "catch everything that throws".
 This is broken, as you DON'T always need to
 handle all sorts of errors (letting it segfault or something sometimes
 simply proves to be better than trying to save the situation;
Except that it won't necessarily segfault. That is not how _reliable_ systems work. Robustness is an important property of critical systems. If your software might kill people if it behaves in the wrong way, you really really don't want to ignore error conditions.
 or you can simply assert it).
Certainly, if it is a consistency criterion internal to the program, then assertions should be used.
 Also http://yosefk.com/c++fqa/exceptions.html#fqa-17.1
 [snip.]
The part of this article relevant for D is this: "Still, in many cases, the benefits of exceptions are more important than their problems. For example, if your language manages memory automatically, the problem of releasing acquired resources becomes a small one (you only have to care about files, etc., which are a tiny part of the "resources" used by a program - most of the "resources" are memory). If your language throws exceptions when you violate its rules (for example, upon out-of-bounds array access), these exceptions will help you find lots of bugs, especially if you can get the call stack from an exception. If the purpose of an application is automated testing, and/or it's used as a quick-and-dirty internal tool as opposed to a product for an end user, this kind of exceptions is all you need to handle errors of almost all kinds. In some languages, you can even resume the execution from the point where the exception was raised after fixing the problem at the point where it was caught." Anyway, I generally avoid exceptions if they are not an obvious fit.
-- - Alex
Apr 29 2012
next sibling parent reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 4/29/12, Alex R=F8nne Petersen <xtzgzorex gmail.com> wrote:
 Next up is the issue of op-assign operations. In D, you can't do:

 obj.foo +=3D 1;
 obj.foo++;


 -> set, etc).
It's great to see another (successful) language implemented this. Do we have a proposal open for this somewhere?
Apr 29 2012
next sibling parent =?ISO-8859-1?Q?Alex_R=F8nne_Petersen?= <xtzgzorex gmail.com> writes:
On 29-04-2012 22:16, Andrej Mitrovic wrote:
 On 4/29/12, Alex Rønne Petersen<xtzgzorex gmail.com>  wrote:
 Next up is the issue of op-assign operations. In D, you can't do:

 obj.foo += 1;
 obj.foo++;


 ->  set, etc).
It's great to see another (successful) language implemented this. Do we have a proposal open for this somewhere?
AFAIK no. -- - Alex
Apr 29 2012
prev sibling next sibling parent reply "Jesse Phillips" <jessekphillips+D gmail.com> writes:
On Sunday, 29 April 2012 at 20:16:16 UTC, Andrej Mitrovic wrote:
 On 4/29/12, Alex Rønne Petersen <xtzgzorex gmail.com> wrote:
 Next up is the issue of op-assign operations. In D, you can't 
 do:

 obj.foo += 1;
 obj.foo++;


 get -> inc
 -> set, etc).
It's great to see another (successful) language implemented this. Do we have a proposal open for this somewhere?
I believe DIP 4 is the proposal http://www.prowiki.org/wiki4d/wiki.cgi?LanguageDevel/DIPs But don't forget to check out DIP 5 too.
Apr 29 2012
parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 4/30/12, Jesse Phillips <jessekphillips+D gmail.com> wrote:
 I believe DIP 4 is the proposal

 http://www.prowiki.org/wiki4d/wiki.cgi?LanguageDevel/DIPs

 But don't forget to check out DIP 5 too.
Well it says they're both superseeded by DIP 6 but DIP6 didn't implement things DIP4 was talking about.DIP4 goes on to discuss I didn't find anything in bugzilla, so I'm opening an enhancement request: http://d.puremagic.com/issues/show_bug.cgi?id=8006
Apr 29 2012
prev sibling parent Jacob Carlborg <doob me.com> writes:
On 2012-04-29 22:16, Andrej Mitrovic wrote:
 On 4/29/12, Alex Rønne Petersen<xtzgzorex gmail.com>  wrote:
 Next up is the issue of op-assign operations. In D, you can't do:

 obj.foo += 1;
 obj.foo++;


 ->  set, etc).
It's great to see another (successful) language implemented this. Do we have a proposal open for this somewhere?
I think someone started to work on this. I have no idea what happened to it though. -- /Jacob Carlborg
Apr 30 2012
prev sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 04/29/2012 10:03 PM, Alex Rønne Petersen wrote:
 On 28-04-2012 23:41, Timon Gehr wrote:
 As I understand it, the 'agreed upon' design is that

  property int foo() { return x; }
  property void foo(int v) { x = v; }



 int foo { set{ x = value; }; get{ return x; } }
Nope. First of all, you'd have to declare the setter like this in D: property int foo(int v) { return x = v; } so that you can write: Next up is the issue of op-assign operations. In D, you can't do: obj.foo += 1; obj.foo++; -> set, etc).
I didn't say this was how it worked in the current compiler implementation. But I may be wrong on what is the design because I didn't take part in that discussion. Notably, read-update operations now work on the built-in length property of arrays. I don't think there is any justification for not implementing this for properties.
Apr 29 2012
prev sibling parent Mike Parker <aldacron gmail.com> writes:
On 4/29/2012 6:05 AM, q66 wrote:

 I find versions sorta neat... and they're simple enough that they don't
 add to much bloat to the language. (Whereas if you added AND and OR to
 them, then they start duplicating the function of static if, and that's
 when they become redundant.)
They're nearly unusable now. And the syntax simply makes no sense.
 T
Someone forgot to tell me how unusable they are, because I've been using them for years. Quite sensibly.
Apr 28 2012
prev sibling parent "Era Scarecrow" <rtcvb32 yahoo.com> writes:
On Saturday, 28 April 2012 at 20:50:30 UTC, H. S. Teoh wrote:
 On Sat, Apr 28, 2012 at 09:22:59PM +0200, q66 wrote:
 - Phobos is too fat - it needs to shrink to just a few core 
 modules,
 others being distributed via some system like CPAN for Perl
Um... that's what a *library* is supposed to be: a large collection of useful stuff from which you can pick the few that you need right now.
And the STL and libc isn't big? Size is only intimidating if you don't know what your looking for. Having to scour in std.ascii, then std.utf, then std.array or other locations when your looking for something can get a little annoying. But it's a learning curve, once you know it you tend to find the functions and information fairly quickly. More likely a good tutorial through the library would alleviate some of that, or just the parts that are more confusing. One part for example involving conversion for unicode, I still have no idea how to convert Latin1String (extended ascii) to utf so I could use all of phobos's power; So I've ended up writing my own little conversion function for that. It's going to come down that stuff we write and post up that we think is self explanatory isn't because as the implementers we understand it in intimately.
Apr 28 2012
prev sibling parent Jacob Carlborg <doob me.com> writes:
On 2012-04-28 21:22, q66 wrote:
 On Saturday, 28 April 2012 at 18:48:18 UTC, Walter Bright wrote:
 Andrei and I had a fun discussion last night about this question. The
 idea was which features in D are redundant and/or do not add
 significant value?

 A couple already agreed upon ones are typedef and the cfloat, cdouble
 and creal types.

 What's your list?
- AAs integrated in the language; you barely ever use AA literals and having them purely in Phobos would help get rid of the runtime fat, as well as better implementations - Phobos is too fat - it needs to shrink to just a few core modules, others being distributed via some system like CPAN for Perl - Properties - they're kinda broken at this point and the value is questionable - trusted system - Exception handling - a lot of runtime, questionable value - Versions - not redundant, but needs a better system (with AND/OR, possibility of de-versioning, the assignment op to set versions is kinda bad) I think I would find some more, but these are the ones I can recall now.
As others have said, I think this is crazy. -- /Jacob Carlborg
Apr 29 2012
prev sibling next sibling parent reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 4/28/12, Walter Bright <newshound2 digitalmars.com> wrote:
 What's your list?
I don't mind extra features, just as long as they're properly documented and implemented. For example, I have absolutely no uses for anonymous classes right now, but I know DWT2 uses them and probably other people do use them. Personally I find the hardest threads to to follow are the ones discussing in/out/inout/autoref. For one thing there are compiler bugs, but then there are misconceptions between what developers vs documentation vs core devs say about them. And then you mix in classes and templates into the story and it all becomes a large forest of information that is very hard to digest. Another feature I'm curious about is .dup/.idup. It's basically hardcoded for a couple of types, but why not instead use UFCS and implement .dup/.idup in std.array as a free function? Then you might even use it for user-types by requiring a type to implement .dup/.idup functions. Also there's mixin templates. What exactly is the difference between mixin templates and regular templates? We can use the mixin statement for both types right now, so there doesn't seem to be a distinction. For example, if you take samples from the template mixin page (http://dlang.org/template-mixin.html) and you remove "mixin" from the template declaration, all of the samples will continue to work. You could remove this declaration feature right now and you probably wouldn't break any code at all. Seems like low-hanging fruit to me.
Apr 28 2012
next sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 4/28/2012 12:36 PM, Andrej Mitrovic wrote:
 Also there's mixin templates. What exactly is the difference between
 mixin templates and regular templates?
A mixin template is instantiated in context of the instantiation point, while a regular template is instantiated in the context of the template definition point. This becomes relevant when looking up symbols that are not defined within the template.
Apr 28 2012
next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 4/28/12, Walter Bright <newshound2 digitalmars.com> wrote:
 A mixin template is instantiated in context of the instantiation point,
 while a
 regular template is instantiated in the context of the template definition
 point.
Ooooh. Suddenly that explains some of my compilation errors.
Apr 28 2012
prev sibling next sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 04/28/2012 10:02 PM, Walter Bright wrote:
 On 4/28/2012 12:36 PM, Andrej Mitrovic wrote:
 Also there's mixin templates. What exactly is the difference between
 mixin templates and regular templates?
A mixin template is instantiated in context of the instantiation point, while a regular template is instantiated in the context of the template definition point. This becomes relevant when looking up symbols that are not defined within the template.
The implementation seems to disagree: int x; template X(){ // not a mixin template void y(){x=2;} } class C{ int x; mixin X; // picks up local 'x' } void main(){ auto c = new C; c.y(); import std.stdio; writeln(x," ",c.x); // "0 2" } Or am I misunderstanding your statement?
Apr 28 2012
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 4/28/2012 1:32 PM, Timon Gehr wrote:
 On 04/28/2012 10:02 PM, Walter Bright wrote:
 On 4/28/2012 12:36 PM, Andrej Mitrovic wrote:
 Also there's mixin templates. What exactly is the difference between
 mixin templates and regular templates?
A mixin template is instantiated in context of the instantiation point, while a regular template is instantiated in the context of the template definition point. This becomes relevant when looking up symbols that are not defined within the template.
The implementation seems to disagree: int x; template X(){ // not a mixin template void y(){x=2;} } class C{ int x; mixin X; // picks up local 'x'
Makes it a mixin template.
 }

 void main(){
 auto c = new C;
 c.y();
 import std.stdio;
 writeln(x," ",c.x); // "0 2"
 }

 Or am I misunderstanding your statement?
The behavior is as I described.
Apr 30 2012
parent "David Nadlinger" <see klickverbot.at> writes:
On Tuesday, 1 May 2012 at 02:40:34 UTC, Walter Bright wrote:
 On 4/28/2012 1:32 PM, Timon Gehr wrote:
 […]
 class C{
 int x;
 mixin X; // picks up local 'x'
Makes it a mixin template.
Why not just require mixin templates to be declared using »mixin template« then? David
Apr 30 2012
prev sibling parent reply Artur Skawina <art.08.09 gmail.com> writes:
On 04/28/12 22:02, Walter Bright wrote:
 On 4/28/2012 12:36 PM, Andrej Mitrovic wrote:
 Also there's mixin templates. What exactly is the difference between
 mixin templates and regular templates?
A mixin template is instantiated in context of the instantiation point, while a regular template is instantiated in the context of the template definition point. This becomes relevant when looking up symbols that are not defined within the template.
Yeah, but this was actually the only suggestion so far in this thread that i could agree with... The issue is template t1() { int a = b; } int main() { int b; mixin t1; return a; } which is currently accepted - and would enforcing the mixin annotation really help anything? artur
Apr 28 2012
parent reply "Simen Kjaeraas" <simen.kjaras gmail.com> writes:
On Sat, 28 Apr 2012 22:40:10 +0200, Artur Skawina <art.08.09 gmail.com>  
wrote:

 On 04/28/12 22:02, Walter Bright wrote:
 On 4/28/2012 12:36 PM, Andrej Mitrovic wrote:
 Also there's mixin templates. What exactly is the difference between
 mixin templates and regular templates?
A mixin template is instantiated in context of the instantiation point, while a regular template is instantiated in the context of the template definition point. This becomes relevant when looking up symbols that are not defined within the template.
Yeah, but this was actually the only suggestion so far in this thread that i could agree with... The issue is template t1() { int a = b; } int main() { int b; mixin t1; return a; } which is currently accepted - and would enforcing the mixin annotation really help anything? artur
At least some of us want mixin templates to be marked mixin at declaration point, and usable without 'mixin': mixin template A( ) { int n; } struct S { A!(); }
Apr 29 2012
parent Artur Skawina <art.08.09 gmail.com> writes:
On 04/30/12 02:33, Simen Kjaeraas wrote:
 On Sat, 28 Apr 2012 22:40:10 +0200, Artur Skawina <art.08.09 gmail.com> wrote:
 
 On 04/28/12 22:02, Walter Bright wrote:
 On 4/28/2012 12:36 PM, Andrej Mitrovic wrote:
 Also there's mixin templates. What exactly is the difference between
 mixin templates and regular templates?
A mixin template is instantiated in context of the instantiation point, while a regular template is instantiated in the context of the template definition point. This becomes relevant when looking up symbols that are not defined within the template.
Yeah, but this was actually the only suggestion so far in this thread that i could agree with... The issue is template t1() { int a = b; } int main() { int b; mixin t1; return a; } which is currently accepted - and would enforcing the mixin annotation really help anything? artur
At least some of us want mixin templates to be marked mixin at declaration point, and usable without 'mixin': mixin template A( ) { int n; } struct S { A!(); }
Yes, that's the other possible use for marking a template as a mixin. Unlike my above example it wouldn't then be redundant; the question is however if this functionality really is desirable... mixin template t1() { auto _ = a = b; } int main() { int a, b=1; t1!(); return a; } This program would now return '1', which can be non-obvious if you don't know the definition of 't1'. Right now you have to write that as template t1() { auto _ = a = b; } int main() { int a, b=1; mixin t1!(); return a; } so the mixin is clearly visible. These kind of template macros would be useful and i'd like to have them too, but there is a cost, and i'm not yet sure that being able to omit the 'mixin' keyword would be worth it. artur
Apr 29 2012
prev sibling next sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2012-04-28 21:36, Andrej Mitrovic wrote:
 On 4/28/12, Walter Bright<newshound2 digitalmars.com>  wrote:
 What's your list?
I don't mind extra features, just as long as they're properly documented and implemented. For example, I have absolutely no uses for anonymous classes right now, but I know DWT2 uses them and probably other people do use them.
If a anonymous classes where remove from D, life would get even harder for DWT.
 Personally I find the hardest threads to to follow are the ones
 discussing in/out/inout/autoref. For one thing there are compiler
 bugs, but then there are misconceptions between what developers vs
 documentation vs core devs say about them. And then you mix in classes
 and templates into the story and it all becomes a large forest of
 information that is very hard to digest.
Agree.
 Another feature I'm curious about is .dup/.idup. It's basically
 hardcoded for a couple of types, but why not instead use UFCS and
 implement .dup/.idup in std.array as a free function? Then you might
 even use it for user-types by requiring a type to implement .dup/.idup
 functions.
Agree with this one as well. -- /Jacob Carlborg
Apr 29 2012
parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Sun, Apr 29, 2012 at 04:43:12PM +0200, Jacob Carlborg wrote:
 On 2012-04-28 21:36, Andrej Mitrovic wrote:
[...]
Another feature I'm curious about is .dup/.idup. It's basically
hardcoded for a couple of types, but why not instead use UFCS and
implement .dup/.idup in std.array as a free function? Then you might
even use it for user-types by requiring a type to implement
.dup/.idup functions.
Agree with this one as well.
[...] +1. This would make generic code easier to write. Which is good, because the less we have to rewrite code that's been written a hundred times in the past already, the better. T -- A linguistics professor was lecturing to his class one day. "In English," he said, "A double negative forms a positive. In some languages, though, such as Russian, a double negative is still a negative. However, there is no language wherein a double positive can form a negative." A voice from the back of the room piped up, "Yeah, yeah."
Apr 29 2012
prev sibling parent =?ISO-8859-1?Q?Alex_R=F8nne_Petersen?= <xtzgzorex gmail.com> writes:
On 28-04-2012 21:36, Andrej Mitrovic wrote:
 On 4/28/12, Walter Bright<newshound2 digitalmars.com>  wrote:
 What's your list?
I don't mind extra features, just as long as they're properly documented and implemented. For example, I have absolutely no uses for anonymous classes right now, but I know DWT2 uses them and probably other people do use them.
I use them too. They're useful if you have an abstract method that just needs to return an arbitrary object implementing some interface or whatever.
 Personally I find the hardest threads to to follow are the ones
 discussing in/out/inout/autoref. For one thing there are compiler
 bugs, but then there are misconceptions between what developers vs
 documentation vs core devs say about them. And then you mix in classes
 and templates into the story and it all becomes a large forest of
 information that is very hard to digest.

 Another feature I'm curious about is .dup/.idup. It's basically
 hardcoded for a couple of types, but why not instead use UFCS and
 implement .dup/.idup in std.array as a free function? Then you might
 even use it for user-types by requiring a type to implement .dup/.idup
 functions.
This seems reasonable to me.
 Also there's mixin templates. What exactly is the difference between
 mixin templates and regular templates? We can use the mixin statement
 for both types right now, so there doesn't seem to be a distinction.
 For example, if you take samples from the template mixin page
 (http://dlang.org/template-mixin.html) and you remove "mixin" from the
 template declaration, all of the samples will continue to work. You
 could remove this declaration feature right now and you probably
 wouldn't break any code at all. Seems like low-hanging fruit to me.
-- - Alex
Apr 29 2012
prev sibling next sibling parent reply "foobar" <foo bar.com> writes:
On Saturday, 28 April 2012 at 18:48:18 UTC, Walter Bright wrote:
 Andrei and I had a fun discussion last night about this 
 question. The idea was which features in D are redundant and/or 
 do not add significant value?

 A couple already agreed upon ones are typedef and the cfloat, 
 cdouble and creal types.

 What's your list?
D has a lot of ad-hock features which make the language needlessly large and complex. I'd strive to replace these with better general purpose mechanisms. My list: * I'd start with getting rid of foreach completely. (not just foreach_reverse). This is nothing more than a fancy function with a delegate parameter. * enum - enum should be completely redesigned to only implement what it's named after: enumerations. * version - this does not belong in a programming language. Git is a much better solution. * di files - a library should encapsulate all the info required to use it. Java Jars, .Net assemblies and even old school; Pascal units all solved this long ago. * This is a big one: get rid of *all* current compile time special syntax. It should be replaced by a standard compilation API and the compiler should be able to use plugins/addons. This would reduce the size of the language to half of its current size, maybe even more.
Apr 28 2012
next sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 04/28/2012 09:58 PM, foobar wrote:
 On Saturday, 28 April 2012 at 18:48:18 UTC, Walter Bright wrote:
 Andrei and I had a fun discussion last night about this question. The
 idea was which features in D are redundant and/or do not add
 significant value?

 A couple already agreed upon ones are typedef and the cfloat, cdouble
 and creal types.

 What's your list?
D has a lot of ad-hock features which make the language needlessly large and complex. I'd strive to replace these with better general purpose mechanisms. My list: * I'd start with getting rid of foreach completely. (not just foreach_reverse).
foreach is very useful. Have you actually used D?
 This is nothing more than a fancy function with
 a delegate parameter.
That would be opApply.
 * enum - enum should be completely redesigned to only implement
 what it's named after: enumerations.
What is the benefit?
 * version - this does not belong in a programming language. Git
 is a much better solution.
So you'd maintain a git branch for every OS if there is some small part that is OS-dependent? I don't think that is a better approach at all.
 * di files - a library should encapsulate all the info required
 to use it. Java Jars, .Net assemblies and even old school; Pascal
 units all solved this long ago.

 * This is a big one: get rid of *all* current compile time
 special syntax.
What would that be exactly?
 It should be replaced by a standard compilation
 API and the compiler should be able to use plugins/addons.
Are you serious?
 This would reduce the size of the language to half of its current
 size, maybe even more.
I am certain that it would not. You missed to present the 'general purpose mechanisms'.
Apr 28 2012
next sibling parent reply "foobar" <foo bar.com> writes:
On Saturday, 28 April 2012 at 20:43:38 UTC, Timon Gehr wrote:
 On 04/28/2012 09:58 PM, foobar wrote:
 On Saturday, 28 April 2012 at 18:48:18 UTC, Walter Bright 
 wrote:
 Andrei and I had a fun discussion last night about this 
 question. The
 idea was which features in D are redundant and/or do not add
 significant value?

 A couple already agreed upon ones are typedef and the cfloat, 
 cdouble
 and creal types.

 What's your list?
D has a lot of ad-hock features which make the language needlessly large and complex. I'd strive to replace these with better general purpose mechanisms. My list: * I'd start with getting rid of foreach completely. (not just foreach_reverse).
foreach is very useful. Have you actually used D?
I have used D and didn't claim that foreach isn't useful. What I said that is that it belongs in the library, NOT the language.
 This is nothing more than a fancy function with
 a delegate parameter.
That would be opApply.
Indeed but I'd go even further by integrating it with ranges so that ranges would provide an opApply like method e.g. auto r = BinaryTree!T.preOrder(); // returns range r.each( (T elem) { ...use elem...}); // each method a-la Ruby
 * enum - enum should be completely redesigned to only implement
 what it's named after: enumerations.
What is the benefit?
On the one hand the current enum for manifest constants is a hack due to weaknesses of the toolchain and on the other hand it doesn't provide properly encapsulated enums such as for instance the Java 5.0 ones or the functional kind.
 * version - this does not belong in a programming language. Git
 is a much better solution.
So you'd maintain a git branch for every OS if there is some small part that is OS-dependent? I don't think that is a better approach at all.
It is far better than having a pile of #ifdef styled spaghetti code. I'd expect to have all the OS specific code encapsulated separately anyway, not spread around the code base. Which is the current recommended way of using versions anyway. The inevitable conclusion would be to either use a version management system like git or have separate implementation modules for platform specific code and use the build tool to implement the logic of select the modules to include in the build.
 * di files - a library should encapsulate all the info required
 to use it. Java Jars, .Net assemblies and even old school; 
 Pascal
 units all solved this long ago.

 * This is a big one: get rid of *all* current compile time
 special syntax.
What would that be exactly?
This includes __traits, templates, static ifs, etc..
 It should be replaced by a standard compilation
 API and the compiler should be able to use plugins/addons.
Are you serious?
No I'm joking. The current system is a pile of hacks on top of the broken model of c++ templates. I should be able to use a *very* minimalistic system to write completely _regular_ D code and run it at different times. This is a simple matter of separation of concerns: what we want to execute (what code) is separate to the concern of when we want to execute it.
 This would reduce the size of the language to half of its 
 current
 size, maybe even more.
I am certain that it would not. You missed to present the 'general purpose mechanisms'.
Apr 28 2012
next sibling parent reply "SomeDude" <lovelydear mailmetrash.com> writes:
On Saturday, 28 April 2012 at 23:25:10 UTC, foobar wrote:
 On Saturday, 28 April 2012 at 20:43:38 UTC, Timon Gehr wrote:
 On 04/28/2012 09:58 PM, foobar wrote:
 On Saturday, 28 April 2012 at 18:48:18 UTC, Walter Bright 
 wrote:
 Andrei and I had a fun discussion last night about this 
 question. The
 idea was which features in D are redundant and/or do not add
 significant value?

 A couple already agreed upon ones are typedef and the 
 cfloat, cdouble
 and creal types.

 What's your list?
D has a lot of ad-hock features which make the language needlessly large and complex. I'd strive to replace these with better general purpose mechanisms. My list: * I'd start with getting rid of foreach completely. (not just foreach_reverse).
foreach is very useful. Have you actually used D?
I have used D and didn't claim that foreach isn't useful. What I said that is that it belongs in the library, NOT the language.
Well, it's your opinion. But I bet it's not the opinion of designers, and I even believe they wanted to add foreach in C++ (or is it already the case ?). Putting things in the library isn't the solution for everything: it's often hard (if possible) to make it work as well as in the core language, and error messages are usually more cryptic. Basic features like this should stay in the core language in my opinion.
 This is nothing more than a fancy function with
 a delegate parameter.
That would be opApply.
Indeed but I'd go even further by integrating it with ranges so that ranges would provide an opApply like method e.g. auto r = BinaryTree!T.preOrder(); // returns range r.each( (T elem) { ...use elem...}); // each method a-la Ruby
 * enum - enum should be completely redesigned to only 
 implement
 what it's named after: enumerations.
What is the benefit?
On the one hand the current enum for manifest constants is a hack due to weaknesses of the toolchain and on the other hand it doesn't provide properly encapsulated enums such as for instance the Java 5.0 ones or the functional kind.
 * version - this does not belong in a programming language. 
 Git
 is a much better solution.
So you'd maintain a git branch for every OS if there is some small part that is OS-dependent? I don't think that is a better approach at all.
It is far better than having a pile of #ifdef styled spaghetti code. I'd expect to have all the OS specific code encapsulated separately anyway, not spread around the code base. Which is the current recommended way of using versions anyway. The inevitable conclusion would be to either use a version management system like git or have separate implementation modules for platform specific code and use the build tool to implement the logic of select the modules to include in the build.
No it isn't. Ask the kernel hackers why they still use #ifdef instead of using hundreds of git branches for every feature and platform they must maintain.
 * di files - a library should encapsulate all the info 
 required
 to use it. Java Jars, .Net assemblies and even old school; 
 Pascal
 units all solved this long ago.

 * This is a big one: get rid of *all* current compile time
 special syntax.
What would that be exactly?
This includes __traits, templates, static ifs, etc..
 It should be replaced by a standard compilation
 API and the compiler should be able to use plugins/addons.
Are you serious?
No I'm joking. The current system is a pile of hacks on top of the broken model of c++ templates. I should be able to use a *very* minimalistic system to write completely _regular_ D code and run it at different times. This is a simple matter of separation of concerns: what we want to execute (what code) is separate to the concern of when we want to execute it.
 This would reduce the size of the language to half of its 
 current
 size, maybe even more.
I am certain that it would not. You missed to present the 'general purpose mechanisms'.
You should use Go. It fits better to your views about programming languages than D.
Apr 28 2012
parent reply =?UTF-8?B?QWxleCBSw7hubmUgUGV0ZXJzZW4=?= <xtzgzorex gmail.com> writes:
On 29-04-2012 01:49, SomeDude wrote:
 On Saturday, 28 April 2012 at 23:25:10 UTC, foobar wrote:
 On Saturday, 28 April 2012 at 20:43:38 UTC, Timon Gehr wrote:
 On 04/28/2012 09:58 PM, foobar wrote:
 On Saturday, 28 April 2012 at 18:48:18 UTC, Walter Bright wrote:
 Andrei and I had a fun discussion last night about this question. The
 idea was which features in D are redundant and/or do not add
 significant value?

 A couple already agreed upon ones are typedef and the cfloat, cdouble
 and creal types.

 What's your list?
D has a lot of ad-hock features which make the language needlessly large and complex. I'd strive to replace these with better general purpose mechanisms. My list: * I'd start with getting rid of foreach completely. (not just foreach_reverse).
foreach is very useful. Have you actually used D?
I have used D and didn't claim that foreach isn't useful. What I said that is that it belongs in the library, NOT the language.
Well, it's your opinion. But I bet it's not the opinion of thousands of believe they wanted to add foreach in C++ (or is it already the case ?). Putting things in the library isn't the solution for everything: it's often hard (if possible) to make it work as well as in the core language, and error messages are usually more cryptic. Basic features like this should stay in the core language in my opinion.
C++11 has range-based for (which is basically foreach).
 This is nothing more than a fancy function with
 a delegate parameter.
That would be opApply.
Indeed but I'd go even further by integrating it with ranges so that ranges would provide an opApply like method e.g. auto r = BinaryTree!T.preOrder(); // returns range r.each( (T elem) { ...use elem...}); // each method a-la Ruby
 * enum - enum should be completely redesigned to only implement
 what it's named after: enumerations.
What is the benefit?
On the one hand the current enum for manifest constants is a hack due to weaknesses of the toolchain and on the other hand it doesn't provide properly encapsulated enums such as for instance the Java 5.0 ones or the functional kind.
 * version - this does not belong in a programming language. Git
 is a much better solution.
So you'd maintain a git branch for every OS if there is some small part that is OS-dependent? I don't think that is a better approach at all.
It is far better than having a pile of #ifdef styled spaghetti code. I'd expect to have all the OS specific code encapsulated separately anyway, not spread around the code base. Which is the current recommended way of using versions anyway. The inevitable conclusion would be to either use a version management system like git or have separate implementation modules for platform specific code and use the build tool to implement the logic of select the modules to include in the build.
No it isn't. Ask the kernel hackers why they still use #ifdef instead of using hundreds of git branches for every feature and platform they must maintain.
 * di files - a library should encapsulate all the info required
 to use it. Java Jars, .Net assemblies and even old school; Pascal
 units all solved this long ago.

 * This is a big one: get rid of *all* current compile time
 special syntax.
What would that be exactly?
This includes __traits, templates, static ifs, etc..
 It should be replaced by a standard compilation
 API and the compiler should be able to use plugins/addons.
Are you serious?
No I'm joking. The current system is a pile of hacks on top of the broken model of c++ templates. I should be able to use a *very* minimalistic system to write completely _regular_ D code and run it at different times. This is a simple matter of separation of concerns: what we want to execute (what code) is separate to the concern of when we want to execute it.
 This would reduce the size of the language to half of its current
 size, maybe even more.
I am certain that it would not. You missed to present the 'general purpose mechanisms'.
You should use Go. It fits better to your views about programming languages than D.
-- - Alex
Apr 29 2012
parent "David Nadlinger" <see klickverbot.at> writes:
On Sunday, 29 April 2012 at 20:10:20 UTC, Alex Rønne Petersen 
wrote:
 On 29-04-2012 01:49, SomeDude wrote:
 [snip wall of text]
C++11 has range-based for (which is basically foreach).
 [snip wall of text]
This is off-topic, but in general, please try to quote only the relevant parts of the message you are replying to (you just quoted the whole long message three times in full). David
Apr 29 2012
prev sibling next sibling parent "Era Scarecrow" <rtcvb32 yahoo.com> writes:
On Saturday, 28 April 2012 at 23:25:10 UTC, foobar wrote:
 On Saturday, 28 April 2012 at 20:43:38 UTC, Timon Gehr wrote:
 On 04/28/2012 09:58 PM, foobar wrote:
 * version - this does not belong in a programming language. 
 Git
 is a much better solution.
So you'd maintain a git branch for every OS if there is some small part that is OS-dependent? I don't think that is a better approach at all.
It is far better than having a pile of #ifdef styled spaghetti code. I'd expect to have all the OS specific code encapsulated separately anyway, not spread around the code base. Which is the current recommended way of using versions anyway. The inevitable conclusion would be to either use a version management system like git or have separate implementation modules for platform specific code and use the build tool to implement the logic of select the modules to include in the build.
Aren't both of those just side effects of bad design? Most #ifdef calls were to overcome limits in the language that probably overloading would have resolved. I haven't done large projects code beyond my own, and the one or two I've seen were actually done in java. All Architecture and OS specific code should be hopefully done in just one file; That way ugly or special purpose code could be limited to one spot. Not only that but the rest of the code should be clean and you can build another architecture or system with minimal work. Course there will be cases where a lot of work would be needed, or in other cases no work at all.
Apr 28 2012
prev sibling next sibling parent reply Dmitry Olshansky <dmitry.olsh gmail.com> writes:
On 29.04.2012 3:25, foobar wrote:
 On Saturday, 28 April 2012 at 20:43:38 UTC, Timon Gehr wrote:
 On 04/28/2012 09:58 PM, foobar wrote:
 On Saturday, 28 April 2012 at 18:48:18 UTC, Walter Bright wrote:
 Andrei and I had a fun discussion last night about this question. The
 idea was which features in D are redundant and/or do not add
 significant value?

 A couple already agreed upon ones are typedef and the cfloat, cdouble
 and creal types.

 What's your list?
D has a lot of ad-hock features which make the language needlessly large and complex. I'd strive to replace these with better general purpose mechanisms. My list: * I'd start with getting rid of foreach completely. (not just foreach_reverse).
foreach is very useful. Have you actually used D?
I have used D and didn't claim that foreach isn't useful. What I said that is that it belongs in the library, NOT the language.
C++ was criticized for a long time for NOT having foreach in the language. Now they have http://www2.research.att.com/~bs/C++0xFAQ.html#for. Also people were so desperate to gave it that even this http://www.boost.org/doc/libs/1_49_0/doc/html/foreach.html was considered a nice addition to boost (and still part of it). Obviously somehow you want to go into the opposite direction. Beats me. -- Dmitry Olshansky
Apr 28 2012
parent reply "Era Scarecrow" <rtcvb32 yahoo.com> writes:
 My list:
 * I'd start with getting rid of foreach completely. (not just 
 foreach_reverse).
 C++ was criticized for a long time for NOT having foreach in 
 the language. Now they have 
 http://www2.research.att.com/~bs/C++0xFAQ.html#for. Also people 
 were so desperate to gave it that even this 
 http://www.boost.org/doc/libs/1_49_0/doc/html/foreach.html was 
 considered a nice addition to boost (and still part of it).

 Obviously somehow you want to go into the opposite direction. 
 Beats me.
If it simplifies code, makes it easier, and is more consistent, having it is better than not having it. Like walter said in one of the recent videos (going native 2012) regarding having an assembler in a language: 'When you need it, you got to have it'. True most features can be re-written as work arounds, but if you don't have to then why insist on it? Backtracking by removing key features which make the language pleasant may throw us back into the C and C++ days. Yes you can do full memory management yourself, and use pointers and pass it's size to functions. We have fat pointers, so why insist on backtracking? At the worst case if it isn't breaking the language leave it alone. If you have good reasons for it, explain them in detail. At best those of us who know better will laugh and move on.
Apr 28 2012
parent "SomeDude" <lovelydear mailmetrash.com> writes:
On Sunday, 29 April 2012 at 06:11:00 UTC, Era Scarecrow wrote:
 My list:
 * I'd start with getting rid of foreach completely. (not just 
 foreach_reverse).
 C++ was criticized for a long time for NOT having foreach in 
 the language. Now they have 
 http://www2.research.att.com/~bs/C++0xFAQ.html#for. Also 
 people were so desperate to gave it that even this 
 http://www.boost.org/doc/libs/1_49_0/doc/html/foreach.html was 
 considered a nice addition to boost (and still part of it).

 Obviously somehow you want to go into the opposite direction. 
 Beats me.
If it simplifies code, makes it easier, and is more consistent, having it is better than not having it. Like walter said in one of the recent videos (going native 2012) regarding having an assembler in a language: 'When you need it, you got to have it'. True most features can be re-written as work arounds, but if you don't have to then why insist on it? Backtracking by removing key features which make the language pleasant may throw us back into the C and C++ days. Yes you can do full memory management yourself, and use pointers and pass it's size to functions. We have fat pointers, so why insist on backtracking? At the worst case if it isn't breaking the language leave it alone. If you have good reasons for it, explain them in detail. At best those of us who know better will laugh and move on.
One of the ideas that I see regularly thrown around is to remove more and more things from the core language and put them in the libraries, because it's possible, and it would make for a thinner languages. Well, these are good reasons to do it, but there are many good reasons NOT to do it. Some general reasons: 1. code is uglier when in the libraries. One must add imports, and template code is uglier and harder to write than plain old code. 2. template code makes bigger size executables 3. error messages are more cryptic 4. we like to think that putting things in the library helps changing things easier, but my opinion is, changing fundamental structures in the standard library may actually break more code than changing them in the core language, because of the heavy interplay between modules, and also because the standard library is probably less well tested (in terms of number of regression tests) than the core language. 5. it makes work much harder for tools and parsers Specific to D: 6. my impression is, from what I've seen in Bugzilla, that Phobos bugs tend to stay around longer, because there is not enough workforce on it These a lot of drawbacks in my opinion. Basically, one of the main reasons the D code is clean, is because the core languages features so many useful things, with a nice, clean syntax. Moving them to the standard library will automatically make the code uglier and the language harder to use.
Apr 29 2012
prev sibling next sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 04/29/2012 01:25 AM, foobar wrote:
 On Saturday, 28 April 2012 at 20:43:38 UTC, Timon Gehr wrote:
 On 04/28/2012 09:58 PM, foobar wrote:
 On Saturday, 28 April 2012 at 18:48:18 UTC, Walter Bright wrote:
 Andrei and I had a fun discussion last night about this question. The
 idea was which features in D are redundant and/or do not add
 significant value?

 A couple already agreed upon ones are typedef and the cfloat, cdouble
 and creal types.

 What's your list?
D has a lot of ad-hock features which make the language needlessly large and complex. I'd strive to replace these with better general purpose mechanisms. My list: * I'd start with getting rid of foreach completely. (not just foreach_reverse).
foreach is very useful. Have you actually used D?
I have used D and didn't claim that foreach isn't useful. What I said that is that it belongs in the library, NOT the language.
Therefore you say that it is not useful as a language feature.
 This is nothing more than a fancy function with
 a delegate parameter.
That would be opApply.
Indeed but I'd go even further by integrating it with ranges so that ranges would provide an opApply like method e.g. auto r = BinaryTree!T.preOrder(); // returns range r.each( (T elem) { ...use elem...}); // each method a-la Ruby
Well, I don't think this is better than built-in foreach (with full break and continue and goto even for user-defined opApply!)
 * enum - enum should be completely redesigned to only implement
 what it's named after: enumerations.
What is the benefit?
On the one hand the current enum for manifest constants is a hack due to weaknesses of the toolchain
I think that is actually not true. It might have been the original motivation, but it has gone beyond that. Which weaknesses in particular? I don't think that the toolchain can be improved in any way in this regard.
 and on the other hand it doesn't provide
 properly encapsulated enums
Those could in theory be added without removing the manifest constant usage.
 such as for instance the Java 5.0 ones or
 the functional kind.
An algebraic data type is not an 'enumeration', so this is a moot point.
 * version - this does not belong in a programming language. Git
 is a much better solution.
So you'd maintain a git branch for every OS if there is some small part that is OS-dependent? I don't think that is a better approach at all.
It is far better than having a pile of #ifdef styled spaghetti code. I'd expect to have all the OS specific code encapsulated separately anyway, not spread around the code base. Which is the current recommended way of using versions anyway. The inevitable conclusion would be to either use a version management system like git or have separate implementation modules for platform specific code and use the build tool to implement the logic of select the modules to include in the build.
Which projects you are aware of actually use this kind of versioning?
 * di files - a library should encapsulate all the info required
 to use it. Java Jars, .Net assemblies and even old school; Pascal
 units all solved this long ago.

 * This is a big one: get rid of *all* current compile time
 special syntax.
What would that be exactly?
This includes __traits, templates, static ifs, etc..
This is what makes D useful to me.
 It should be replaced by a standard compilation
 API and the compiler should be able to use plugins/addons.
Are you serious?
No I'm joking. The current system is a pile of hacks on top of the broken model of c++ templates. I should be able to use a *very* minimalistic system to write completely _regular_ D code and run it at different times.
Examples in concrete syntax? How would you replace eg. string mixin functionality?
 This is a simple matter
 of separation of concerns: what we want to execute (what code) is
 separate to the concern of when we want to execute it.
It is not. For example, code that is only executed during CTFE does never have to behave gracefully if the input is ill-formed.
Apr 29 2012
parent reply "foobar" <foo bar.com> writes:
On Sunday, 29 April 2012 at 08:58:24 UTC, Timon Gehr wrote:
[...]
 Indeed but I'd go even further by integrating it with ranges 
 so that
 ranges would provide an opApply like method e.g.
 auto r = BinaryTree!T.preOrder(); // returns range
 r.each( (T elem) { ...use elem...}); // each method a-la Ruby
Well, I don't think this is better than built-in foreach (with full break and continue and goto even for user-defined opApply!)
I think we reached a matter of taste here. How often do you use these features anyway in your regular code? I prefer a more functional style with higher order functions (map/reduce/filter/etc..) so for me foreach is about applying something to all elements and doesn't entail usage of break/continue/etc.. I'll use these constructs in a for loop but not a foreach loop.
 * enum - enum should be completely redesigned to only 
 implement
 what it's named after: enumerations.
What is the benefit?
On the one hand the current enum for manifest constants is a hack due to weaknesses of the toolchain
I think that is actually not true. It might have been the original motivation, but it has gone beyond that. Which weaknesses in particular? I don't think that the toolchain can be improved in any way in this regard.
The weakness as far as I know is about link time optimization of constants. But regardless, my ideal implementation of so called "compile-time" features, including compile time constants, would be very different anyway.
 and on the other hand it doesn't provide
 properly encapsulated enums
Those could in theory be added without removing the manifest constant usage.
 such as for instance the Java 5.0 ones or
 the functional kind.
An algebraic data type is not an 'enumeration', so this is a moot point.
I disagree. They are a generalization of the concept. In fact, functional languages such as ML implement c style enums as an algebraic data type.
[...]

 I should be able to use a *very* minimalistic system to write 
 completely
 _regular_ D code and run it at different times.
Examples in concrete syntax? How would you replace eg. string mixin functionality?
 This is a simple matter
 of separation of concerns: what we want to execute (what code) 
 is
 separate to the concern of when we want to execute it.
It is not. For example, code that is only executed during CTFE does never have to behave gracefully if the input is ill-formed.
I disagree - you should make sure the input is valid or all sorts of bad things could potentially happen such as a compiler can get stuck in an infinite loop. If you only use a batch mode compiler you can simply kill the process which btw applies just the same to your user program. However, if you use an integrated compiler in your IDE that could cause me to lose part of my work if the IDE crashes.
Apr 29 2012
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 04/29/2012 11:31 AM, foobar wrote:
 On Sunday, 29 April 2012 at 08:58:24 UTC, Timon Gehr wrote:
 [...]
 Indeed but I'd go even further by integrating it with ranges so that
 ranges would provide an opApply like method e.g.
 auto r = BinaryTree!T.preOrder(); // returns range
 r.each( (T elem) { ...use elem...}); // each method a-la Ruby
Well, I don't think this is better than built-in foreach (with full break and continue and goto even for user-defined opApply!)
I think we reached a matter of taste here.
Certainly, and this applies to the other issues as well.
 How often do you use these features anyway in your regular code?
Not too often, but it is awesome that it actually works. ;)
 I prefer a more functional style
 with higher order functions (map/reduce/filter/etc..) so for me foreach
 is about applying something to all elements and doesn't entail usage of
 break/continue/etc..
Some algorithms are better expressed in functional terms, some algorithms are better expressed in imperative terms. I think a combination of the two usually is the best choice.
 I'll use these constructs in a for loop but not a foreach loop.
break can be used as an optimisation to stop execution of a loop that performs a 'reduce' if the result cannot change after a certain point. I use continue mostly for 'filter'-ing out elements from consideration. Usually there is not a huge difference between imperative style and functional style loops.
 * enum - enum should be completely redesigned to only implement
 what it's named after: enumerations.
What is the benefit?
On the one hand the current enum for manifest constants is a hack due to weaknesses of the toolchain
I think that is actually not true. It might have been the original motivation, but it has gone beyond that. Which weaknesses in particular? I don't think that the toolchain can be improved in any way in this regard.
The weakness as far as I know is about link time optimization of constants. But regardless, my ideal implementation of so called "compile-time" features, including compile time constants, would be very different anyway.
Well, you never elaborate on these things. BTW, what is your stance on template haskell?
 and on the other hand it doesn't provide
 properly encapsulated enums
Those could in theory be added without removing the manifest constant usage.
 such as for instance the Java 5.0 ones or
 the functional kind.
An algebraic data type is not an 'enumeration', so this is a moot point.
I disagree. They are a generalization of the concept. In fact, functional languages such as ML implement c style enums as an algebraic data type.
The current way enums can be used as manifest constants is a generalization as well. The generalization takes place on the static semantics level instead of on the conceptual level though.
 [...]

 I should be able to use a *very* minimalistic system to write completely
 _regular_ D code and run it at different times.
Examples in concrete syntax? How would you replace eg. string mixin functionality?
?
 This is a simple matter
 of separation of concerns: what we want to execute (what code) is
 separate to the concern of when we want to execute it.
It is not. For example, code that is only executed during CTFE does never have to behave gracefully if the input is ill-formed.
I disagree - you should make sure the input is valid or all sorts of bad things could potentially happen such as a compiler can get stuck in an infinite loop.
It could fail in a number of other ways. I don't think that this example can be used to invalidate the statement.
 If you only use a batch mode compiler you can simply kill
 the process which btw applies just the same to your user program.
Maybe the user program should not be killed. See your IDE example.
 However, if you use an integrated compiler in your IDE that could cause
 me to lose part of my work if the IDE crashes.
Why would the IDE crash?
Apr 29 2012
next sibling parent reply "foobar" <foo bar.com> writes:
On Sunday, 29 April 2012 at 11:23:17 UTC, Timon Gehr wrote:
 On 04/29/2012 11:31 AM, foobar wrote:
 On Sunday, 29 April 2012 at 08:58:24 UTC, Timon Gehr wrote:
 [...]
 Indeed but I'd go even further by integrating it with ranges 
 so that
 ranges would provide an opApply like method e.g.
 auto r = BinaryTree!T.preOrder(); // returns range
 r.each( (T elem) { ...use elem...}); // each method a-la Ruby
Well, I don't think this is better than built-in foreach (with full break and continue and goto even for user-defined opApply!)
I think we reached a matter of taste here.
Certainly, and this applies to the other issues as well.
 How often do you use these features anyway in your regular 
 code?
Not too often, but it is awesome that it actually works. ;)
 I prefer a more functional style
 with higher order functions (map/reduce/filter/etc..) so for 
 me foreach
 is about applying something to all elements and doesn't entail 
 usage of
 break/continue/etc..
Some algorithms are better expressed in functional terms, some algorithms are better expressed in imperative terms. I think a combination of the two usually is the best choice.
I agree and indeed I haven't argued to remove break/continue from the language. Imperative style loops are already expressible with for/while/etc where break/continue work as advertizes. IMO a foreach loop is a higher level concept more suitable for functional style loops. In any case, break/continue is implemented via opApply's return values and as such doesn't require anything special from the compiler to implement a library based foreach.
 I'll use these constructs in a for loop but not a foreach loop.
break can be used as an optimisation to stop execution of a loop that performs a 'reduce' if the result cannot change after a certain point. I use continue mostly for 'filter'-ing out elements from consideration.
Well, I'll use a filter to filter out elements.... :)
 Usually there is not a huge difference between imperative style 
 and functional style loops.

 * enum - enum should be completely redesigned to only 
 implement
 what it's named after: enumerations.
What is the benefit?
On the one hand the current enum for manifest constants is a hack due to weaknesses of the toolchain
I think that is actually not true. It might have been the original motivation, but it has gone beyond that. Which weaknesses in particular? I don't think that the toolchain can be improved in any way in this regard.
The weakness as far as I know is about link time optimization of constants. But regardless, my ideal implementation of so called "compile-time" features, including compile time constants, would be very different anyway.
Well, you never elaborate on these things. BTW, what is your stance on template haskell?
I discussed this many times in the past... I don't really know haskell. But I do like ML.
 and on the other hand it doesn't provide
 properly encapsulated enums
Those could in theory be added without removing the manifest constant usage.
 such as for instance the Java 5.0 ones or
 the functional kind.
An algebraic data type is not an 'enumeration', so this is a moot point.
I disagree. They are a generalization of the concept. In fact, functional languages such as ML implement c style enums as an algebraic data type.
The current way enums can be used as manifest constants is a generalization as well. The generalization takes place on the static semantics level instead of on the conceptual level though.
A language is the interface between a human programmer and a computer and should IMO provide clear conceptual level abstractions for the benefit of the human. I realize that using enum for manifest constants makes sense on the implementation level but I feel the compiler should work for me and not the other way around.
 [...]

 I should be able to use a *very* minimalistic system to 
 write completely
 _regular_ D code and run it at different times.
Examples in concrete syntax? How would you replace eg. string mixin functionality?
?
macro testMacro() { std.writeln("Hello world!"); <| std.writeln("Hello world!"); |> } macro is a syntactic sugar on top of a regular function. You can call it just like you call a regular function. The first line is executed regularly and the second one is mixed-in [returned token stream from the macro] since the macro is evaluated by the compiler, the first line would generate compile-time output. the second line would be part of the generated code and would be thus executed during run-time of my code. Regarding syntax, the main difference is that it's a token stream and not text but otherwise pretty much the same as current CTFE. The important difference here is the execution model which is different from CTFE.
 This is a simple matter
 of separation of concerns: what we want to execute (what 
 code) is
 separate to the concern of when we want to execute it.
It is not. For example, code that is only executed during CTFE does never have to behave gracefully if the input is ill-formed.
I disagree - you should make sure the input is valid or all sorts of bad things could potentially happen such as a compiler can get stuck in an infinite loop.
It could fail in a number of other ways. I don't think that this example can be used to invalidate the statement.
 If you only use a batch mode compiler you can simply kill
 the process which btw applies just the same to your user 
 program.
Maybe the user program should not be killed. See your IDE example.
 However, if you use an integrated compiler in your IDE that 
 could cause
 me to lose part of my work if the IDE crashes.
Why would the IDE crash?
My example illustrates that the same considerations should be given to "compile-time" code as well as to the client application and it all depends on what you're trying to achieve.
Apr 29 2012
parent Timon Gehr <timon.gehr gmx.ch> writes:
On 04/29/2012 02:17 PM, foobar wrote:
 On Sunday, 29 April 2012 at 11:23:17 UTC, Timon Gehr wrote:
 break can be used as an optimisation to stop execution of a loop that
 performs a 'reduce' if the result cannot change after a certain point.
 I use continue mostly for 'filter'-ing out elements from consideration.
Well, I'll use a filter to filter out elements.... :)
The filter condition is not always conveniently expressed in terms of a lambda function.
 ...
 The current way enums can be used as manifest constants is a
 generalization as well. The generalization takes place on the static
 semantics level instead of on the conceptual level though.
A language is the interface between a human programmer and a computer and should IMO provide clear conceptual level abstractions for the benefit of the human. I realize that using enum for manifest constants makes sense on the implementation level but I feel the compiler should work for me and not the other way around.
Well, I don't think that 'enum' for manifest constants asks a lot from the programmer, but YMMV.
 ...
 macro testMacro() {
  std.writeln("Hello world!");
  <| std.writeln("Hello world!"); |>
 }

 macro is a syntactic sugar on top of a regular function. You can call it
 just like you call a regular function. The first line is executed
 regularly and the second one is mixed-in [returned token stream from the
 macro]
 since the macro is evaluated by the compiler, the first line would
 generate compile-time output. the second line would be part of the
 generated code and would be thus executed during run-time of my code.

 Regarding syntax, the main difference is that it's a token stream and
 not text but otherwise pretty much the same as current CTFE. The
 important difference here is the execution model which is different from
 CTFE.
We have the 'macro' keyword ;). Probably it should just be a built-in primitive type of the language that represents an AST?
Apr 29 2012
prev sibling parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Sun, Apr 29, 2012 at 01:23:17PM +0200, Timon Gehr wrote:
 On 04/29/2012 11:31 AM, foobar wrote:
On Sunday, 29 April 2012 at 08:58:24 UTC, Timon Gehr wrote:
[...]
It is not. For example, code that is only executed during CTFE does
never have to behave gracefully if the input is ill-formed.
I disagree - you should make sure the input is valid or all sorts of bad things could potentially happen such as a compiler can get stuck in an infinite loop.
It could fail in a number of other ways. I don't think that this example can be used to invalidate the statement.
Like if the Ackermann function was evaluated in CTFE for very large arguments. Technically it isn't an infinite loop, but you probably wouldn't like the results. T -- If I were two-faced, would I be wearing this one? -- Abraham Lincoln
Apr 29 2012
prev sibling parent reply =?UTF-8?B?QWxleCBSw7hubmUgUGV0ZXJzZW4=?= <xtzgzorex gmail.com> writes:
On 29-04-2012 01:25, foobar wrote:
 On Saturday, 28 April 2012 at 20:43:38 UTC, Timon Gehr wrote:
 On 04/28/2012 09:58 PM, foobar wrote:
 On Saturday, 28 April 2012 at 18:48:18 UTC, Walter Bright wrote:
 Andrei and I had a fun discussion last night about this question. The
 idea was which features in D are redundant and/or do not add
 significant value?

 A couple already agreed upon ones are typedef and the cfloat, cdouble
 and creal types.

 What's your list?
D has a lot of ad-hock features which make the language needlessly large and complex. I'd strive to replace these with better general purpose mechanisms. My list: * I'd start with getting rid of foreach completely. (not just foreach_reverse).
foreach is very useful. Have you actually used D?
I have used D and didn't claim that foreach isn't useful. What I said that is that it belongs in the library, NOT the language.
Yeah, we tried that in C++. It sucked. The reason it works for many functional languages is that they have even more terse syntax than D. It would suck to make foreach a function in D.
 This is nothing more than a fancy function with
 a delegate parameter.
That would be opApply.
Indeed but I'd go even further by integrating it with ranges so that ranges would provide an opApply like method e.g. auto r = BinaryTree!T.preOrder(); // returns range r.each( (T elem) { ...use elem...}); // each method a-la Ruby
 * enum - enum should be completely redesigned to only implement
 what it's named after: enumerations.
What is the benefit?
On the one hand the current enum for manifest constants is a hack due to weaknesses of the toolchain and on the other hand it doesn't provide properly encapsulated enums such as for instance the Java 5.0 ones or the functional kind.
 * version - this does not belong in a programming language. Git
 is a much better solution.
So you'd maintain a git branch for every OS if there is some small part that is OS-dependent? I don't think that is a better approach at all.
It is far better than having a pile of #ifdef styled spaghetti code. I'd expect to have all the OS specific code encapsulated separately anyway, not spread around the code base. Which is the current recommended way of using versions anyway. The inevitable conclusion would be to either use a version management system like git or have separate implementation modules for platform specific code and use the build tool to implement the logic of select the modules to include in the build.
Yeah, we tried that in C and C++. It sucked. See: Autotools.
 * di files - a library should encapsulate all the info required
 to use it. Java Jars, .Net assemblies and even old school; Pascal
 units all solved this long ago.

 * This is a big one: get rid of *all* current compile time
 special syntax.
What would that be exactly?
This includes __traits, templates, static ifs, etc..
 It should be replaced by a standard compilation
 API and the compiler should be able to use plugins/addons.
Are you serious?
No I'm joking. The current system is a pile of hacks on top of the broken model of c++ templates. I should be able to use a *very* minimalistic system to write completely _regular_ D code and run it at different times. This is a simple matter of separation of concerns: what we want to execute (what code) is separate to the concern of when we want to execute it.
 This would reduce the size of the language to half of its current
 size, maybe even more.
I am certain that it would not. You missed to present the 'general purpose mechanisms'.
-- - Alex
Apr 29 2012
parent reply "foobar" <foo bar.com> writes:
Meta comment: C++ is the spawn of the devil so I don't accept 
anything related to c++ as a valid argument.

On Sunday, 29 April 2012 at 20:09:34 UTC, Alex Rønne Petersen 
wrote:
[...]
 I have used D and didn't claim that foreach isn't useful.
 What I said that is that it belongs in the library, NOT the 
 language.
Yeah, we tried that in C++. It sucked.
See meta comment above.
 The reason it works for many functional languages is that they 
 have even more terse syntax than D. It would suck to make 
 foreach a function in D.
D wants to support functional programming. That means we should provide whatever is necessary to write functional style code including foreach methods. IF D can't properly implement a FP foreach method (And IMO it *can*) than we have failed.
 * version - this does not belong in a programming language. 
 Git
 is a much better solution.
So you'd maintain a git branch for every OS if there is some small part that is OS-dependent? I don't think that is a better approach at all.
It is far better than having a pile of #ifdef styled spaghetti code. I'd expect to have all the OS specific code encapsulated separately anyway, not spread around the code base. Which is the current recommended way of using versions anyway. The inevitable conclusion would be to either use a version management system like git or have separate implementation modules for platform specific code and use the build tool to implement the logic of select the modules to include in the build.
Yeah, we tried that in C and C++. It sucked. See: Autotools.
see meta comment above. The fact that you used a horribly designed language with a horrible mess of a "build tool" made out of shell scripts IIRC is not an indication that the language should include build-tool functionality.
Apr 30 2012
parent reply =?UTF-8?B?QWxleCBSw7hubmUgUGV0ZXJzZW4=?= <xtzgzorex gmail.com> writes:
On 30-04-2012 12:18, foobar wrote:
 Meta comment: C++ is the spawn of the devil so I don't accept anything
 related to c++ as a valid argument.

 On Sunday, 29 April 2012 at 20:09:34 UTC, Alex Rønne Petersen wrote:
 [...]
 I have used D and didn't claim that foreach isn't useful.
 What I said that is that it belongs in the library, NOT the language.
Yeah, we tried that in C++. It sucked.
See meta comment above.
 The reason it works for many functional languages is that they have
 even more terse syntax than D. It would suck to make foreach a
 function in D.
D wants to support functional programming. That means we should provide whatever is necessary to write functional style code including foreach methods. IF D can't properly implement a FP foreach method (And IMO it *can*) than we have failed.
Of course it can, but not with type inference, unless you templatize it. That is: void forEach(alias fun, R)(R range) { // ... } enjoys type inference: forEach!(item => foo(item))(myRange); But this doesn't: void forEach(R)(R range, scope void delegate(ElementType!R) dg) { // ... } This won't work: forEach(myRange, item => foo(item)); You have to do: forEach(myRange, (ElementType!(typeof(myRange)) => foo(item)); which, frankly, sucks.
 * version - this does not belong in a programming language. Git
 is a much better solution.
So you'd maintain a git branch for every OS if there is some small part that is OS-dependent? I don't think that is a better approach at all.
It is far better than having a pile of #ifdef styled spaghetti code. I'd expect to have all the OS specific code encapsulated separately anyway, not spread around the code base. Which is the current recommended way of using versions anyway. The inevitable conclusion would be to either use a version management system like git or have separate implementation modules for platform specific code and use the build tool to implement the logic of select the modules to include in the build.
Yeah, we tried that in C and C++. It sucked. See: Autotools.
see meta comment above. The fact that you used a horribly designed language with a horrible mess of a "build tool" made out of shell scripts IIRC is not an indication that the language should include build-tool functionality.
-- - Alex
Apr 30 2012
parent Timon Gehr <timon.gehr gmx.ch> writes:
On 04/30/2012 05:13 PM, Alex Rønne Petersen wrote:
 On 30-04-2012 12:18, foobar wrote:
 Meta comment: C++ is the spawn of the devil so I don't accept anything
 related to c++ as a valid argument.

 On Sunday, 29 April 2012 at 20:09:34 UTC, Alex Rønne Petersen wrote:
 [...]
 I have used D and didn't claim that foreach isn't useful.
 What I said that is that it belongs in the library, NOT the language.
Yeah, we tried that in C++. It sucked.
See meta comment above.
 The reason it works for many functional languages is that they have
 even more terse syntax than D. It would suck to make foreach a
 function in D.
D wants to support functional programming. That means we should provide whatever is necessary to write functional style code including foreach methods. IF D can't properly implement a FP foreach method (And IMO it *can*) than we have failed.
Of course it can, but not with type inference, unless you templatize it. That is: void forEach(alias fun, R)(R range) { // ... } enjoys type inference: forEach!(item => foo(item))(myRange); But this doesn't: void forEach(R)(R range, scope void delegate(ElementType!R) dg) { // ... } This won't work: forEach(myRange, item => foo(item)); You have to do: forEach(myRange, (ElementType!(typeof(myRange)) => foo(item)); which, frankly, sucks.
I agree. It is due to the fact that currently actually no inference takes place, it is just simple deduction. It shouldn't be very hard to add that functionality.
Apr 30 2012
prev sibling next sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2012-04-28 22:43, Timon Gehr wrote:
 On 04/28/2012 09:58 PM, foobar wrote:
 It should be replaced by a standard compilation
 API and the compiler should be able to use plugins/addons.
Are you serious?
Have a look at what Scala have done. They basically have the complete compiler available as a library. Then they used this library to implement runtime reflection and macros. Macros in Scala are functions that execute at compile time. -- /Jacob Carlborg
Apr 29 2012
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 04/29/2012 04:53 PM, Jacob Carlborg wrote:
 On 2012-04-28 22:43, Timon Gehr wrote:
 On 04/28/2012 09:58 PM, foobar wrote:
 It should be replaced by a standard compilation
 API and the compiler should be able to use plugins/addons.
Are you serious?
Have a look at what Scala have done. They basically have the complete compiler available as a library. Then they used this library to implement runtime reflection and macros. Macros in Scala are functions that execute at compile time.
It is not as powerful as what we have in D and it requires invoking the compiler multiple times.
Apr 29 2012
parent Jacob Carlborg <doob me.com> writes:
On 2012-04-29 18:28, Timon Gehr wrote:
 On 04/29/2012 04:53 PM, Jacob Carlborg wrote:
 On 2012-04-28 22:43, Timon Gehr wrote:
 On 04/28/2012 09:58 PM, foobar wrote:
 It should be replaced by a standard compilation
 API and the compiler should be able to use plugins/addons.
Are you serious?
Have a look at what Scala have done. They basically have the complete compiler available as a library. Then they used this library to implement runtime reflection and macros. Macros in Scala are functions that execute at compile time.
It is not as powerful as what we have in D and it requires invoking the compiler multiple times.
That's the whole point, there won't be any special case for CTFE. BTW, isn't that basically the same as having a built-in interpreter? -- /Jacob Carlborg
Apr 29 2012
prev sibling parent =?UTF-8?B?QWxleCBSw7hubmUgUGV0ZXJzZW4=?= <xtzgzorex gmail.com> writes:
On 28-04-2012 22:43, Timon Gehr wrote:
 On 04/28/2012 09:58 PM, foobar wrote:
 On Saturday, 28 April 2012 at 18:48:18 UTC, Walter Bright wrote:
 Andrei and I had a fun discussion last night about this question. The
 idea was which features in D are redundant and/or do not add
 significant value?

 A couple already agreed upon ones are typedef and the cfloat, cdouble
 and creal types.

 What's your list?
D has a lot of ad-hock features which make the language needlessly large and complex. I'd strive to replace these with better general purpose mechanisms. My list: * I'd start with getting rid of foreach completely. (not just foreach_reverse).
foreach is very useful. Have you actually used D?
Removing it would be craziness.
 This is nothing more than a fancy function with
 a delegate parameter.
That would be opApply.
 * enum - enum should be completely redesigned to only implement
 what it's named after: enumerations.
What is the benefit?
 * version - this does not belong in a programming language. Git
 is a much better solution.
So you'd maintain a git branch for every OS if there is some small part that is OS-dependent? I don't think that is a better approach at all.
That is absolutely horrible. It's not how branches are meant to be used.
 * di files - a library should encapsulate all the info required
 to use it. Java Jars, .Net assemblies and even old school; Pascal
 units all solved this long ago.

 * This is a big one: get rid of *all* current compile time
 special syntax.
What would that be exactly?
 It should be replaced by a standard compilation
 API and the compiler should be able to use plugins/addons.
Are you serious?
 This would reduce the size of the language to half of its current
 size, maybe even more.
I am certain that it would not. You missed to present the 'general purpose mechanisms'.
-- - Alex
Apr 29 2012
prev sibling next sibling parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Sat, Apr 28, 2012 at 09:58:02PM +0200, foobar wrote:
[...]
 D has a lot of ad-hock features which make the language
 needlessly large and complex. I'd strive to replace these with
 better general purpose mechanisms.
 
 My list:
 * I'd start with getting rid of foreach completely. (not just
 foreach_reverse). This is nothing more than a fancy function with
 a delegate parameter.
I disagree. Having a dedicated foreach construct allows the compiler to optimize away the delegate in certain cases. I wouldn't want to incur the cost of creating and passing a delegate in something as simple as foreach (i; 0..100), for example.
 * enum - enum should be completely redesigned to only implement
 what it's named after: enumerations.
Actually, I rather like the enum idiom of declaring compile-time constants. Though it could do with a renaming to something more befitting.
 * version - this does not belong in a programming language. Git
 is a much better solution.
This is an interesting idea. But using separate git branches just for having versioned code seems a bit like total overkill... plus a maintenance nightmare since you have to continue pull and merge changes to every porting branch every time development happens. Whereas having everything represented in source means that whoever writes a new feature is also responsible for making it work with whatever versions are currently out there. After-the-fact fixes are always painful.
 * di files - a library should encapsulate all the info required
 to use it. Java Jars, .Net assemblies and even old school; Pascal
 units all solved this long ago.
I proposed a while ago that .di files should be replaced by something better: omit ALL function bodies, template bodies, private members, etc., and just keep the "real" public API in the human-readable part of the file. Function and template bodies should be kept in as a binary blob readable by the compiler (which obviously needs to know them otherwise it won't be able to expand templates). (Yes the binary blob can be reverse-engineered, but so can executables, so it's a moot point. We're not trying to write cryptographic security here, but it's nice to separate what the compiler needs to know vs. what the user of a library needs to know.)
 * This is a big one: get rid of *all* current compile time
 special syntax. It should be replaced by a standard compilation
 API and the compiler should be able to use plugins/addons. This
 would reduce the size of the language to half of its current
 size, maybe even more.
I have to disagree here. CTFE and compile-time features is a major reason I like D. I argue rather that compile-time features should be *improved*. The current situation is good, but not quite there yet. It can be made better. T -- Be in denial for long enough, and one day you'll deny yourself of things you wish you hadn't.
Apr 28 2012
next sibling parent reply "foobar" <foo bar.com> writes:
On Saturday, 28 April 2012 at 21:02:25 UTC, H. S. Teoh wrote:
 [...]
 I disagree. Having a dedicated foreach construct allows the 
 compiler to
 optimize away the delegate in certain cases. I wouldn't want to 
 incur
 the cost of creating and passing a delegate in something as 
 simple as
 foreach (i; 0..100), for example.
compiler inlining? There is no reason why this should be special cased for a specific redundant construct in the language. Shouldn't I enjoy similar optimization techniques when using other kinds of functions with delegate parameters?
 * enum - enum should be completely redesigned to only implement
 what it's named after: enumerations.
Actually, I rather like the enum idiom of declaring compile-time constants. Though it could do with a renaming to something more befitting.
 * version - this does not belong in a programming language. Git
 is a much better solution.
This is an interesting idea. But using separate git branches just for having versioned code seems a bit like total overkill... plus a maintenance nightmare since you have to continue pull and merge changes to every porting branch every time development happens. Whereas having everything represented in source means that whoever writes a new feature is also responsible for making it work with whatever versions are currently out there. After-the-fact fixes are always painful.
 * di files - a library should encapsulate all the info required
 to use it. Java Jars, .Net assemblies and even old school; 
 Pascal
 units all solved this long ago.
I proposed a while ago that .di files should be replaced by something better: omit ALL function bodies, template bodies, private members, etc., and just keep the "real" public API in the human-readable part of the file. Function and template bodies should be kept in as a binary blob readable by the compiler (which obviously needs to know them otherwise it won't be able to expand templates). (Yes the binary blob can be reverse-engineered, but so can executables, so it's a moot point. We're not trying to write cryptographic security here, but it's nice to separate what the compiler needs to know vs. what the user of a library needs to know.)
I agree with the general notion here. Whatever the actual implementation details are, the API should be strongly tied to the binary in order to insure consistency and ease of use. I shouldn't need to worry if the header files match the binary library. Regarding the human readable API - that's why we have documentation for.
 * This is a big one: get rid of *all* current compile time
 special syntax. It should be replaced by a standard compilation
 API and the compiler should be able to use plugins/addons. This
 would reduce the size of the language to half of its current
 size, maybe even more.
I have to disagree here. CTFE and compile-time features is a major reason I like D. I argue rather that compile-time features should be *improved*. The current situation is good, but not quite there yet. It can be made better. T
Please see my other reply to Timor. "compile-time" is simply the run-time of the compiler and shouldn't require any special syntax. E.g. D currently requires me to use pragma to output a message during compilation whereas I think it would be much cleaner to simply use writeln() in a component loaded and run by the compiler during compilation of my target code.
Apr 28 2012
parent reply "Era Scarecrow" <rtcvb32 yahoo.com> writes:
On Saturday, 28 April 2012 at 23:50:22 UTC, foobar wrote:
 On Saturday, 28 April 2012 at 21:02:25 UTC, H. S. Teoh wrote:
 * di files - a library should encapsulate all the info 
 required
 to use it. Java Jars, .Net assemblies and even old school; 
 Pascal
 units all solved this long ago.
 I agree with the general notion here. Whatever the actual 
 implementation details are, the API should be strongly tied to 
 the binary in order to insure consistency and ease of use. I 
 shouldn't need to worry if the header files match the binary 
 library. Regarding the human readable API - that's why we have 
 documentation for.
Mmm well the main reason I see using .di files, is cases when the input library/file/dll doesn't give you much or any information. like... most dll's today. There's also tools to strip that extra debugging and structure information from your output file, so if you distribute a binary only, you still need to include it's .h file or .di file. Cases where this would be far more relevant could be in systems that don't have a lot of room (mini-distros or recovery disks for example). I've seen a recovery disk distro with everything you needed 2 floppies disks. Only reason I don't use floppies anymore is the ones being made are crap and don't keep data where as 14 years ago I could accidentally put mine through the wash and still access it's contents. (Cheap bastards)
Apr 28 2012
parent reply "foobar" <foo bar.com> writes:
On Sunday, 29 April 2012 at 00:40:01 UTC, Era Scarecrow wrote:
 On Saturday, 28 April 2012 at 23:50:22 UTC, foobar wrote:
 On Saturday, 28 April 2012 at 21:02:25 UTC, H. S. Teoh wrote:
 * di files - a library should encapsulate all the info 
 required
 to use it. Java Jars, .Net assemblies and even old school; 
 Pascal
 units all solved this long ago.
 I agree with the general notion here. Whatever the actual 
 implementation details are, the API should be strongly tied to 
 the binary in order to insure consistency and ease of use. I 
 shouldn't need to worry if the header files match the binary 
 library. Regarding the human readable API - that's why we have 
 documentation for.
Mmm well the main reason I see using .di files, is cases when the input library/file/dll doesn't give you much or any information. like... most dll's today. There's also tools to strip that extra debugging and structure information from your output file, so if you distribute a binary only, you still need to include it's .h file or .di file. Cases where this would be far more relevant could be in systems that don't have a lot of room (mini-distros or recovery disks for example). I've seen a recovery disk distro with everything you needed 2 floppies disks. Only reason I don't use floppies anymore is the ones being made are crap and don't keep data where as 14 years ago I could accidentally put mine through the wash and still access it's contents. (Cheap bastards)
floppies, are you for real?! This is only relevant if you travel a decade or so back in time. The current generation dvd/Blu-ray discs and USB sticks aren't good enough for you?
Apr 29 2012
parent "Era Scarecrow" <rtcvb32 yahoo.com> writes:
On Sunday, 29 April 2012 at 07:00:51 UTC, foobar wrote:
 floppies, are you for real?!
 This is only relevant if you travel a decade or so back in time.
 The current generation dvd/Blu-ray discs and USB sticks aren't 
 good enough for you?
What? I like my floppies... or did when they worked. Depends on what I'm doing; I mean a meg is a lot of space if your primarily doing text and using compression. But I accept it is an old technology and won't be coming back.
Apr 29 2012
prev sibling parent "Adam Wilson" <flyboynw gmail.com> writes:
On Sat, 28 Apr 2012 14:03:26 -0700, H. S. Teoh <hsteoh quickfur.ath.cx>  
wrote:

 On Sat, Apr 28, 2012 at 09:58:02PM +0200, foobar wrote:
 [...]
 D has a lot of ad-hock features which make the language
 needlessly large and complex. I'd strive to replace these with
 better general purpose mechanisms.

 My list:
 * I'd start with getting rid of foreach completely. (not just
 foreach_reverse). This is nothing more than a fancy function with
 a delegate parameter.
I disagree. Having a dedicated foreach construct allows the compiler to optimize away the delegate in certain cases. I wouldn't want to incur the cost of creating and passing a delegate in something as simple as foreach (i; 0..100), for example.
 * enum - enum should be completely redesigned to only implement
 what it's named after: enumerations.
Actually, I rather like the enum idiom of declaring compile-time constants. Though it could do with a renaming to something more befitting.
 * version - this does not belong in a programming language. Git
 is a much better solution.
This is an interesting idea. But using separate git branches just for having versioned code seems a bit like total overkill... plus a maintenance nightmare since you have to continue pull and merge changes to every porting branch every time development happens. Whereas having everything represented in source means that whoever writes a new feature is also responsible for making it work with whatever versions are currently out there. After-the-fact fixes are always painful.
 * di files - a library should encapsulate all the info required
 to use it. Java Jars, .Net assemblies and even old school; Pascal
 units all solved this long ago.
I proposed a while ago that .di files should be replaced by something better: omit ALL function bodies, template bodies, private members, etc., and just keep the "real" public API in the human-readable part of the file. Function and template bodies should be kept in as a binary blob readable by the compiler (which obviously needs to know them otherwise it won't be able to expand templates).
I have written code that will do just that. You can check it out here: https://github.com/LightBender/dmd.git. It builds both the DRuntime and Phobos perfectly, however, the Phobos makefile has not yet been updated to generate DI files. However, Phobos uses the Druntime DI files for it's build.
 (Yes the binary blob can be reverse-engineered, but so can executables,
 so it's a moot point. We're not trying to write cryptographic security
 here, but it's nice to separate what the compiler needs to know vs. what
 the user of a library needs to know.)


 * This is a big one: get rid of *all* current compile time
 special syntax. It should be replaced by a standard compilation
 API and the compiler should be able to use plugins/addons. This
 would reduce the size of the language to half of its current
 size, maybe even more.
I have to disagree here. CTFE and compile-time features is a major reason I like D. I argue rather that compile-time features should be *improved*. The current situation is good, but not quite there yet. It can be made better. T
-- Adam Wilson IRC: LightBender Project Coordinator The Horizon Project http://www.thehorizonproject.org/
Apr 28 2012
prev sibling next sibling parent Jacob Carlborg <doob me.com> writes:
On 2012-04-28 21:58, foobar wrote:

 D has a lot of ad-hock features which make the language
 needlessly large and complex. I'd strive to replace these with
 better general purpose mechanisms.

 My list:
 * I'd start with getting rid of foreach completely. (not just
 foreach_reverse). This is nothing more than a fancy function with
 a delegate parameter.
I agree.
 * This is a big one: get rid of *all* current compile time
 special syntax. It should be replaced by a standard compilation
 API and the compiler should be able to use plugins/addons. This
 would reduce the size of the language to half of its current
 size, maybe even more.
I agree with this one as well. At least if the compiler would be implemented like this. -- /Jacob Carlborg
Apr 29 2012
prev sibling parent "akaz" <nemo utopia.com> writes:
On Saturday, 28 April 2012 at 19:58:03 UTC, foobar wrote:
 * di files - a library should encapsulate all the info required
 to use it. Java Jars, .Net assemblies and even old school; 
 Pascal
 units all solved this long ago.
I strongly support this.
Apr 29 2012
prev sibling next sibling parent reply "bearophile" <bearophileHUGS lycos.com> writes:
Walter:

 which features in D are redundant and/or do not add significant 
 value?
...
 What's your list?
Finding things to remove now from D is hard, in my code I have used most D features now. And many suggestions I have seen in this thread are very bad, like removing foreach_reverse (that I use often), or "Phobos is too fat" (that is the opposite of what I'd like, I'd like D with more batteries). The features I have not used in my programs so far are: 1) Typesafe Variadic Functions for class objects (never used so far). 2) >>>= >>> (Never used so far). 3) Floating point comparison operators (never used). 4) Delimited Strings / heredoc strings (never used so far in real code, despite Perl programmers use them now and then). 5) lazy (as function argument. I have used "lazy" in some test programs, but not in real code so far). 6) Anonymous classes (used only in demo code so far). 7) Shortened floating point literals as .6 or 6. Other things that I don't like: 1) Mixed C/D array declarations (http://d.puremagic.com/issues/show_bug.cgi?id=5807 ) 2) I'd like to disallow (or fix!) default arguments of out and ref arguments (http://d.puremagic.com/issues/show_bug.cgi?id=5850 ). 3) Automatic joining of adjacent strings (a bug-prone anti-feature: ["red" "green", "blue"]). 4) Comma operator, it gives more troubles than flexibility. 5) The most complex parts of the is() syntax (to be replaced with other things). 6) Two kinds of tuples. I'd like a single tuple type in a language, but I understand this is hard to do. ------------------------- I'd also like to see some limits removed like: struct Foo {} void main() { auto f = new Foo; // currently not accepted, silly } BigInt x; switch (x) { case BigInt(0): break; default: } And I'd like some features added/improved, like: - tuple unpacking syntax; - computed gotos; - a static foreach (http://d.puremagic.com/issues/show_bug.cgi?id=4085 ); - attribute hiding error or warning (http://d.puremagic.com/issues/show_bug.cgi?id=5187 ); - safer typesafe variadics (http://d.puremagic.com/issues/show_bug.cgi?id=5212 ); - Named arguments; And few other things. Bye, bearophile
Apr 28 2012
next sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 4/28/2012 1:00 PM, bearophile wrote:
 "Phobos is too fat"
As opposed to Phobos being phat?
Apr 28 2012
parent reply "q66" <quaker66 gmail.com> writes:
On Saturday, 28 April 2012 at 20:04:11 UTC, Walter Bright wrote:
 On 4/28/2012 1:00 PM, bearophile wrote:
 "Phobos is too fat"
As opposed to Phobos being phat?
Well my concern is so that it doesn't end up like Python standard library, half-bitrotting and half-crap :) Huge standard library is not a good idea even for a very big language/library team, and D doesn't have one.
Apr 28 2012
parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Sat, Apr 28, 2012 at 10:07:54PM +0200, q66 wrote:
 On Saturday, 28 April 2012 at 20:04:11 UTC, Walter Bright wrote:
On 4/28/2012 1:00 PM, bearophile wrote:
"Phobos is too fat"
As opposed to Phobos being phat?
Well my concern is so that it doesn't end up like Python standard library, half-bitrotting and half-crap :) Huge standard library is not a good idea even for a very big language/library team, and D doesn't have one.
On the contrary, being able to do stuff without having to reinvent the square wheel every single time is a big plus. I used to have a strong NIH attitude -- years ago during my DOS days, I reimplemented video output routines in assembly because I wanted to use protected mode in DOS. Nothing in the C standard library worked because they are all tied to DOS or otherwise do stuff that breaks in protected mode. So I reinvented file abstractions, string processing, etc., in my own library. I was rather proud of it too: my video routines took advantage of features of my particular chosen video mode, so I could use the i386's built-in loop instructions and other such things to output characters really fast. In retrospect, it was a fun and very educational experience. But to be frank, you can only reinvent the C standard library so many times before you get totally sick and tired of it. I mean, I've implemented linked lists, hand-made lexers, parsers, etc., who knows how many times, and nowadays the thought of having to do it all over again just makes me feel, "I should be doing better things with my time". The whole point of a standard library is that if somebody has written that code before, and it's general enough for everyday use, then you shouldn't need to download this, install that, configure the other, before you can use it. It's a major plus if you're publishing code to be able to say, just download my sources and compile it with the language standard library and it will all work. As opposed to, if you want to compile my code, you need library X and Y which depend on W and Z, all of which have to be downloaded from different places all over the 'net and you better make sure you get the right versions otherwise everything will break. Besides, the whole point of a library is that only what you need is actually linked in. You don't walk around carrying every book from your bookshelf just because you *might* need to refer to one of them on some rare occasion. But the library itself doesn't need to be minimal, in fact, rather to the contrary. (That's why it's called a "library".) T -- Latin's a dead language, as dead as can be; it killed off all the Romans, and now it's killing me! -- Schoolboy
Apr 28 2012
next sibling parent reply "q66" <quaker66 gmail.com> writes:
On Saturday, 28 April 2012 at 21:19:00 UTC, H. S. Teoh wrote:
 On Sat, Apr 28, 2012 at 10:07:54PM +0200, q66 wrote:
 On Saturday, 28 April 2012 at 20:04:11 UTC, Walter Bright 
 wrote:
On 4/28/2012 1:00 PM, bearophile wrote:
"Phobos is too fat"
As opposed to Phobos being phat?
Well my concern is so that it doesn't end up like Python standard library, half-bitrotting and half-crap :) Huge standard library is not a good idea even for a very big language/library team, and D doesn't have one.
On the contrary, being able to do stuff without having to reinvent the square wheel every single time is a big plus. I used to have a strong NIH attitude -- years ago during my DOS days, I reimplemented video output routines in assembly because I wanted to use protected mode in DOS. Nothing in the C standard library worked because they are all tied to DOS or otherwise do stuff that breaks in protected mode. So I reinvented file abstractions, string processing, etc., in my own library. I was rather proud of it too: my video routines took advantage of features of my particular chosen video mode, so I could use the i386's built-in loop instructions and other such things to output characters really fast. In retrospect, it was a fun and very educational experience. But to be frank, you can only reinvent the C standard library so many times before you get totally sick and tired of it. I mean, I've implemented linked lists, hand-made lexers, parsers, etc., who knows how many times, and nowadays the thought of having to do it all over again just makes me feel, "I should be doing better things with my time". The whole point of a standard library is that if somebody has written that code before, and it's general enough for everyday use, then you shouldn't need to download this, install that, configure the other, before you can use it. It's a major plus if you're publishing code to be able to say, just download my sources and compile it with the language standard library and it will all work. As opposed to, if you want to compile my code, you need library X and Y which depend on W and Z, all of which have to be downloaded from different places all over the 'net and you better make sure you get the right versions otherwise everything will break. Besides, the whole point of a library is that only what you need is actually linked in. You don't walk around carrying every book from your bookshelf just because you *might* need to refer to one of them on some rare occasion. But the library itself doesn't need to be minimal, in fact, rather to the contrary. (That's why it's called a "library".) T
Well I'm not obviously saying the features should disappear, what I had in mind was some kind of distribution system for small packages, kinda like luaforge or CPAN, where everyone could find what they need for their project. But keep Phobos itself small.
Apr 28 2012
parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Sat, Apr 28, 2012 at 11:21:52PM +0200, q66 wrote:
[...]
 Well I'm not obviously saying the features should disappear, what I
 had in mind was some kind of distribution system for small packages,
 kinda like luaforge or CPAN, where everyone could find what they need
 for their project. But keep Phobos itself small.
If you're talking about very specific, niche features (like parsing protein structure data files), then I agree they should be distributed in separate libraries. But generic stuff that can be used in a wide array of tasks should go in the standard library. Again I say, being able to distribute your sources without requiring the user to download 50 different libraries just to compile it, is a big plus to me. Being able to say "just compile with the standard library" is best, because it means people can just download my code and compile it immediately. Same goes for binary distribution: it's much much better to say "here, just download this binary and run it with the language standard library" than to say "download this binary, then library X, then library Y, then library Z which is needed by library X, then library W needed by ...". T -- Freedom of speech: the whole world has no right *not* to hear my spouting off!
Apr 28 2012
prev sibling parent "Era Scarecrow" <rtcvb32 yahoo.com> writes:
On Saturday, 28 April 2012 at 21:19:00 UTC, H. S. Teoh wrote:
 On Sat, Apr 28, 2012 at 10:07:54PM +0200, q66 wrote:
 On Saturday, 28 April 2012 at 20:04:11 UTC, Walter Bright
The whole point of a standard library is that if somebody has written that code before, and it's general enough for everyday use, then you shouldn't need to download this, install that, configure the other, before you can use it. It's a major plus if you're publishing code to be able to say, just download my sources and compile it with the language standard library and it will all work. As opposed to, if you want to compile my code, you need library X and Y which depend on W and Z, all of which have to be downloaded from different places all over the 'net and you better make sure you get the right versions otherwise everything will break.
OMG I love you :) A long time ago when I began programming I came to a distinct conclusion that anything I write has to be able to compile and just work with only the standard library. I don't want to make people go out of their way to get this or that. * If you have something that requires multimedia, then fine a library will help. * If you have to have something that does translations between other languages and makes sense, then use it. But for everything that's just basic work processing and otherwise, there is no reason you should have an external library used. Need compression? If the standard library (like C) doesn't include something, then what do you choose? LZMA? lzop? gzip/zlib? bzip2? Depends on how heavy duty you need. If a basic compression is included then you will use it unless you REALLY need the extra speed or compression ratio. "Make everything as simple as possible, but no simpler." -- Albert Einstein
Apr 28 2012
prev sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Saturday, April 28, 2012 22:00:52 bearophile wrote:
 2) I'd like to disallow (or fix!) default arguments of out and
 ref arguments (http://d.puremagic.com/issues/show_bug.cgi?id=5850
 ).
If the changes to ref and const ref that were discussed during the beta are fully fleshed out and implemented, then it'll be perfectly legal to pass a temporary value to a ref in many cases (if not in general), in which case having them take a default argument wouldn't be a problem at all. But as long as ref can't take temporaries, having it take a default argument makes no sense at all.
 3) Automatic joining of adjacent strings (a bug-prone
 anti-feature: ["red" "green", "blue"]).
Agreed. - Jonathan M Davis
Apr 28 2012
prev sibling next sibling parent reply "bearophile" <bearophileHUGS lycos.com> writes:
On Saturday, 28 April 2012 at 18:48:18 UTC, Walter Bright wrote:
 Andrei and I had a fun discussion last night about this 
 question. The idea was which features in D are redundant and/or 
 do not add significant value?
A more general answer. From my experience the real problem with language features is not their high number, because I am able to learn hundreds of them well. The main problem comes from bad/broken interaction between features, hard to see side effects of features, and so on. Bye, bearophile
Apr 28 2012
parent "David Piepgrass" <qwertie256 gmail.com> writes:
forum.dlang.org apparently failed to post this 10 minutes ago, 
retrying.

On Tuesday, 10 July 2012 at 02:43:05 UTC, Era Scarecrow wrote:
 On Tuesday, 10 July 2012 at 01:41:29 UTC, bearophile wrote:
 David Piepgrass:
 This use case is pretty complex, so if I port this to D, I'd 
 probably just cast away const/immutable where necessary.
You are not the first person that says similar things. So D docs need to stress more than casting away const/immutable in D is rather more dangerous than doing the same thing in C++.
...
  Let's say a class/struct is a book with Page protectors 
 signifying 'const(ant)'. You promise to return the book to the 
 library without making any changes; Although you promised you 
 wouldn't make changes, you still take the Page protectors off 
 and make make notes on the outer edges or make adjustments in 
 the text, then return the book.

  Is this wise? This isn't C++. If something shouldn't change, 
 then don't change it god damn it. If it needs to change it 
 isn't const(ant) and shouldn't suggest it is.
The difficulty, in case you missed it, is that somebody else (the Object class) says that certain functions are const, but in certain cases we really, really want to mutate something, either for efficiency or because "that's just how the data structure works". If a data structure needs to mutate itself when read, yeah, maybe its functions should not be marked const, but quite often the "const" is inherited from Object or some interface that (quite reasonably, it would seem) expects functions that /read stuff/ to be const. And yet we can't drop const from Object or such interfaces, because there is other code elsewhere that /needs/ const to be there. So far I have no solution to the dilemma in mind, btw. But the idea someone had of providing two (otherwise identical) functions, one const and one non-const, feels like a kludge to me, and note that anybody with an object would expect to be able to call the const version on any Object.
 Seriously, it's not that hard a concept. I guess if something 
 doesn't port well from C++ then redesign it. Some things done 
 in C++ are hacks due to the language's limitations and faults.
My particular data structure (a complex beast) contains a mutable tree of arbitrary size, which the user can convert to a conceptually immutable tree in O(1) time by calling Clone(). This marks a flag in the root node that says "read-only! do not change" and shares the root between the clones. At this point it should be safe to cast the clone to immutable. However, the original, mutable-typed version still exists. As the user requests changes to the mutable copy in the future, parts of the tree are duplicated to avoid changing the immutable nodes, with one exception: the read-only flag in various parts of the original, immutable tree will gradually be set to true. In this case, I don't think the D type system could do anything to help ensure that I don't modify the original tree that is supposed to be immutable. Since the static type of internal references must either be all mutable or all immutable, they will be typed mutable in the mutable copy, and immutable in the immutable copy, even though the two copies are sharing the same memory. And one flag, the read-only flag, must be mutable in this data structure, at least the transition from false->true must happen *after* the immutable copy is created; otherwise, Clone() would have to run in O(N) time, to mark every node read-only. This fact, however, does not affect the immutable copy in any way.
Jul 10 2012
prev sibling next sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 04/28/2012 08:47 PM, Walter Bright wrote:
 Andrei and I had a fun discussion last night about this question. The
 idea was which features in D are redundant and/or do not add significant
 value?

 A couple already agreed upon ones are typedef and the cfloat, cdouble
 and creal types.

 What's your list?
- Associative array literals as non-associative array initializers [1] - C style array declarations [2] - 'align' declaration [3] - 'synchronized' [4] - special treatment of built-in types during parsing [5] - the arcane restrictions on which exact kind of argument can be used to substitute which kind of template parameter I think all other language features are useful and except for new instance.Class and 'this' template parameters, I think they all occur in my code. (But those would certainly come in handy for a somewhat more OO-like style of programming.) (There are a few features that I'd like to give a (mostly syntactic) overhaul, but that is not what is discussed here.) Explanations: [1] Actually I think the functionality is very useful, but the syntax is probably confusing for many fellow D programmers. CTFE should enable a library implementation. [2] They violate the 'same syntax, same behaviour' rule, and they don't add a lot of value. [3] I have not understood until now what exactly the guarantees are that it gives, so take this with a grain of salt. I know that it is not useful as implemented DMD for typical alignment tasks, and that GDC implements different semantics. Can you explain to me what it is useful for? [4] It adds memory overhead for the monitor to every single class, even though most classes are explicitly _typed_ as unshared. [5] It is for example impossible to directly string mixin "int".
Apr 28 2012
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 04/28/2012 10:24 PM, Timon Gehr wrote:
 On 04/28/2012 08:47 PM, Walter Bright wrote:
 Andrei and I had a fun discussion last night about this question. The
 idea was which features in D are redundant and/or do not add significant
 value?

 A couple already agreed upon ones are typedef and the cfloat, cdouble
 and creal types.

 What's your list?
- Associative array literals as non-associative array initializers [1] - C style array declarations [2] - 'align' declaration [3] - 'synchronized' [4] - special treatment of built-in types during parsing [5] - the arcane restrictions on which exact kind of argument can be used to substitute which kind of template parameter
Oh, completely forgot about that one: - 'in' operator returning a pointer to the element.
Apr 28 2012
next sibling parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Sun, Apr 29, 2012 at 12:39:03AM +0200, Timon Gehr wrote:
 On 04/28/2012 10:24 PM, Timon Gehr wrote:
On 04/28/2012 08:47 PM, Walter Bright wrote:
Andrei and I had a fun discussion last night about this question. The
idea was which features in D are redundant and/or do not add significant
value?

A couple already agreed upon ones are typedef and the cfloat, cdouble
and creal types.

What's your list?
- Associative array literals as non-associative array initializers [1] - C style array declarations [2] - 'align' declaration [3] - 'synchronized' [4] - special treatment of built-in types during parsing [5] - the arcane restrictions on which exact kind of argument can be used to substitute which kind of template parameter
Oh, completely forgot about that one: - 'in' operator returning a pointer to the element.
Yeah that one elicited a WAT from me when I first started using it. Surprisingly enough, it sounded OK when I read it in TDPL, but when I started using it I realized just how b0rken it is. T -- People tell me that I'm paranoid, but they're just out to get me.
Apr 28 2012
parent reply =?ISO-8859-1?Q?Alex_R=F8nne_Petersen?= <xtzgzorex gmail.com> writes:
On 29-04-2012 00:49, H. S. Teoh wrote:
 On Sun, Apr 29, 2012 at 12:39:03AM +0200, Timon Gehr wrote:
 On 04/28/2012 10:24 PM, Timon Gehr wrote:
 On 04/28/2012 08:47 PM, Walter Bright wrote:
 Andrei and I had a fun discussion last night about this question. The
 idea was which features in D are redundant and/or do not add significant
 value?

 A couple already agreed upon ones are typedef and the cfloat, cdouble
 and creal types.

 What's your list?
- Associative array literals as non-associative array initializers [1] - C style array declarations [2] - 'align' declaration [3] - 'synchronized' [4] - special treatment of built-in types during parsing [5] - the arcane restrictions on which exact kind of argument can be used to substitute which kind of template parameter
Oh, completely forgot about that one: - 'in' operator returning a pointer to the element.
Yeah that one elicited a WAT from me when I first started using it. Surprisingly enough, it sounded OK when I read it in TDPL, but when I started using it I realized just how b0rken it is. T
How so? It's seemed entirely reasonable to me. -- - Alex
Apr 29 2012
parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Sun, Apr 29, 2012 at 10:21:19PM +0200, Alex Rønne Petersen wrote:
 On 29-04-2012 00:49, H. S. Teoh wrote:
On Sun, Apr 29, 2012 at 12:39:03AM +0200, Timon Gehr wrote:
[...]
- 'in' operator returning a pointer to the element.
Yeah that one elicited a WAT from me when I first started using it. Surprisingly enough, it sounded OK when I read it in TDPL, but when I started using it I realized just how b0rken it is.
[...]
 
 How so? It's seemed entirely reasonable to me.
[...] I was expecting it to return bool. It also precludes bool-valued AA's from being implemented using bit arrays, since you can't return a pointer to a bit. T -- In order to understand recursion you must first understand recursion.
Apr 29 2012
prev sibling next sibling parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On Sunday, April 29, 2012 00:39:03 Timon Gehr wrote:
 Oh, completely forgot about that one:
 
 - 'in' operator returning a pointer to the element.
Really? I use that all the time with AAs. Without that, you would have to do two lookups to get an object which might not be in the container, so it would be less efficient. I'd hate it if in stopped returning a pointer. We'd just have to add some other function which does the exact same thing as in now, and then I'd use in a _lot_ less. - Jonathan M Davis
Apr 28 2012
parent reply "bearophile" <bearophileHUGS lycos.com> writes:
Jonathan M Davis:

 - 'in' operator returning a pointer to the element.
Really? I use that all the time with AAs. Without that, you would have to do two lookups to get an object which might not be in the container, so it would be less efficient.
LDC1 compiler introduced a small optimization, it looks for nearby associative array lookups and removes the second of them where possible. In my code I have seen this frees me to use "in" nearby followed by [], with the same efficiency of a single AA lookup. With this small optimization, D "in" is free to return a more clean boolean. This optimization doesn't work if you want to store the pointer returned by "in" to use it later, but in my code this pattern doesn't happen, I think it's quite uncommon. Java/JavaScript/Lua show that the language design has to focus on what's hard to optimize away for the compiler, like offering ways to the programmer to specify higher level semantics (like asserting: foo(a,b) is equal to foo(b,a)), instead of focusing on what a not dumb static compiler (not even a JIT) is able to optimize away. Bye, bearophile
Apr 28 2012
parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On Sunday, April 29, 2012 01:42:05 bearophile wrote:
 Jonathan M Davis:
 - 'in' operator returning a pointer to the element.
Really? I use that all the time with AAs. Without that, you would have to do two lookups to get an object which might not be in the container, so it would be less efficient.
LDC1 compiler introduced a small optimization, it looks for nearby associative array lookups and removes the second of them where possible. In my code I have seen this frees me to use "in" nearby followed by [], with the same efficiency of a single AA lookup. With this small optimization, D "in" is free to return a more clean boolean.
I really don't see anything "unclean" about returing a pointer. It does the job fantastically, and you can use it in conditional expressions just like you would use a bool. Also, while it may work for the most part, I'd be very skeptical about the compiler being able to optimize out lookups as well as simply using in would - especially in cases where you don't immediately use the pointer.
 This optimization doesn't work if you want to store the pointer
 returned by "in" to use it later, but in my code this pattern
 doesn't happen, I think it's quite uncommon.
Storing it for later use within the function is quite common. Storing it in a member variable or the like should be _very_ uncommon, since it's almost always a bad idea. But even just storing it in a local variable to use later could destroy the locality enough to defeat LDC's optimization. - Jonathan M Davis
Apr 28 2012
parent reply "David Nadlinger" <see klickverbot.at> writes:
On Saturday, 28 April 2012 at 23:51:43 UTC, Jonathan M Davis 
wrote:
 But even just storing it in a local variable to use later
 could destroy the locality enough to defeat LDC's optimization.
Huh? I can't think of a situation where a hash table lookup would entail less indirections than dereferencing a pointer stored in a register (resp. the stack, depending on scheduling). David
Apr 29 2012
parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On Sunday, April 29, 2012 10:07:38 David Nadlinger wrote:
 On Saturday, 28 April 2012 at 23:51:43 UTC, Jonathan M Davis
 
 wrote:
 But even just storing it in a local variable to use later
 could destroy the locality enough to defeat LDC's optimization.
Huh? I can't think of a situation where a hash table lookup would entail less indirections than dereferencing a pointer stored in a register (resp. the stack, depending on scheduling).
If you have something like if(key in aa) { // lots of code func(aa[key]); } the compiler is not necessarily going to be able to determine that the AA has not been changed such that aa[key] can use the same lookup that key in aa did rather than redoing the lookup. A prime example would be if(key in aa) { foo(aa); func(aa[key]); } The compiler doesn't necessarily know that foo won't remove key from aa, so it can't save the result of key in aa to reuse rather than calling aa[key], whereas the programmer could know that foo doesn't do anything to aa which would make a pointer to the element invalid and can guarantee that only one lookup occurs by doing if(auto value = key in aa) { foo(aa); func(value); } And that's just one case where the compiler can't make such an optimization but the programmer can. It's _far_ better iMHO to have in return a pointer than to rely on the compiler removing extraneous lookups. - Jonathan M Davis
Apr 29 2012
next sibling parent reply "David Nadlinger" <see klickverbot.at> writes:
On Sunday, 29 April 2012 at 08:20:59 UTC, Jonathan M Davis wrote:
 The compiler doesn't necessarily know that foo won't remove key 
 from aa, so it
 can't save the result of key in aa to reuse rather than calling 
 aa[key],
 whereas the programmer could know that foo doesn't do anything 
 to aa which
 would make a pointer to the element invalid and can guarantee 
 that only one
 lookup occurs by doing
 […]
Yes, point taken, but what does this have to do with locality? David
Apr 29 2012
parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On Sunday, April 29, 2012 10:22:44 David Nadlinger wrote:
 On Sunday, 29 April 2012 at 08:20:59 UTC, Jonathan M Davis wrote:
 The compiler doesn't necessarily know that foo won't remove key
 from aa, so it
 can't save the result of key in aa to reuse rather than calling
 aa[key],
 whereas the programmer could know that foo doesn't do anything
 to aa which
 would make a pointer to the element invalid and can guarantee
 that only one
 lookup occurs by doing
 [=E2=80=A6]
=20 Yes, point taken, but what does this have to do with locality?
I think that you're thinking of something completely different about th= e term=20 locality than I meant. I meant locality in terms of how close the aa[ke= y]=20 expression was to the key in aa expression within the function - i.e. h= ow=20 local they were to each other. I may have misused the term though. I do= n't=20 know. - Jonathan M Davis
Apr 29 2012
parent "David Nadlinger" <see klickverbot.at> writes:
On Sunday, 29 April 2012 at 08:30:15 UTC, Jonathan M Davis wrote:
 On Sunday, April 29, 2012 10:22:44 David Nadlinger wrote:
 Yes, point taken, but what does this have to do with locality?
I think that you're thinking of something completely different about the term locality than I meant. I meant locality in terms of how close the aa[key] expression was to the key in aa expression within the function - i.e. how local they were to each other. I may have misused the term though. I don't know.
Okay, then it was just a misunderstanding, I thought about memory locality. David
Apr 29 2012
prev sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 04/29/2012 10:20 AM, Jonathan M Davis wrote:
 On Sunday, April 29, 2012 10:07:38 David Nadlinger wrote:
 On Saturday, 28 April 2012 at 23:51:43 UTC, Jonathan M Davis

 wrote:
 But even just storing it in a local variable to use later
 could destroy the locality enough to defeat LDC's optimization.
Huh? I can't think of a situation where a hash table lookup would entail less indirections than dereferencing a pointer stored in a register (resp. the stack, depending on scheduling).
If you have something like if(key in aa) { // lots of code func(aa[key]); } the compiler is not necessarily going to be able to determine that the AA has not been changed such that aa[key] can use the same lookup that key in aa did rather than redoing the lookup. A prime example would be if(key in aa) { foo(aa); func(aa[key]); } The compiler doesn't necessarily know that foo won't remove key from aa, so it can't save the result of key in aa to reuse rather than calling aa[key], whereas the programmer could know that foo doesn't do anything to aa which would make a pointer to the element invalid and can guarantee that only one lookup occurs by doing if(auto value = key in aa) { foo(aa); func(value); } And that's just one case where the compiler can't make such an optimization but the programmer can. It's _far_ better iMHO to have in return a pointer than to rely on the compiler removing extraneous lookups. - Jonathan M Davis
Well, what if the programmer "knows" that foo does not change 'aa', but it actually does? Then there would possibly be a segmentation fault. This implies that the 'in' operator cannot be used in safe code. (Or there would have to be a special case, that allows 'in' if the result is directly cast to bool.)
Apr 29 2012
next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Sunday, April 29, 2012 10:37:10 Timon Gehr wrote:
 Well, what if the programmer "knows" that foo does not change 'aa', but
 it actually does? Then there would possibly be a segmentation fault.
 This implies that the 'in' operator cannot be used in  safe code. (Or
 there would have to be a special case, that allows 'in' if the result is
 directly cast to bool.)
It's exactly as safe as any iterator or range which could be invalidated - both of which can occur in safe code. Any of those could blow up in entertaining ways if you use them after they've been invalidated. Pointers are considered safe. It's pointer arithmetic which isn't. - Jonathan M Davis
Apr 29 2012
prev sibling parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Sun, Apr 29, 2012 at 01:46:25AM -0700, Jonathan M Davis wrote:
 On Sunday, April 29, 2012 10:37:10 Timon Gehr wrote:
 Well, what if the programmer "knows" that foo does not change 'aa',
 but it actually does? Then there would possibly be a segmentation
 fault.  This implies that the 'in' operator cannot be used in  safe
 code. (Or there would have to be a special case, that allows 'in' if
 the result is directly cast to bool.)
It's exactly as safe as any iterator or range which could be invalidated - both of which can occur in safe code. Any of those could blow up in entertaining ways if you use them after they've been invalidated. Pointers are considered safe. It's pointer arithmetic which isn't.
[...] I get that this discussion is about what type 'in' should return, but taking a step back, isn't it all moot because you could just use the .get() method? T -- Let's not fight disease by killing the patient. -- Sean 'Shaleh' Perry
Apr 29 2012
parent Timon Gehr <timon.gehr gmx.ch> writes:
On 04/30/2012 04:21 AM, H. S. Teoh wrote:
 On Sun, Apr 29, 2012 at 01:46:25AM -0700, Jonathan M Davis wrote:
 On Sunday, April 29, 2012 10:37:10 Timon Gehr wrote:
 Well, what if the programmer "knows" that foo does not change 'aa',
 but it actually does? Then there would possibly be a segmentation
 fault.  This implies that the 'in' operator cannot be used in  safe
 code. (Or there would have to be a special case, that allows 'in' if
 the result is directly cast to bool.)
It's exactly as safe as any iterator or range which could be invalidated - both of which can occur in safe code. Any of those could blow up in entertaining ways if you use them after they've been invalidated. Pointers are considered safe. It's pointer arithmetic which isn't.
[...] I get that this discussion is about what type 'in' should return, but taking a step back, isn't it all moot because you could just use the .get() method? T
The AA might actually contain the provided default value, so 'get' is not always a good match.
Apr 30 2012
prev sibling parent reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 4/29/12, Timon Gehr <timon.gehr gmx.ch> wrote:
 - 'in' operator returning a pointer to the element.
AFAIK this is a property of how the opIn_r function is implemented, nothing much to do with the language itself. But it does allow for some neat tricks, like: int[int] hash; hash[1] = 2; int value = *enforce(1 in hash, new Exception("1 not in hash")); assert(value == 2); or: if (auto val = 1 in hash) ...use val pointer (+ if it's a class/struct pointer you still have access to the dot syntax) else ... errors..
Apr 28 2012
next sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 04/29/2012 06:36 AM, Andrej Mitrovic wrote:
 On 4/29/12, Timon Gehr<timon.gehr gmx.ch>  wrote:
 - 'in' operator returning a pointer to the element.
AFAIK this is a property of how the opIn_r function is implemented, nothing much to do with the language itself.
Well, AAs are part of the language.
 But it does allow for some neat tricks, like:

      int[int] hash;
      hash[1] = 2;
      int value = *enforce(1 in hash, new Exception("1 not in hash"));
      assert(value == 2);
 or:
      if (auto val = 1 in hash)
          ...use val pointer (+ if it's a class/struct pointer you still
 have access to the dot syntax)
      else
          ... errors..
I know, but 'in' is somewhat of a misnomer. Anyway, it is not a huge issue.
Apr 29 2012
prev sibling parent reply =?ISO-8859-1?Q?Alex_R=F8nne_Petersen?= <xtzgzorex gmail.com> writes:
On 29-04-2012 06:36, Andrej Mitrovic wrote:
 On 4/29/12, Timon Gehr<timon.gehr gmx.ch>  wrote:
 - 'in' operator returning a pointer to the element.
AFAIK this is a property of how the opIn_r function is implemented, nothing much to do with the language itself.
I hate to nitpick and all that, but opBinaryRight!"in" actually works now. ;)
 But it does allow for some neat tricks, like:

      int[int] hash;
      hash[1] = 2;
      int value = *enforce(1 in hash, new Exception("1 not in hash"));
      assert(value == 2);
 or:
      if (auto val = 1 in hash)
          ...use val pointer (+ if it's a class/struct pointer you still
 have access to the dot syntax)
      else
          ... errors..
-- - Alex
Apr 29 2012
next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 4/29/12, Alex R=F8nne Petersen <xtzgzorex gmail.com> wrote:
 I hate to nitpick and all that, but opBinaryRight!"in" actually works
 now. ;)
Yes and then you get to have those nice template instantiation errors, which make no sense at all: struct Foo { auto opIn_r(string op)(int i) { return 1; } } struct Bar { auto opBinaryRight(string op)(int i) { return 1; } } void main() { Foo foo; auto x =3D "" in foo; Bar bar; auto y =3D "" in bar; } Foo: test.d(34): Error: template test.Foo.opIn_r does not match any function template declaration test.d(16): Error: template test.Foo.opIn_r(string op) cannot deduce template function from argument types !()(string) Bar: test.d(37): Error: rvalue of in expression must be an associative array, no= t Bar The Bar error message is completely useless.
Apr 29 2012
prev sibling parent reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 4/29/12, Andrej Mitrovic <andrej.mitrovich gmail.com> wrote:
 struct Foo {
     auto opIn_r(string op)(int i) { return 1; }
 }
Sorry that's wrong, should be: struct Foo { auto opIn_r(int i) { return 1; } } And then you get: test.d(25): Error: function test.Foo.opIn_r (int i) is not callable using argument types (string) test.d(25): Error: cannot implicitly convert expression ("") of type string to int which much better than Bar's error message.
Apr 29 2012
parent =?ISO-8859-1?Q?Alex_R=F8nne_Petersen?= <xtzgzorex gmail.com> writes:
On 29-04-2012 22:52, Andrej Mitrovic wrote:
 On 4/29/12, Andrej Mitrovic<andrej.mitrovich gmail.com>  wrote:
 struct Foo {
      auto opIn_r(string op)(int i) { return 1; }
 }
Sorry that's wrong, should be: struct Foo { auto opIn_r(int i) { return 1; } } And then you get: test.d(25): Error: function test.Foo.opIn_r (int i) is not callable using argument types (string) test.d(25): Error: cannot implicitly convert expression ("") of type string to int which much better than Bar's error message.
I think all of the error messages you posted could need improvement. In any case, that's a compiler issue if anything. -- - Alex
Apr 29 2012
prev sibling next sibling parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Sat, Apr 28, 2012 at 11:47:31AM -0700, Walter Bright wrote:
 Andrei and I had a fun discussion last night about this question.
 The idea was which features in D are redundant and/or do not add
 significant value?
 
 A couple already agreed upon ones are typedef and the cfloat,
 cdouble and creal types.
D has typedef?? Wow. And I thought I had a good grasp of D.
 What's your list?
Comma operator. foreach_reverse. with statements. They make code hard to read, and besides you can (or should be able to) alias long expressions into a short identifier for this purpose anyway. The great variety of string quoting syntax, while useful, seem to need some cleanup and unification. Get rid of r"", `` works just fine. (Or vice versa, but not both.) Delimited strings and token strings may be possible to be unified, perhaps? It's about time octal literals went the way of the bit bucket. There's probably more, I'll post them as I think of them. T -- Questions are the beginning of intelligence, but the fear of God is the beginning of wisdom.
Apr 28 2012
parent reply =?ISO-8859-1?Q?Alex_R=F8nne_Petersen?= <xtzgzorex gmail.com> writes:
On 28-04-2012 22:43, H. S. Teoh wrote:
 On Sat, Apr 28, 2012 at 11:47:31AM -0700, Walter Bright wrote:
 Andrei and I had a fun discussion last night about this question.
 The idea was which features in D are redundant and/or do not add
 significant value?

 A couple already agreed upon ones are typedef and the cfloat,
 cdouble and creal types.
D has typedef?? Wow. And I thought I had a good grasp of D.
It "has" typedef, but it is deprecated.
 What's your list?
Comma operator.
+1.
 foreach_reverse.
+1.
 with statements. They make code hard to read, and besides you can (or
 should be able to) alias long expressions into a short identifier for
 this purpose anyway.
I don't think I agree entirely here. If you have very long sequences of statements operating on the same object, with can be very useful. That said, I recognize that the current implementation of with needs some work.
 The great variety of string quoting syntax, while useful, seem to need
 some cleanup and unification. Get rid of r"", `` works just fine. (Or
 vice versa, but not both.) Delimited strings and token strings may be
 possible to be unified, perhaps?
IMHO r"" is better than `` for the simple reason that typing `` is extremely annoying on non-US keyboards.
 It's about time octal literals went the way of the bit bucket.
I think those are already deprecated.
 There's probably more, I'll post them as I think of them.


 T
-- - Alex
Apr 29 2012
next sibling parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Sun, Apr 29, 2012 at 10:26:40PM +0200, Alex Rønne Petersen wrote:
 On 28-04-2012 22:43, H. S. Teoh wrote:
[...]
with statements. They make code hard to read, and besides you can (or
should be able to) alias long expressions into a short identifier for
this purpose anyway.
I don't think I agree entirely here. If you have very long sequences of statements operating on the same object, with can be very useful. That said, I recognize that the current implementation of with needs some work.
[...] I think the correct solution here is to use alias. (If that doesn't work, then it should be made to work. It's a lot cleaner and doesn't introduce potentially nasty ambiguities into code, as well as make code more readable without needing to implement nested symbol tables in your brain.) T -- Help a man when he is in trouble and he will remember you when he is in trouble again.
Apr 29 2012
parent reply "bearophile" <bearophileHUGS lycos.com> writes:
H. S. Teoh:

 I think the correct solution here is to use alias. (If that 
 doesn't
 work, then it should be made to work. It's a lot cleaner and 
 doesn't
 introduce potentially nasty ambiguities into code,
What ambiguities? Bye, bearophile
Apr 30 2012
parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Mon, Apr 30, 2012 at 10:21:23AM +0200, bearophile wrote:
 H. S. Teoh:
 
I think the correct solution here is to use alias. (If that doesn't
work, then it should be made to work. It's a lot cleaner and doesn't
introduce potentially nasty ambiguities into code,
What ambiguities?
[...] When you have nested with's. Or when the object members shadow local variables in the parent scope. struct S { int x; } void main() { int x, y; S s; with(s) { x = 1; y = 2; } } Technically it's unambiguous which symbols are being referred to, but it makes the code hard to read because casual scanning will usually get it wrong. Plus, you're entirely at the mercy of the definition of S. If it's an imported object from an external library, for example, then when upstream makes changes to their struct/class there's a risk of introducing subtle errors into existing, correct code (by suddenly interpreting an identifier differently). This is never good. It gets worse with nested with's: when any object being with'd changes, you risk identifier collision. The worst thing is that this can happen just by upstream(s) changing object definitions, with no change in user code. T -- Long, long ago, the ancient Chinese invented a device that lets them see through walls. It was called the "window".
Apr 30 2012
next sibling parent reply simendsjo <simendsjo gmail.com> writes:
On Mon, 30 Apr 2012 17:35:14 +0200, H. S. Teoh <hsteoh quickfur.ath.cx>  
wrote:

 On Mon, Apr 30, 2012 at 10:21:23AM +0200, bearophile wrote:
 H. S. Teoh:

I think the correct solution here is to use alias. (If that doesn't
work, then it should be made to work. It's a lot cleaner and doesn't
introduce potentially nasty ambiguities into code,
What ambiguities?
[...] When you have nested with's. Or when the object members shadow local variables in the parent scope. struct S { int x; } void main() { int x, y; S s; with(s) { x = 1; y = 2; } } Technically it's unambiguous which symbols are being referred to, but it makes the code hard to read because casual scanning will usually get it wrong. Plus, you're entirely at the mercy of the definition of S. If it's an imported object from an external library, for example, then when upstream makes changes to their struct/class there's a risk of introducing subtle errors into existing, correct code (by suddenly interpreting an identifier differently). This is never good. It gets worse with nested with's: when any object being with'd changes, you risk identifier collision. The worst thing is that this can happen just by upstream(s) changing object definitions, with no change in user code. T
I think struct literals is worse in this regard: struct S { int a; int b; } user code: S(1, 2); The author of S cleans up the struct and changes the order: struct S { int b; int a; } Suddely user code has bugs. I believe the reason named parameters hasn't been introduced is because the names becomes part of the public interface. Well.. With struct literals, the _position_ of the parameters is part of the interface.
Apr 30 2012
parent reply "foobar" <foo bar.com> writes:
On Monday, 30 April 2012 at 15:38:41 UTC, simendsjo wrote:
 I think struct literals is worse in this regard:
 struct S {
   int a;
   int b;
 }

 user code:
 S(1, 2);

 The author of S cleans up the struct and changes the order:
 struct S {
   int b;
   int a;
 }

 Suddely user code has bugs. I believe the reason named 
 parameters hasn't been introduced is because the names becomes 
 part of the public interface. Well.. With struct literals, the 
 _position_ of the parameters is part of the interface.
Structs provide POD value types and as such MUST include the position as part of the interface. The memory layout of these types is used to copy, compare, transmit over the net, etc. If you want encapsulation you need to at the least to define a ctor or maybe change to a class. I'd be very upset if I defined a struct for serialization/transmitting over the net/etc and changing its memory _didn't_ cause loud compiler errors. named parameters are 99% of the time a horrible idea and likely indicate a design flaw.
Apr 30 2012
parent "bearophile" <bearophileHUGS lycos.com> writes:
foobar:

 named parameters are 99% of the time a horrible idea and likely 
 indicate a design flaw.
Named arguments help avoid some bugs, make the code more readable, and having used them for many years, they don't seem to indicate significant flaws in my code. Bye, bearophile
Apr 30 2012
prev sibling next sibling parent reply "bearophile" <bearophileHUGS lycos.com> writes:
H. S. Teoh:

 When you have nested with's.

 Or when the object members shadow local variables in the parent 
 scope.

 	struct S {
 		int x;
 	}

 	void main() {
 		int x, y;
 		S s;

 		with(s) {
 			x = 1;
 			y = 2;
 		}
 	}
That code doesn't compile: test.d(10): Error: with symbol test.S.x is shadowing local symbol test.main.x Bye, bearophile
Apr 30 2012
parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Mon, Apr 30, 2012 at 05:47:59PM +0200, bearophile wrote:
 H. S. Teoh:
 
When you have nested with's.

Or when the object members shadow local variables in the parent
scope.

	struct S {
		int x;
	}

	void main() {
		int x, y;
		S s;

		with(s) {
			x = 1;
			y = 2;
		}
	}
That code doesn't compile: test.d(10): Error: with symbol test.S.x is shadowing local symbol test.main.x
[...] Which means your code is at the mercy of the external library. Upstream updates a class, and suddenly a whole bunch of code is unnecessarily broken (if you had just used aliases instead, there would be no problem). T -- It is of the new things that men tire --- of fashions and proposals and improvements and change. It is the old things that startle and intoxicate. It is the old things that are young. -- G.K. Chesterton
Apr 30 2012
parent reply "bearophile" <bearophileHUGS lycos.com> writes:
H. S. Teoh:

 Which means your code is at the mercy of the external library.
 Upstream updates a class, and suddenly a whole bunch of code is
 unnecessarily broken
How? (I think you are wrong again). Bye, bearohile
Apr 30 2012
parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Mon, Apr 30, 2012 at 06:54:31PM +0200, bearophile wrote:
 H. S. Teoh:
 
Which means your code is at the mercy of the external library.
Upstream updates a class, and suddenly a whole bunch of code is
unnecessarily broken
How? (I think you are wrong again).
[...] struct S { int x; } void main() { int y; S s; with(s) { x = 1; y = 2; } } This works. Now suppose S is updated to: struct S { int x; int y; } Now the program fails to compile because S.y conflicts with the local y. This is bad because unrelated code is broken just by changing S: it breaks encapsulation. This is just a small example; imagine if a lot of code uses S. Many places may break when S changes just because they happen to use the wrong local variable names. Whereas if you had _not_ used with, this is a non-problem, since you'd be referring to s.x, and the fact that S now has a new member does not break any existing code regardless of how it was named. T -- People say I'm indecisive, but I'm not sure about that. -- YHL, CONLANG
Apr 30 2012
next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
H. S. Teoh:

 This is bad because unrelated code is broken just by changing 
 S: it
 breaks encapsulation. This is just a small example; imagine if 
 a lot of
 code uses S. Many places may break when S changes just because 
 they
 happen to use the wrong local variable names.
But it's a kind of safe breaking, it doesn't cause a lot of silent bugs. I have found with useful in many situation to reduce the noise in my code. Bye, bearophile
Apr 30 2012
prev sibling next sibling parent =?ISO-8859-1?Q?Alex_R=F8nne_Petersen?= <xtzgzorex gmail.com> writes:
On 30-04-2012 19:05, H. S. Teoh wrote:
 On Mon, Apr 30, 2012 at 06:54:31PM +0200, bearophile wrote:
 H. S. Teoh:

 Which means your code is at the mercy of the external library.
 Upstream updates a class, and suddenly a whole bunch of code is
 unnecessarily broken
How? (I think you are wrong again).
[...] struct S { int x; } void main() { int y; S s; with(s) { x = 1; y = 2; } } This works. Now suppose S is updated to: struct S { int x; int y; } Now the program fails to compile because S.y conflicts with the local y. This is bad because unrelated code is broken just by changing S: it breaks encapsulation. This is just a small example; imagine if a lot of code uses S. Many places may break when S changes just because they happen to use the wrong local variable names. Whereas if you had _not_ used with, this is a non-problem, since you'd be referring to s.x, and the fact that S now has a new member does not break any existing code regardless of how it was named. T
You always risk breaking *something* when you change an interface, whether it's through adding or removing members. The problem you point out is not at all specific to with. Consider UFCS: You have struct S and free function foo operating on S. Upstream now adds a method foo to S. -- - Alex
Apr 30 2012
prev sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 04/30/2012 07:05 PM, H. S. Teoh wrote:
 On Mon, Apr 30, 2012 at 06:54:31PM +0200, bearophile wrote:
 H. S. Teoh:

 Which means your code is at the mercy of the external library.
 Upstream updates a class, and suddenly a whole bunch of code is
 unnecessarily broken
How? (I think you are wrong again).
[...] struct S { int x; } void main() { int y; S s; with(s) { x = 1; y = 2; } } This works. Now suppose S is updated to: struct S { int x; int y; } Now the program fails to compile because S.y conflicts with the local y. This is bad because unrelated code
It is not unrelated.
 is broken just by changing S: it breaks encapsulation.
No it does not. Changing an interface is bound to break code.
 This is just a small example; imagine if a lot of
 code uses S. Many places may break when S changes just because they
 happen to use the wrong local variable names.
That is an extremely constructed argument. I cannot imagine that this will ever be a problem in practice.
 Whereas if you had _not_ used with, this is a non-problem, since you'd
 be referring to s.x, and the fact that S now has a new member does not
 break any existing code regardless of how it was named.
int* x = cast(int*)&s; int y = *x; S t = *cast(S*)&y; static if(!is(typeof(S.y)){ ... }
Apr 30 2012
prev sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 04/30/2012 05:35 PM, H. S. Teoh wrote:
 On Mon, Apr 30, 2012 at 10:21:23AM +0200, bearophile wrote:
 H. S. Teoh:

 I think the correct solution here is to use alias. (If that doesn't
 work, then it should be made to work. It's a lot cleaner and doesn't
 introduce potentially nasty ambiguities into code,
What ambiguities?
[...] When you have nested with's. Or when the object members shadow local variables in the parent scope. struct S { int x; } void main() { int x, y; S s; with(s) { x = 1; y = 2; } } [snip.]
You probably should try compiling that code. ;)
Apr 30 2012
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 4/30/12, H. S. Teoh <hsteoh quickfur.ath.cx> wrote:
 I think the correct solution here is to use alias. (If that doesn't
 work, then it should be made to work..)
It probably will. Quote Andrei: "Yah, we should add that at some point. Walter and I discussed about it and it's virtually approved. But to be on the conservative side, it's not for expressions but for mere pointer-chasing chains." So this would probably work: alias var.some.deeply.nested.object obj; // use obj here.. I think that's what is being discussed w.r.t. with()?
Apr 29 2012
prev sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2012-04-29 22:26, Alex Rønne Petersen wrote:

 IMHO r"" is better than `` for the simple reason that typing `` is
 extremely annoying on non-US keyboards.
`` is better because you don't have to escape ". -- /Jacob Carlborg
Apr 30 2012
parent reply =?ISO-8859-1?Q?Alex_R=F8nne_Petersen?= <xtzgzorex gmail.com> writes:
On 30-04-2012 09:08, Jacob Carlborg wrote:
 On 2012-04-29 22:26, Alex Rønne Petersen wrote:

 IMHO r"" is better than `` for the simple reason that typing `` is
 extremely annoying on non-US keyboards.
`` is better because you don't have to escape ".
That only applies when you actually have " in the string. I think both have their uses. -- - Alex
Apr 30 2012
parent reply Jacob Carlborg <doob me.com> writes:
On 2012-04-30 17:14, Alex Rønne Petersen wrote:
 On 30-04-2012 09:08, Jacob Carlborg wrote:
 On 2012-04-29 22:26, Alex Rønne Petersen wrote:

 IMHO r"" is better than `` for the simple reason that typing `` is
 extremely annoying on non-US keyboards.
`` is better because you don't have to escape ".
That only applies when you actually have " in the string. I think both have their uses.
When is r"" a better use than ``? We already have the regular "". -- /Jacob Carlborg
Apr 30 2012
parent reply =?ISO-8859-1?Q?Alex_R=F8nne_Petersen?= <xtzgzorex gmail.com> writes:
On 30-04-2012 21:42, Jacob Carlborg wrote:
 On 2012-04-30 17:14, Alex Rønne Petersen wrote:
 On 30-04-2012 09:08, Jacob Carlborg wrote:
 On 2012-04-29 22:26, Alex Rønne Petersen wrote:

 IMHO r"" is better than `` for the simple reason that typing `` is
 extremely annoying on non-US keyboards.
`` is better because you don't have to escape ".
That only applies when you actually have " in the string. I think both have their uses.
When is r"" a better use than ``? We already have the regular "".
You don't have escape sequences inside r"", so they can be useful if you have backslashes in your string. -- - Alex
Apr 30 2012
parent reply Jacob Carlborg <doob me.com> writes:
On 2012-04-30 22:03, Alex Rønne Petersen wrote:
 On 30-04-2012 21:42, Jacob Carlborg wrote:
 When is r"" a better use than ``? We already have the regular "".
You don't have escape sequences inside r"", so they can be useful if you have backslashes in your string.
`` can be used for that. ` is good because it's a different delimiter compared to r"" or "". -- /Jacob Carlborg
May 01 2012
parent reply =?ISO-8859-1?Q?Alex_R=F8nne_Petersen?= <xtzgzorex gmail.com> writes:
On 01-05-2012 13:22, Jacob Carlborg wrote:
 On 2012-04-30 22:03, Alex Rønne Petersen wrote:
 On 30-04-2012 21:42, Jacob Carlborg wrote:
 When is r"" a better use than ``? We already have the regular "".
You don't have escape sequences inside r"", so they can be useful if you have backslashes in your string.
`` can be used for that. ` is good because it's a different delimiter compared to r"" or "".
It *can*, but it's annoying on non-US keyboards, which was my original point. -- - Alex
May 01 2012
parent Jacob Carlborg <doob me.com> writes:
On 2012-05-01 16:28, Alex Rønne Petersen wrote:

 It *can*, but it's annoying on non-US keyboards, which was my original
 point.
Well, I don't agree. -- /Jacob Carlborg
May 01 2012
prev sibling next sibling parent reply "Maxim Fomin" <maxim maxim-fomin.ru> writes:
On Saturday, 28 April 2012 at 18:48:18 UTC, Walter Bright wrote:
 Andrei and I had a fun discussion last night about this 
 question. The idea was which features in D are redundant and/or 
 do not add significant value?

 A couple already agreed upon ones are typedef and the cfloat, 
 cdouble and creal types.

 What's your list?
I guess the underlying problem is inability to formulate the target state of the language with specified relations between different components. Being looking at the language since late 2011 I found problematic to know the language as a whole. When a newcomer looks for information he either gets a common overview "native efficiency, ..." at dlang.org with (outdated) documentation or videos on youtube which explains how scope(xxx) beats exceptions and templates are superior to that in C++ and similar posts in the web, let alone toolchain lack complaints. My comment was provoked mainly by http://forum.dlang.org/thread/vwpzirpppabcgylmvpsx forum.dlang.org discussion (D3 idea). You ask which features are redundant or not significant, but this depends on how features are integrated in the rest of language and without clear and completed vision there is no answer. And please remember, that each of D member has its own (biased) information about D and what to do. The language is moving and it is hard to reveal how any change will affect other components. Even if you found a particular item redundant there is no guarantee that the situation will not change in future. "usability" and C performance) view D as a ship which sails in unknown direction with lots of holes (look at bugzilla proposals how to make a language) and what I found the most dreaded is that the direction of the ship movement today is determined by which hole was fixed yesterday. So, you are free to ask ship's crew about what hole and how to fix and expect that it will tomorrow bring ship to a better place, but without final destination this brownian movement may theoretically last infinitely, but of course, in practice it will lead either to ship crashing, departure of sailors or finally targeting an unexpected place with unsatisfactory result.
Apr 28 2012
next sibling parent "D Day" <damianday hotmail.co.uk> writes:
On Saturday, 28 April 2012 at 20:49:33 UTC, Maxim Fomin wrote:
 On Saturday, 28 April 2012 at 18:48:18 UTC, Walter Bright wrote:
 Andrei and I had a fun discussion last night about this 
 question. The idea was which features in D are redundant 
 and/or do not add significant value?

 A couple already agreed upon ones are typedef and the cfloat, 
 cdouble and creal types.

 What's your list?
I guess the underlying problem is inability to formulate the target state of the language with specified relations between different components. Being looking at the language since late 2011 I found problematic to know the language as a whole. When a newcomer looks for information he either gets a common overview "native efficiency, ..." at dlang.org with (outdated) documentation or videos on youtube which explains how scope(xxx) beats exceptions and templates are superior to that in C++ and similar posts in the web, let alone toolchain lack complaints. My comment was provoked mainly by http://forum.dlang.org/thread/vwpzirpppabcgylmvpsx forum.dlang.org discussion (D3 idea). You ask which features are redundant or not significant, but this depends on how features are integrated in the rest of language and without clear and completed vision there is no answer. And please remember, that each of D member has its own (biased) information about D and what to do. The language is moving and it is hard to reveal how any change will affect other components. Even if you found a particular item redundant there is no guarantee that the situation will not change in future. "usability" and C performance) view D as a ship which sails in unknown direction with lots of holes (look at bugzilla proposals how to make a language) and what I found the most dreaded is that the direction of the ship movement today is determined by which hole was fixed yesterday. So, you are free to ask ship's crew about what hole and how to fix and expect that it will tomorrow bring ship to a better place, but without final destination this brownian movement may theoretically last infinitely, but of course, in practice it will lead either to ship crashing, departure of sailors or finally targeting an unexpected place with unsatisfactory result.
Apr 28 2012
prev sibling parent "SomeDude" <lovelydear mailmetrash.com> writes:
On Saturday, 28 April 2012 at 20:49:33 UTC, Maxim Fomin wrote:
 On Saturday, 28 April 2012 at 18:48:18 UTC, Walter Bright wrote:
 Andrei and I had a fun discussion last night about this 
 question. The idea was which features in D are redundant 
 and/or do not add significant value?

 A couple already agreed upon ones are typedef and the cfloat, 
 cdouble and creal types.

 What's your list?
I guess the underlying problem is inability to formulate the target state of the language with specified relations between different components. Being looking at the language since late 2011 I found problematic to know the language as a whole. When a newcomer looks for information he either gets a common overview "native efficiency, ..." at dlang.org with (outdated) documentation or videos on youtube which explains how scope(xxx) beats exceptions and templates are superior to that in C++ and similar posts in the web, let alone toolchain lack complaints. My comment was provoked mainly by http://forum.dlang.org/thread/vwpzirpppabcgylmvpsx forum.dlang.org discussion (D3 idea). You ask which features are redundant or not significant, but this depends on how features are integrated in the rest of language and without clear and completed vision there is no answer. And please remember, that each of D member has its own (biased) information about D and what to do. The language is moving and it is hard to reveal how any change will affect other components. Even if you found a particular item redundant there is no guarantee that the situation will not change in future. "usability" and C performance) view D as a ship which sails in unknown direction with lots of holes (look at bugzilla proposals how to make a language) and what I found the most dreaded is that the direction of the ship movement today is determined by which hole was fixed yesterday. So, you are free to ask ship's crew about what hole and how to fix and expect that it will tomorrow bring ship to a better place, but without final destination this brownian movement may theoretically last infinitely, but of course, in practice it will lead either to ship crashing, departure of sailors or finally targeting an unexpected place with unsatisfactory result.
That's a very well worded post. That's one more reason why the most important thing imho is to have the current feature set stabilized, and not adding or removing features every other month, because we don't have enough experience with D to be certain such feature is redundant. This kind of experience can only be gained with feedback from hundreds or thousands of users, and there aren't that many users in this newsgroup. D is large enough that I'm pretty sure no two programmers use the same features. That's why we have so different answers to the question "which features is useless ?". Yet every programmer has his favorite feature that saves his ass at one point or another, and that's why everybody finds it's a joy to use. Were it missing, someone would complain. I'm pretty confident that in a sufficiently large program, nearly every single feature of the language will be put to good use. Now what people don't like is when features or Phobos don't work as expected, I suppose that's what you call holes. And that's another matter. I've browsed through hundreds of bug reports last week, and I could see many many features don't work as expected. And that's the most important problem in my opinion. That's where most of the efforts should be put.
Apr 28 2012
prev sibling next sibling parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
On Saturday, 28 April 2012 at 18:48:18 UTC, Walter Bright wrote:
 What's your list?
I think most the responses to this thread are insane. But, there is one thing I don't think D needs: new. I'm pretty sure it could be done in the library now that we have robust templates, which I think would open up some nice things. Suppose: module std.typecons; NotNull!T new(T, Args...)(Args args) { return assumeNotNull(core.gc.new!T(args)); } module core.gc; T new(T, Args...)(Args args) { // implement the new we know now } And so on, then you could get new allocators just by changing which module you import new from. We could kinda sorta do it now, but it wouldn't be as consistent, and of course, the name "new" is unavailable.
Apr 28 2012
next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Saturday, April 28, 2012 23:20:42 Adam D. Ruppe wrote:
 On Saturday, 28 April 2012 at 18:48:18 UTC, Walter Bright wrote:
 What's your list?
I think most the responses to this thread are insane.
LOL. Yeah. Many of them involve completely gutted pieces of the language, and very few discuss "redundant" features like Walter mentioned. - Jonathan M Davis
Apr 28 2012
prev sibling parent =?UTF-8?B?QWxleCBSw7hubmUgUGV0ZXJzZW4=?= <xtzgzorex gmail.com> writes:
On 28-04-2012 23:20, Adam D. Ruppe wrote:
 On Saturday, 28 April 2012 at 18:48:18 UTC, Walter Bright wrote:
 What's your list?
I think most the responses to this thread are insane. But, there is one thing I don't think D needs: new. I'm pretty sure it could be done in the library now that we have robust templates, which I think would open up some nice things. Suppose: module std.typecons; NotNull!T new(T, Args...)(Args args) { return assumeNotNull(core.gc.new!T(args)); } module core.gc; T new(T, Args...)(Args args) { // implement the new we know now } And so on, then you could get new allocators just by changing which module you import new from. We could kinda sorta do it now, but it wouldn't be as consistent, and of course, the name "new" is unavailable.
OK, so while in general I agree that 'new' shouldn't be tied to the GC by default, I don't think your example of swapping allocators through imports is a good idea at all. The reason is simple: More often than not, it never *is* as simple as just changing an import. Some allocators use stack allocation, some use C heap allocation, some use the druntime GC, some use the libgc library, ... All of these need different treatment of the allocated memory, so I don't think there is much to be gained here. -- - Alex
Apr 29 2012
prev sibling next sibling parent reply "Peter Alexander" <peter.alexander.au gmail.com> writes:
On Saturday, 28 April 2012 at 18:48:18 UTC, Walter Bright wrote:
 Andrei and I had a fun discussion last night about this 
 question. The idea was which features in D are redundant and/or 
 do not add significant value?

 A couple already agreed upon ones are typedef and the cfloat, 
 cdouble and creal types.

 What's your list?
Here's my list: - Properties. They add no value and just start pointless discussions about what should and shouldn't be a property. - UFCS. It's just sugar, but adds complexity. - const/immutable/inout/shared/pure. These add massive complexity to the language for little (IMO) benefit. When I do multi-threading, I usually have to resort to casting. Maybe these will improve with time. - opDispatch. I think it just promotes sloppy, obfuscated code for minor syntactical benefit. Member access through pointers should require -> like in C++ so that you can overload it for smart pointer/reference ADTs. That's all I can think of for now.
Apr 28 2012
next sibling parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Sat, Apr 28, 2012 at 11:42:31PM +0200, Peter Alexander wrote:
[...]
 - UFCS. It's just sugar, but adds complexity.
On the contrary, it's a major helper for writing generic code. In my new AA implementation, I use UFCS to provide a default toHash function for all types that don't already provide one. Without UFCS, this would require lots of ugly hacks and constraints on how user code can provide custom hash functions. (Due to the way D overloading works, UFCS is currently the only way to provide a default function without causing a conflict at compile-time.)
 - const/immutable/inout/shared/pure. These add massive complexity to
 the language for little (IMO) benefit. When I do multi-threading, I
 usually have to resort to casting. Maybe these will improve with
 time.
Yeah they are complex, but they also open ways for powerful optimizations by the compiler. Though I do have to say that inout needs some serious reconsideration, since the way they work currently is ambiguous when you have more than one inout argument, or when you have a delegate parameter with inout arguments.
 - opDispatch. I think it just promotes sloppy, obfuscated code for
 minor syntactical benefit.
Wrong. It's a powerful tool for building runtime dynamic class loading. It allows you to write generic code that Just Works without having to special-case them for statically-known classes vs. dynamic classes. If anything, I'd argue for *more* similar features that let you write generic code that integrates seamlessly into the language. Just because it's been used (arguably abused) for things like making roman numerals or vector swizzling, doesn't mean it's a bad feature.
 Member access through pointers should require -> like in C++ so that
 you can overload it for smart pointer/reference ADTs.
[...] Yikes!! Please don't reintroduce that monstrous -> operator from C++! (Besides, most of the time idiomatic D code doesn't even need pointers.) T -- If you look at a thing nine hundred and ninety-nine times, you are perfectly safe; if you look at it the thousandth time, you are in frightful danger of seeing it for the first time. -- G. K. Chesterton
Apr 28 2012
next sibling parent reply "Peter Alexander" <peter.alexander.au gmail.com> writes:
On Saturday, 28 April 2012 at 21:58:47 UTC, H. S. Teoh wrote:
 On Sat, Apr 28, 2012 at 11:42:31PM +0200, Peter Alexander wrote:
 [...]
 - UFCS. It's just sugar, but adds complexity.
On the contrary, it's a major helper for writing generic code. In my new AA implementation, I use UFCS to provide a default toHash function for all types that don't already provide one. Without UFCS, this would require lots of ugly hacks and constraints on how user code can provide custom hash functions. (Due to the way D overloading works, UFCS is currently the only way to provide a default function without causing a conflict at compile-time.)
The problem there is that toHash is a member function. That UFCS is helpful in working around other problems in D is not a good argument for its existence IMO. To be honest, I don't like the idea of member functions at all. Having two syntaxes for calling a function is the core problem, and UFCS is just an extra complication on top of it to try and mitigate the original problem. f(x) ---> x.f() is not progress in language design.
 - const/immutable/inout/shared/pure. These add massive 
 complexity to
 the language for little (IMO) benefit. When I do 
 multi-threading, I
 usually have to resort to casting. Maybe these will improve 
 with
 time.
Yeah they are complex, but they also open ways for powerful optimizations by the compiler.
In theory. IMO the amount of time you spend trying to please the type system could have been better spent optimizing your code manually. No code I have ever written would benefit significantly from these potential optimisations. For example, one optimisation is that pure function calls could be hoisted out of loops. Great, except that if that function call had any significant cost whatsoever, I would have already done that optimisation myself.
 - opDispatch. I think it just promotes sloppy, obfuscated code 
 for
 minor syntactical benefit.
Wrong.
It's my opinion. You are free to disagree, but opinions can't be wrong. I've seen no good uses of opDispatch so far. If you can point me towards some code that justifies its use then please let me know about it.
Apr 28 2012
parent reply "bearophile" <bearophileHUGS lycos.com> writes:
Peter Alexander:

 f(x) ---> x.f() is not progress in language design.
I used to think the same. But Haskell offers "." and $ to chain In D UCFS is almost equally useful to turn nesting of function calls in a more readable chain. In functional-style code this makes a lot of difference, turning: foo(bar(copy(baz(a), spam(b)))) Into: baz(a).copy(b.spam()).bar().foo() When I see 3+ nested parentheses I find it hard to read the expression. While a chain is easy to read.
 In theory. IMO the amount of time you spend trying to please 
 the type system could have been better spent optimizing your 
 code manually.

 No code I have ever written would benefit significantly from 
 these potential optimisations. For example, one optimisation is 
 that pure function calls could be hoisted out of loops. Great, 
 except that if that function call had any significant cost 
 whatsoever, I would have already done that optimisation myself.
I used to write lot of D1 code too, and I've seen that managing D2 const-related issues slows down significantly my coding compared to D1 coding, so undeniably they have a cost. But in D the main purpose of "pure" is not as optimization tool, but more as a tool to enforce a better coding style, that makes code understanding (and testing simpler), and helps avoid some bugs, coming from using variables from outer scopes. Bye, bearophile
Apr 28 2012
parent reply "Peter Alexander" <peter.alexander.au gmail.com> writes:
On Saturday, 28 April 2012 at 23:29:35 UTC, bearophile wrote:
 Peter Alexander:

 f(x) ---> x.f() is not progress in language design.
I used to think the same. But Haskell offers "." and $ to chain operator. In D UCFS is almost equally useful to turn nesting of function calls in a more readable chain. In functional-style code this makes a lot of difference, turning: foo(bar(copy(baz(a), spam(b)))) Into: baz(a).copy(b.spam()).bar().foo() When I see 3+ nested parentheses I find it hard to read the expression. While a chain is easy to read.
What D does and what Haskell does are very different things. D has (at least) two types of functions: free functions and member functions. UFCS makes free functions look like member functions. In Haskell, $ just gives you a way of re-ordering precedence -- it doesn't hide anything. This matters because UFCS in D is deceitful. It makes you think the free function is a member function when it is not. struct Foo { void bar() {} } void baz(Foo f) {} Foo f; f.bar(); // ok f.baz(); // ok, looks like baz is a member function auto pbar = &Foo.bar; // ok auto pbaz = &Foo.baz; // error! IMO, D would be better with Haskell's function calling syntax (of course, this would require many, many other syntactical changes).
 But in D the main purpose of "pure" is not as optimization 
 tool, but more as a tool to enforce a better coding style, that 
 makes code understanding (and testing simpler), and helps avoid 
 some bugs, coming from using variables from outer scopes.
True, but I'm quite happy to write pure functions without the static checking. I do not believe that the safety provided by the static checks outweighs the development cost of ensuring you have the correct qualifiers everywhere.
Apr 28 2012
next sibling parent =?UTF-8?B?QWxleCBSw7hubmUgUGV0ZXJzZW4=?= <xtzgzorex gmail.com> writes:
On 29-04-2012 01:41, Peter Alexander wrote:
 On Saturday, 28 April 2012 at 23:29:35 UTC, bearophile wrote:
 Peter Alexander:

 f(x) ---> x.f() is not progress in language design.
I used to think the same. But Haskell offers "." and $ to chain UCFS is almost equally useful to turn nesting of function calls in a more readable chain. In functional-style code this makes a lot of difference, turning: foo(bar(copy(baz(a), spam(b)))) Into: baz(a).copy(b.spam()).bar().foo() When I see 3+ nested parentheses I find it hard to read the expression. While a chain is easy to read.
What D does and what Haskell does are very different things. D has (at least) two types of functions: free functions and member functions. UFCS makes free functions look like member functions. In Haskell, $ just gives you a way of re-ordering precedence -- it doesn't hide anything. This matters because UFCS in D is deceitful. It makes you think the free function is a member function when it is not. struct Foo { void bar() {} } void baz(Foo f) {} Foo f; f.bar(); // ok f.baz(); // ok, looks like baz is a member function auto pbar = &Foo.bar; // ok auto pbaz = &Foo.baz; // error! IMO, D would be better with Haskell's function calling syntax (of course, this would require many, many other syntactical changes).
 But in D the main purpose of "pure" is not as optimization tool, but
 more as a tool to enforce a better coding style, that makes code
 understanding (and testing simpler), and helps avoid some bugs, coming
 from using variables from outer scopes.
True, but I'm quite happy to write pure functions without the static checking. I do not believe that the safety provided by the static checks outweighs the development cost of ensuring you have the correct qualifiers everywhere.
In my experience, pure is only hard to use in D due to the runtime and standard library not being properly annotated. I don't think anything is wrong with the language feature itself. -- - Alex
Apr 29 2012
prev sibling parent "SomeDude" <lovelydear mailmetrash.com> writes:
On Saturday, 28 April 2012 at 23:41:29 UTC, Peter Alexander wrote:
 But in D the main purpose of "pure" is not as optimization 
 tool, but more as a tool to enforce a better coding style, 
 that makes code understanding (and testing simpler), and helps 
 avoid some bugs, coming from using variables from outer scopes.
True, but I'm quite happy to write pure functions without the static checking. I do not believe that the safety provided by the static checks outweighs the development cost of ensuring you have the correct qualifiers everywhere.
Maybe you don't feel the benefit because you have less bugs in multithreaded applications than you would without, but you can't really know unless you do write the same code without ? Or something like that. :o) Anyway, I have the feeling that it's very hard to quantify the benefits of adding purity vs not having it. The benefits are both very theoretical, and practically verified in functional languages everyday. But knowing that the compiler *guarantees* certain properties and that some classes of errors cannot happen helps coding with a certain peace of mind, i.e you *know* that some bad things can't happen. So it's a little pain to satisfy the static checking of the compiler, but it's still much better than having to debug random race conditions that happen once in a while in production and are thus very hard to reproduce, and it does certainly help when you have to *ensure* that your critical code can never hang.
Apr 29 2012
prev sibling parent =?ISO-8859-1?Q?Alex_R=F8nne_Petersen?= <xtzgzorex gmail.com> writes:
On 28-04-2012 23:59, H. S. Teoh wrote:
 On Sat, Apr 28, 2012 at 11:42:31PM +0200, Peter Alexander wrote:
 [...]
 - UFCS. It's just sugar, but adds complexity.
On the contrary, it's a major helper for writing generic code. In my new AA implementation, I use UFCS to provide a default toHash function for all types that don't already provide one. Without UFCS, this would require lots of ugly hacks and constraints on how user code can provide custom hash functions. (Due to the way D overloading works, UFCS is currently the only way to provide a default function without causing a conflict at compile-time.)
 - const/immutable/inout/shared/pure. These add massive complexity to
 the language for little (IMO) benefit. When I do multi-threading, I
 usually have to resort to casting. Maybe these will improve with
 time.
Yeah they are complex, but they also open ways for powerful optimizations by the compiler.
I don't know of any production compilers that make significant use of such annotations in any language. These qualifiers look nice in theory, but have little practical value other than making it easier to reason about code. I don't think they should go away, just sayin'. (BTW, I think nothing is wrong with pure.)
 Though I do have to say that inout needs some serious reconsideration,
 since the way they work currently is ambiguous when you have more than
 one inout argument, or when you have a delegate parameter with inout
 arguments.


 - opDispatch. I think it just promotes sloppy, obfuscated code for
 minor syntactical benefit.
Wrong. It's a powerful tool for building runtime dynamic class loading. It allows you to write generic code that Just Works without having to special-case them for statically-known classes vs. dynamic classes. If anything, I'd argue for *more* similar features that let you write generic code that integrates seamlessly into the language. Just because it's been used (arguably abused) for things like making roman numerals or vector swizzling, doesn't mean it's a bad feature.
 Member access through pointers should require ->  like in C++ so that
 you can overload it for smart pointer/reference ADTs.
[...] Yikes!! Please don't reintroduce that monstrous -> operator from C++! (Besides, most of the time idiomatic D code doesn't even need pointers.) T
-- - Alex
Apr 29 2012
prev sibling next sibling parent reply Manu <turkeyman gmail.com> writes:
On 29 April 2012 00:42, Peter Alexander <peter.alexander.au gmail.com>wrote:

 On Saturday, 28 April 2012 at 18:48:18 UTC, Walter Bright wrote:

 Andrei and I had a fun discussion last night about this question. The
 idea was which features in D are redundant and/or do not add significant
 value?

 A couple already agreed upon ones are typedef and the cfloat, cdouble and
 creal types.

 What's your list?
Here's my list: - Properties. They add no value and just start pointless discussions about what should and shouldn't be a property. - UFCS. It's just sugar, but adds complexity. - const/immutable/inout/shared/**pure. These add massive complexity to the language for little (IMO) benefit. When I do multi-threading, I usually have to resort to casting. Maybe these will improve with time. - opDispatch. I think it just promotes sloppy, obfuscated code for minor syntactical benefit. Member access through pointers should require -> like in C++ so that you can overload it for smart pointer/reference ADTs. That's all I can think of for now.
I disagree with every one of those points, except maybe 'shared', which seems like a good idea in theory, but I think it's completely broken (every interaction requires an explicit cast, and there is no facility for transfer of ownership, which is a VERY common operation in my experience)
Apr 28 2012
parent =?UTF-8?B?QWxleCBSw7hubmUgUGV0ZXJzZW4=?= <xtzgzorex gmail.com> writes:
On 29-04-2012 00:30, Manu wrote:
 On 29 April 2012 00:42, Peter Alexander <peter.alexander.au gmail.com
 <mailto:peter.alexander.au gmail.com>> wrote:

     On Saturday, 28 April 2012 at 18:48:18 UTC, Walter Bright wrote:

         Andrei and I had a fun discussion last night about this
         question. The idea was which features in D are redundant and/or
         do not add significant value?

         A couple already agreed upon ones are typedef and the cfloat,
         cdouble and creal types.

         What's your list?


     Here's my list:

     - Properties. They add no value and just start pointless discussions
     about what should and shouldn't be a property.

     - UFCS. It's just sugar, but adds complexity.

     - const/immutable/inout/shared/__pure. These add massive complexity
     to the language for little (IMO) benefit. When I do multi-threading,
     I usually have to resort to casting. Maybe these will improve with time.

     - opDispatch. I think it just promotes sloppy, obfuscated code for
     minor syntactical benefit. Member access through pointers should
     require -> like in C++ so that you can overload it for smart
     pointer/reference ADTs.

     That's all I can think of for now.


 I disagree with every one of those points, except maybe 'shared', which
 seems like a good idea in theory, but I think it's completely broken
 (every interaction requires an explicit cast, and there is no facility
 for transfer of ownership, which is a VERY common operation in my
 experience)
For shared to be useful, every function you call on/with a shared object/value must be templatized. This may be nice if most of the code you write is template-rich, but like anything else, templates are not a silver bullet. IMHO shared is heavily biased in its design, which is bad. -- - Alex
Apr 29 2012
prev sibling next sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 04/28/2012 11:42 PM, Peter Alexander wrote:
 On Saturday, 28 April 2012 at 18:48:18 UTC, Walter Bright wrote:
 Andrei and I had a fun discussion last night about this question. The
 idea was which features in D are redundant and/or do not add
 significant value?

 A couple already agreed upon ones are typedef and the cfloat, cdouble
 and creal types.

 What's your list?
Here's my list: - Properties. They add no value and just start pointless discussions about what should and shouldn't be a property. - UFCS. It's just sugar, but adds complexity. - const/immutable/inout/shared/pure. These add massive complexity to the language for little (IMO) benefit. When I do multi-threading, I usually have to resort to casting. Maybe these will improve with time. - opDispatch. I think it just promotes sloppy, obfuscated code for minor syntactical benefit. Member access through pointers should require -> like in C++ so that you can overload it for smart pointer/reference ADTs. That's all I can think of for now.
- UFCS: The complexity comes from having multiple function invocation syntaxes. UFCS actually makes that situation better without adding a lot of complexity to the compiler implementation. - const/immutable/shared/pure shared: The fact that everything that is not marked as shared is actually thread-local is extremely important. I think most other imperative languages got this wrong. But if shared is explicit in the type system, immutable really should be explicit too. The sad part is that the qualifiers don't play nicely with reference types at the moment. - opDispatch This is useful and of significant value if used the right way. I hope you are not actually serious about that '->' part.
Apr 28 2012
parent reply "Peter Alexander" <peter.alexander.au gmail.com> writes:
On Saturday, 28 April 2012 at 22:33:08 UTC, Timon Gehr wrote:
 - UFCS:
    The complexity comes from having multiple function invocation
    syntaxes. UFCS actually makes that situation better without 
 adding a
    lot of complexity to the compiler implementation.
Exactly. The problem is having multiple function invocation syntaxes. That's one source of complexity, and UFCS add another in attempt to reduce the first cause.
 - const/immutable/shared/pure
    shared: The fact that everything that is not marked as 
 shared is
    actually thread-local is extremely important. I think most 
 other
    imperative languages got this wrong.
    But if shared is explicit in the type system, immutable 
 really
    should be explicit too. The sad part is that the qualifiers 
 don't
    play nicely with reference types at the moment.
I agree with thread-local by default, but that is separate from shared.
 - opDispatch
    This is useful and of significant value if used the right 
 way.
Can you give me an example of it being used the right way?
    I hope you are not actually serious about that '->' part.
I'm serious. I don't like overloaded syntax. foo.bar shouldn't also mean (*foo).bar -- it causes confusion and introduces ambiguities when either could work. Combine this with opDispatch, UFCS and function overloading and your in for some nasty headaches.
Apr 28 2012
next sibling parent "q66" <quaker66 gmail.com> writes:
On Saturday, 28 April 2012 at 23:11:17 UTC, Peter Alexander wrote:
 On Saturday, 28 April 2012 at 22:33:08 UTC, Timon Gehr wrote:
 - UFCS:
   The complexity comes from having multiple function invocation
   syntaxes. UFCS actually makes that situation better without 
 adding a
   lot of complexity to the compiler implementation.
Exactly. The problem is having multiple function invocation syntaxes. That's one source of complexity, and UFCS add another in attempt to reduce the first cause.
 - const/immutable/shared/pure
   shared: The fact that everything that is not marked as 
 shared is
   actually thread-local is extremely important. I think most 
 other
   imperative languages got this wrong.
   But if shared is explicit in the type system, immutable 
 really
   should be explicit too. The sad part is that the qualifiers 
 don't
   play nicely with reference types at the moment.
I agree with thread-local by default, but that is separate from shared.
 - opDispatch
   This is useful and of significant value if used the right 
 way.
Can you give me an example of it being used the right way?
vector swizzling! :D
   I hope you are not actually serious about that '->' part.
I'm serious. I don't like overloaded syntax. foo.bar shouldn't also mean (*foo).bar -- it causes confusion and introduces ambiguities when either could work. Combine this with opDispatch, UFCS and function overloading and your in for some nasty headaches.
Apr 28 2012
prev sibling parent reply "F i L" <witte2008 gmail.com> writes:
Peter Alexander wrote:
 - opDispatch
   This is useful and of significant value if used the right 
 way.
Can you give me an example of it being used the right way?
It can be very useful for jQuery/JSON style dynamic objects: import std.variant, std.stdio; struct Dynamic { Variant[string] vars; void opDispatch(string key)() property { return vars[key]; } void opDispatch(string key, T)(T value) property { vars[key] = value; } } void main() { auto foo = Dynamic(); foo.a = "A"; foo.b = 11; writefln("%s, %s", foo.a, foo.b); }
   I hope you are not actually serious about that '->' part.
I'm serious. I don't like overloaded syntax. foo.bar shouldn't also mean (*foo).bar -- it causes confusion and introduces ambiguities when either could work. Combine this with opDispatch, UFCS and function overloading and your in for some nasty headaches.
Craziness. What could you possibly gain is there in forcing a pointer distinction at every point that it's used? We already declared the variable as a pointer, we don't need to be reminded of that fact at every line.
Apr 28 2012
parent reply "Peter Alexander" <peter.alexander.au gmail.com> writes:
On Saturday, 28 April 2012 at 23:37:14 UTC, F i L wrote:
 Peter Alexander wrote:
 - opDispatch
  This is useful and of significant value if used the right 
 way.
Can you give me an example of it being used the right way?
It can be very useful for jQuery/JSON style dynamic objects: import std.variant, std.stdio; struct Dynamic { Variant[string] vars; void opDispatch(string key)() property { return vars[key]; } void opDispatch(string key, T)(T value) property { vars[key] = value; } } void main() { auto foo = Dynamic(); foo.a = "A"; foo.b = 11; writefln("%s, %s", foo.a, foo.b); }
This is a perfect example of misuse. Glancing at that code, it looks like foo has two member variables. It is also not clear that each access involves a hash-table lookup. Why abuse well-understood syntax when there are simpler ways to solve the problem?
  I hope you are not actually serious about that '->' part.
I'm serious. I don't like overloaded syntax. foo.bar shouldn't also mean (*foo).bar -- it causes confusion and introduces ambiguities when either could work. Combine this with opDispatch, UFCS and function overloading and your in for some nasty headaches.
Craziness. What could you possibly gain is there in forcing a pointer distinction at every point that it's used? We already declared the variable as a pointer, we don't need to be reminded of that fact at every line.
It matters when you have things that imitate pointers (e.g. smart pointers). Those will have their own members, separate from the pointee's members, so ptr.foo could refer to the smart pointer's members or the pointee's members.
Apr 28 2012
next sibling parent "SomeDude" <lovelydear mailmetrash.com> writes:
On Saturday, 28 April 2012 at 23:54:36 UTC, Peter Alexander wrote:
 It matters when you have things that imitate pointers (e.g. 
 smart pointers). Those will have their own members, separate 
 from the pointee's members, so ptr.foo could refer to the smart 
 pointer's members or the pointee's members.
So basically, for your very specific issue, you want to ditch a syntax that 99% of people actually prefer. I must say you are the very first person I see *anywhere* who actually complains about the . notation and would rather go back to ->.
Apr 28 2012
prev sibling next sibling parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On Sunday, April 29, 2012 01:54:35 Peter Alexander wrote:
 On Saturday, 28 April 2012 at 23:37:14 UTC, F i L wrote:
 Peter Alexander wrote:
 I'm serious. I don't like overloaded syntax.  foo.bar
 shouldn't also mean (*foo).bar -- it causes confusion and
 introduces ambiguities when either could work. Combine this
 with opDispatch, UFCS and function overloading and your in for
 some nasty headaches.
Craziness. What could you possibly gain is there in forcing a pointer distinction at every point that it's used? We already declared the variable as a pointer, we don't need to be reminded of that fact at every line.
It matters when you have things that imitate pointers (e.g. smart pointers). Those will have their own members, separate from the pointee's members, so ptr.foo could refer to the smart pointer's members or the pointee's members.
For better or worse, the solution for smart pointers in D would be to use opDispatch, but it _does_ still mean that the type pointed to can't have any of the same functions as the smart pointer (or at least, they would have to be called differently, since . would use opDispatch and therefore use the smart pointer's function), so you _do_ lose something over the -> syntax here. However, the overall gain is usability probably still outweighs that. I wouldn't exactly have been heartbroken if -> had been in D, but simplicity of not needing it can be very nice - and it can be invaluable in the case of templates, because then you don't have to distinguish between structs, pointers to structs, and classes when calling functions on them. - Jonathan M Davis
Apr 28 2012
parent reply Dmitry Olshansky <dmitry.olsh gmail.com> writes:
On 29.04.2012 4:31, Jonathan M Davis wrote:
 On Sunday, April 29, 2012 01:54:35 Peter Alexander wrote:
 On Saturday, 28 April 2012 at 23:37:14 UTC, F i L wrote:
 Peter Alexander wrote:
 I'm serious. I don't like overloaded syntax.  foo.bar
 shouldn't also mean (*foo).bar -- it causes confusion and
 introduces ambiguities when either could work. Combine this
 with opDispatch, UFCS and function overloading and your in for
 some nasty headaches.
Craziness. What could you possibly gain is there in forcing a pointer distinction at every point that it's used? We already declared the variable as a pointer, we don't need to be reminded of that fact at every line.
It matters when you have things that imitate pointers (e.g. smart pointers). Those will have their own members, separate from the pointee's members, so ptr.foo could refer to the smart pointer's members or the pointee's members.
For better or worse, the solution for smart pointers in D would be to use opDispatch,
*cough* alias this *cough* but it _does_ still mean that the type pointed to can't have any
 of the same functions as the smart pointer (or at least, they would have to be
 called differently, since . would use opDispatch and therefore use the smart
 pointer's function), so you _do_ lose something over the ->  syntax here.
 However, the overall gain is usability probably still outweighs that. I
 wouldn't exactly have been heartbroken if ->  had been in D, but simplicity of
 not needing it can be very nice - and it can be invaluable in the case of
 templates, because then you don't have to distinguish between structs,
 pointers to structs, and classes when calling functions on them.

 - Jonathan M Davis
-- Dmitry Olshansky
Apr 28 2012
parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On Sunday, April 29, 2012 09:53:15 Dmitry Olshansky wrote:
 On 29.04.2012 4:31, Jonathan M Davis wrote:
 For better or worse, the solution for smart pointers in D would be to use
 opDispatch,
*cough* alias this *cough*
That's not necessarily a good idea, depending on how it's used. You want to avoid having the smart pointer implicitly convert to what it holds such that a reference to it leaks. If you're dealing with a pointer to a struct, and alias this aliases to the struct (rather than the pointer), then you're okay. But if you're dealing with a class, you don't have that option. So, alias this ends up leaking a reference to the class, which defeats the purpose of the smart pointer. You have the same problem if alias this aliases to the pointer rather than what's pointed to. But regardless of whether you use alias this or opDispatch, you have the same problem with regards to ->. In C++, . would be used to call the smart pointer's functions, and -> would be used to call functions on the object pointed to. In D, the two aren't distinguished - both use . - so you can't have any functions on the type pointed to which conflict with the smart pointer's functions, or you won't be able to call them (unless another way to call them is provided somehow). So, it's definitely something that C++ does better with as far as that goes. - Jonathan M Davis
Apr 28 2012
parent reply Dmitry Olshansky <dmitry.olsh gmail.com> writes:
On 29.04.2012 10:42, Jonathan M Davis wrote:
 On Sunday, April 29, 2012 09:53:15 Dmitry Olshansky wrote:
 On 29.04.2012 4:31, Jonathan M Davis wrote:
 For better or worse, the solution for smart pointers in D would be to use
 opDispatch,
*cough* alias this *cough*
That's not necessarily a good idea, depending on how it's used. You want to avoid having the smart pointer implicitly convert to what it holds such that a reference to it leaks. If you're dealing with a pointer to a struct, and alias this aliases to the struct (rather than the pointer), then you're okay. But if you're dealing with a class, you don't have that option. So, alias this ends up leaking a reference to the class, which defeats the purpose of the smart pointer. You have the same problem if alias this aliases to the pointer rather than what's pointed to.
Point taken.
 But regardless of whether you use alias this or opDispatch, you have the same
 problem with regards to ->. In C++, . would be used to call the smart
 pointer's functions, and ->  would be used to call functions on the object
 pointed to. In D, the two aren't distinguished - both use . - so you can't
 have any functions on the type pointed to which conflict with the smart
 pointer's functions, or you won't be able to call them (unless another way to
 call them is provided somehow). So, it's definitely something that C++ does
 better with as far as that goes.
So you just need not to have any _member_ functions on smart pointer? Just use free functions that take SmartPointer!T. UFCS may also lend a hand if T and SmartPointer do not have ambiguous funcs. -- Dmitry Olshansky
Apr 29 2012
parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Sunday, April 29, 2012 16:28:23 Dmitry Olshansky wrote:
 On 29.04.2012 10:42, Jonathan M Davis wrote:
 But regardless of whether you use alias this or opDispatch, you have the
 same problem with regards to ->. In C++, . would be used to call the
 smart pointer's functions, and ->  would be used to call functions on the
 object pointed to. In D, the two aren't distinguished - both use . - so
 you can't have any functions on the type pointed to which conflict with
 the smart pointer's functions, or you won't be able to call them (unless
 another way to call them is provided somehow). So, it's definitely
 something that C++ does better with as far as that goes.
So you just need not to have any _member_ functions on smart pointer? Just use free functions that take SmartPointer!T. UFCS may also lend a hand if T and SmartPointer do not have ambiguous funcs.
That could work (though they'd obviously have to be in the same module as the smart pointer - not exactly an onerous requirement - in order to be able to access its private members). - Jonathan M Davis
Apr 29 2012
prev sibling next sibling parent reply "F i L" <witte2008 gmail.com> writes:
On Saturday, 28 April 2012 at 23:54:36 UTC, Peter Alexander wrote:
 On Saturday, 28 April 2012 at 23:37:14 UTC, F i L wrote:
 Peter Alexander wrote:
 - opDispatch
 This is useful and of significant value if used the right 
 way.
Can you give me an example of it being used the right way?
It can be very useful for jQuery/JSON style dynamic objects: import std.variant, std.stdio; struct Dynamic { Variant[string] vars; void opDispatch(string key)() property { return vars[key]; } void opDispatch(string key, T)(T value) property { vars[key] = value; } } void main() { auto foo = Dynamic(); foo.a = "A"; foo.b = 11; writefln("%s, %s", foo.a, foo.b); }
This is a perfect example of misuse. Glancing at that code, it looks like foo has two member variables. It is also not clear that each access involves a hash-table lookup. Why abuse well-understood syntax when there are simpler ways to solve the problem?
It's not abuse, it's design. That's why I called the type "Dynamic" so the user has an idea about what it is. You could make your same arguments against ever using a Variant object. When you have to manipulate a DOM or XML tree, there's reason why people prefer languages that syntactically interface with those dynamic structure very well. D simply powerful enough to provide a way for programmers to do both. Btw, it's just as unclear that any property (or function) doesn't look through a hash-table or any other number of performance pitfalls if used without any insight into _how_ to use it. This is why we have documentation for libraries, it's impractical cater the language to the idea that coders wont understand the objects their working with to a basic degree.
 I hope you are not actually serious about that '->' part.
I'm serious. I don't like overloaded syntax. foo.bar shouldn't also mean (*foo).bar -- it causes confusion and introduces ambiguities when either could work. Combine this with opDispatch, UFCS and function overloading and your in for some nasty headaches.
Craziness. What could you possibly gain is there in forcing a pointer distinction at every point that it's used? We already declared the variable as a pointer, we don't need to be reminded of that fact at every line.
It matters when you have things that imitate pointers (e.g. smart pointers). Those will have their own members, separate from the pointee's members, so ptr.foo could refer to the smart pointer's members or the pointee's members.
SomeDude said this best. This is far the common case, and the language shouldn't force everyone to pay for this situation.
Apr 28 2012
parent "F i L" <witte2008 gmail.com> writes:
Typos. Typos everywhere :S I'm sure you get my meaning.
Apr 28 2012
prev sibling parent "Nick Sabalausky" <SeeWebsiteToContactMe semitwist.com> writes:
"Peter Alexander" <peter.alexander.au gmail.com> wrote in message 
news:nvvuxboigxxfdqfhyftw forum.dlang.org...
 To be honest, I don't like the idea of member functions at all. Having two 
 syntaxes for calling a function is the core problem, and UFCS is just an 
 extra complication on top of it to try and mitigate the original problem.

 f(x) ---> x.f() is not progress in language design.
[...]
 I'm serious. I don't like overloaded syntax.  foo.bar shouldn't also mean 
 (*foo).bar -- it causes confusion and introduces ambiguities when either 
 could work. Combine this with opDispatch, UFCS and function overloading 
 and your in for some nasty headaches.
[...]
 Glancing at that code, it looks like foo has two member variables. It is 
 also not clear that each access involves a hash-table lookup.
It sounds like you just simply don't like abstractions. I can understand that (although I don't agree with it), but it always puzzles me why such people even try to use high-level langauges at all instead of just binary machine code. And for the record, I've *never* seen anyone confused by foo.bar syntax being used on reference types.
Apr 29 2012
prev sibling parent Jacob Carlborg <doob me.com> writes:
On 2012-04-28 23:42, Peter Alexander wrote:

 Here's my list:

 - Properties. They add no value and just start pointless discussions
 about what should and shouldn't be a property.

 - UFCS. It's just sugar, but adds complexity.

 - const/immutable/inout/shared/pure. These add massive complexity to the
 language for little (IMO) benefit. When I do multi-threading, I usually
 have to resort to casting. Maybe these will improve with time.

 - opDispatch. I think it just promotes sloppy, obfuscated code for minor
 syntactical benefit. Member access through pointers should require ->
 like in C++ so that you can overload it for smart pointer/reference ADTs.

 That's all I can think of for now.
I love all these features beside the attributes. -- /Jacob Carlborg
Apr 29 2012
prev sibling next sibling parent reply deadalnix <deadalnix gmail.com> writes:
Le 28/04/2012 20:47, Walter Bright a écrit :
 Andrei and I had a fun discussion last night about this question. The
 idea was which features in D are redundant and/or do not add significant
 value?

 A couple already agreed upon ones are typedef and the cfloat, cdouble
 and creal types.

 What's your list?
OK longer answer. - is is messed up. It is a massive hack and have to be rationalized. - version is a bad version of static if. The static if part of the version must go. - comma expression is confusing and have very little benefice. - out arguments. We can return tuples, out argument is going backward in history. - many array properties (.sort for instance) are useless and would be way better as libs.
Apr 28 2012
next sibling parent reply "SomeDude" <lovelydear mailmetrash.com> writes:
On Saturday, 28 April 2012 at 21:51:42 UTC, deadalnix wrote:
  - out arguments. We can return tuples, out argument is going 
 backward in history.
  - many array properties (.sort for instance) are useless and 
 would be way better as libs.
What happens the day the language is actually fit for embedded programming, and you don't want to have to link against Phobos because it's too big ?
Apr 28 2012
parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Sat, Apr 28, 2012 at 11:57:46PM +0200, SomeDude wrote:
 On Saturday, 28 April 2012 at 21:51:42 UTC, deadalnix wrote:
 - out arguments. We can return tuples, out argument is going
backward in history.
 - many array properties (.sort for instance) are useless and
would be way better as libs.
What happens the day the language is actually fit for embedded programming, and you don't want to have to link against Phobos because it's too big ?
We need to fix things so that using a single feature in Phobos will not pull in the entire library. That's an implementation issue, not a language issue. T -- LINUX = Lousy Interface for Nefarious Unix Xenophobes.
Apr 28 2012
parent "SomeDude" <lovelydear mailmetrash.com> writes:
On Saturday, 28 April 2012 at 22:04:26 UTC, H. S. Teoh wrote:
 On Sat, Apr 28, 2012 at 11:57:46PM +0200, SomeDude wrote:
 
 What happens the day the language is actually fit for embedded
 programming, and you don't want to have to link against Phobos
 because it's too big ?
We need to fix things so that using a single feature in Phobos will not pull in the entire library. That's an implementation issue, not a language issue. T
It is, but it's actually a very difficult implementation issue. And what I currently see is, many Phobos bugs are simply not corrected, while DMD bugs actually are. It seems that noone but Andrei is working on Phobos. And he is only part time on it. Also, ranges are cool, but they are big. And not everyone wants to have to huge ranges when they can use simpler, and arguably faster arrays. I'm not very satisfied with the current state of Phobos. Being the standard library, it should *work*. Yet it seems to me some things simply don't work at all. The new regex, for instance, I've yet to compile anything with it. The author argues the CTFE is broken, but even the runtime regex doesn't compile. That's not acceptable in a standard library. So before thinking about removing these little features from the core language, thoses issues with Phobos must first be solved.
Apr 28 2012
prev sibling next sibling parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Sat, Apr 28, 2012 at 11:58:19PM +0200, deadalnix wrote:
[...]
  - is is messed up. It is a massive hack and have to be rationalized.
As I said in another thread, the _functionality_ of various is() expressions are very useful and should be kept. But the _syntax_ is completely b0rked and needs some serious redesign.
  - version is a bad version of static if. The static if part of the
 version must go.
What's your proposal?
  - comma expression is confusing and have very little benefice.
+1. I say that D3 should drop the comma operator. Esp. when doing so will open up the way for having native syntax for tuples. Needing to resort to Phobos to have a way to name a compiler-supported type is backwards and silly.
  - out arguments. We can return tuples, out argument is going
 backward in history.
Not when there's no way to name tuples without resorting to Phobos (or copy-n-paste Phobos code).
  - many array properties (.sort for instance) are useless and would
 be way better as libs.
Yeah, .sort is redundant, and besides shouldn't be an array "property" to begin with. T -- What's a "hot crossed bun"? An angry rabbit.
Apr 28 2012
next sibling parent deadalnix <deadalnix gmail.com> writes:
Le 29/04/2012 00:04, H. S. Teoh a écrit :
 On Sat, Apr 28, 2012 at 11:58:19PM +0200, deadalnix wrote:
 [...]
   - is is messed up. It is a massive hack and have to be rationalized.
As I said in another thread, the _functionality_ of various is() expressions are very useful and should be kept. But the _syntax_ is completely b0rked and needs some serious redesign.
That is what I meant.
   - version is a bad version of static if. The static if part of the
 version must go.
What's your proposal?
version(foobar) returning a boolean at compile time for instance.
   - comma expression is confusing and have very little benefice.
+1. I say that D3 should drop the comma operator. Esp. when doing so will open up the way for having native syntax for tuples. Needing to resort to Phobos to have a way to name a compiler-supported type is backwards and silly.
   - out arguments. We can return tuples, out argument is going
 backward in history.
Not when there's no way to name tuples without resorting to Phobos (or copy-n-paste Phobos code).
See how both go together. Remove comma expression, get a nice tuple syntax, and then remove out parameter seems a nice way to go.
Apr 28 2012
prev sibling parent reply =?ISO-8859-1?Q?Alex_R=F8nne_Petersen?= <xtzgzorex gmail.com> writes:
On 29-04-2012 00:04, H. S. Teoh wrote:
 On Sat, Apr 28, 2012 at 11:58:19PM +0200, deadalnix wrote:
 [...]
   - is is messed up. It is a massive hack and have to be rationalized.
As I said in another thread, the _functionality_ of various is() expressions are very useful and should be kept. But the _syntax_ is completely b0rked and needs some serious redesign.
   - version is a bad version of static if. The static if part of the
 version must go.
What's your proposal?
   - comma expression is confusing and have very little benefice.
+1. I say that D3 should drop the comma operator. Esp. when doing so will open up the way for having native syntax for tuples. Needing to resort to Phobos to have a way to name a compiler-supported type is backwards and silly.
   - out arguments. We can return tuples, out argument is going
 backward in history.
Not when there's no way to name tuples without resorting to Phobos (or copy-n-paste Phobos code).
   - many array properties (.sort for instance) are useless and would
 be way better as libs.
Yeah, .sort is redundant, and besides shouldn't be an array "property" to begin with. T
Let's not forget .reverse. Why these are properties (and .dup/.idup) is seriously beyond me..... -- - Alex
Apr 29 2012
next sibling parent deadalnix <deadalnix gmail.com> writes:
Le 29/04/2012 22:40, Alex Rønne Petersen a écrit :
 On 29-04-2012 00:04, H. S. Teoh wrote:
 On Sat, Apr 28, 2012 at 11:58:19PM +0200, deadalnix wrote:
 [...]
 - is is messed up. It is a massive hack and have to be rationalized.
As I said in another thread, the _functionality_ of various is() expressions are very useful and should be kept. But the _syntax_ is completely b0rked and needs some serious redesign.
 - version is a bad version of static if. The static if part of the
 version must go.
What's your proposal?
 - comma expression is confusing and have very little benefice.
+1. I say that D3 should drop the comma operator. Esp. when doing so will open up the way for having native syntax for tuples. Needing to resort to Phobos to have a way to name a compiler-supported type is backwards and silly.
 - out arguments. We can return tuples, out argument is going
 backward in history.
Not when there's no way to name tuples without resorting to Phobos (or copy-n-paste Phobos code).
 - many array properties (.sort for instance) are useless and would
 be way better as libs.
Yeah, .sort is redundant, and besides shouldn't be an array "property" to begin with. T
Let's not forget .reverse. Why these are properties (and .dup/.idup) is seriously beyond me.....
Why they are not provided as lib but by the core language ?
Apr 29 2012
prev sibling parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Sun, Apr 29, 2012 at 10:40:03PM +0200, Alex Rønne Petersen wrote:
 On 29-04-2012 00:04, H. S. Teoh wrote:
[...]
Yeah, .sort is redundant, and besides shouldn't be an array
"property" to begin with.
[...]
 Let's not forget .reverse. Why these are properties (and .dup/.idup)
 is seriously beyond me.....
[...] AFAIK, it's a historical accident. These "properties" date from before people decided to distinguish between methods and properties. T -- "A man's wife has more power over him than the state has." -- Ralph Emerson
Apr 29 2012
prev sibling parent reply "Nick Sabalausky" <SeeWebsiteToContactMe semitwist.com> writes:
"deadalnix" <deadalnix gmail.com> wrote in message 
news:jnhopd$gi3$1 digitalmars.com...
  - out arguments. We can return tuples, out argument is going backward in 
 history.
You can overload on out parameters. You can't overload on return type. So without "out" making an optional output param would be harder to make and uglier to use. That could be even more of a problem if the out param in question is expensive to compute. Also, out is nice when interfacing with C. Returning tuples wouldn't help here. I do agree that maybe we should *prefer* returning tuples over out params (at least once we kill off the useless comma operator and have a concise built-in syntax for tuples), but I don't think tuples are enough to replace out entirely.
Apr 29 2012
next sibling parent reply deadalnix <deadalnix gmail.com> writes:
Le 29/04/2012 21:30, Nick Sabalausky a écrit :
 "deadalnix"<deadalnix gmail.com>  wrote in message
 news:jnhopd$gi3$1 digitalmars.com...
   - out arguments. We can return tuples, out argument is going backward in
 history.
You can overload on out parameters. You can't overload on return type. So without "out" making an optional output param would be harder to make and uglier to use. That could be even more of a problem if the out param in question is expensive to compute.
Good point, but it have many way to work around and shouldn't justify a feature in the core language by itself, especially if, like out parameter, it is a confusing feature.
 Also, out is nice when interfacing with C. Returning tuples wouldn't help
 here.
C don't have out parameters as D have. C have pointer to do kind of out parameters, and D have pointers too, this is a non issue.
Apr 29 2012
parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Sun, Apr 29, 2012 at 11:18:12PM +0200, deadalnix wrote:
[...]
 C don't have out parameters as D have. C have pointer to do kind of
 out parameters, and D have pointers too, this is a non issue.
I argue that using 'out' vs. a pointer is a good thing, because it clarifies intent. When you see a pointer, it's far from clear whether it's an input parameter, an output parameter, or both. More and more, I'm leaning towards the opinion that all code should reveal intent, preferably in a language-supported way. Unclear intent is what leads to subtle bugs caused by people calling functions with wrong assumptions. (You'd think this should be a non-problem with programmers, who are presumably smart enough to figure things out without being told in the face, but I've seen too much "enterprise" code by now to not be cynical about it.) T -- Heuristics are bug-ridden by definition. If they didn't have bugs, they'd be algorithms.
Apr 29 2012
next sibling parent reply "SomeDude" <lovelydear mailmetrash.com> writes:
On Monday, 30 April 2012 at 02:33:35 UTC, H. S. Teoh wrote:
 On Sun, Apr 29, 2012 at 11:18:12PM +0200, deadalnix wrote:
 [...]
 C don't have out parameters as D have. C have pointer to do 
 kind of
 out parameters, and D have pointers too, this is a non issue.
I argue that using 'out' vs. a pointer is a good thing, because it clarifies intent. When you see a pointer, it's far from clear whether it's an input parameter, an output parameter, or both. More and more, I'm leaning towards the opinion that all code should reveal intent, preferably in a language-supported way. Unclear intent is what leads to subtle bugs caused by people calling functions with wrong assumptions. (You'd think this should be a non-problem with programmers, who are presumably smart enough to figure things out without being told in the face, but I've seen too much "enterprise" code by now to not be cynical about it.) T
Of course, a better way would be to change the meaning of the comma operator to allow a Python-style syntax for return values, i.e something like int, Error foo(char[] input, ref Bar){...} auto res, err = foo(input, bar); We would then only allow in and inout parameters. This would be much closer to functional style. There would be no longer any need for the "in" and "out" keywords. If we push a little further, you can also get rid of inout by doing this: int, ref Bar foo(char[] input, ref Bar){...} auto out, bar = foo(input, bar); Every time the compiler sees the same symbol as an input and output parameter, it can assume it's an inout parameter. This, of course, would break a lot of code.
Apr 30 2012
next sibling parent deadalnix <deadalnix gmail.com> writes:
Le 30/04/2012 11:17, SomeDude a écrit :
 On Monday, 30 April 2012 at 02:33:35 UTC, H. S. Teoh wrote:
 On Sun, Apr 29, 2012 at 11:18:12PM +0200, deadalnix wrote:
 [...]
 C don't have out parameters as D have. C have pointer to do kind of
 out parameters, and D have pointers too, this is a non issue.
I argue that using 'out' vs. a pointer is a good thing, because it clarifies intent. When you see a pointer, it's far from clear whether it's an input parameter, an output parameter, or both. More and more, I'm leaning towards the opinion that all code should reveal intent, preferably in a language-supported way. Unclear intent is what leads to subtle bugs caused by people calling functions with wrong assumptions. (You'd think this should be a non-problem with programmers, who are presumably smart enough to figure things out without being told in the face, but I've seen too much "enterprise" code by now to not be cynical about it.) T
Of course, a better way would be to change the meaning of the comma operator to allow a Python-style syntax for return values, i.e something like int, Error foo(char[] input, ref Bar){...} auto res, err = foo(input, bar);
Exactly.
 We would then only allow in and inout parameters. This would be much
 closer to functional style. There would be no longer any need for the
 "in" and "out" keywords.
 If we push a little further, you can also get rid of inout by doing this:

 int, ref Bar foo(char[] input, ref Bar){...}
 auto out, bar = foo(input, bar);

 Every time the compiler sees the same symbol as an input and output
 parameter, it can assume it's an inout parameter. This, of course, would
 break a lot of code.
It isn't a good idea.
Apr 30 2012
prev sibling parent reply "Nick Sabalausky" <SeeWebsiteToContactMe semitwist.com> writes:
"SomeDude" <lovelydear mailmetrash.com> wrote in message 
news:ajdmseliewbindkkoxxj forum.dlang.org...
 [...]There would be no longer any need for the "in" and "out" 
 keywords.[...]
void foo() in{ ... } out{ ... } body{ ... }
Apr 30 2012
parent "SomeDude" <lovelydear mailmetrash.com> writes:
On Monday, 30 April 2012 at 18:32:36 UTC, Nick Sabalausky wrote:
 "SomeDude" <lovelydear mailmetrash.com> wrote in message
 news:ajdmseliewbindkkoxxj forum.dlang.org...
 [...]There would be no longer any need for the "in" and "out" 
 keywords.[...]
void foo() in{ ... } out{ ... } body{ ... }
OKay, I meant in the function signatures
Apr 30 2012
prev sibling parent deadalnix <deadalnix gmail.com> writes:
Le 30/04/2012 04:34, H. S. Teoh a écrit :
 On Sun, Apr 29, 2012 at 11:18:12PM +0200, deadalnix wrote:
 [...]
 C don't have out parameters as D have. C have pointer to do kind of
 out parameters, and D have pointers too, this is a non issue.
I argue that using 'out' vs. a pointer is a good thing, because it clarifies intent. When you see a pointer, it's far from clear whether it's an input parameter, an output parameter, or both. More and more, I'm leaning towards the opinion that all code should reveal intent, preferably in a language-supported way. Unclear intent is what leads to subtle bugs caused by people calling functions with wrong assumptions. (You'd think this should be a non-problem with programmers, who are presumably smart enough to figure things out without being told in the face, but I've seen too much "enterprise" code by now to not be cynical about it.) T
I do agree. However, I don't think this apply in any way to our case. out parameter is a C usage, and it is confusing in C, because, as you mentioned, you don't know if you pass the pointer because it is an out parameter, because you want to avoid copy, because something else . . . The fact that better constructs (ie Tuples) exists in D make it already clear. And if the point is to fix C, it is useless because the whole thing is already confusing in C.
Apr 30 2012
prev sibling parent "foobar" <foo bar.com> writes:
On Sunday, 29 April 2012 at 19:30:24 UTC, Nick Sabalausky wrote:
 "deadalnix" <deadalnix gmail.com> wrote in message
 news:jnhopd$gi3$1 digitalmars.com...
  - out arguments. We can return tuples, out argument is going 
 backward in history.
You can overload on out parameters. You can't overload on return type. So without "out" making an optional output param would be harder to make and uglier to use. That could be even more of a problem if the out param in question is expensive to compute. Also, out is nice when interfacing with C. Returning tuples wouldn't help here. I do agree that maybe we should *prefer* returning tuples over out params (at least once we kill off the useless comma operator and have a concise built-in syntax for tuples), but I don't think tuples are enough to replace out entirely.
Well the functional way would be to use Option types as in: Tuple!(int, Option!ExpensiveType) foobar(bool cond) { if (cond) return tuple(0, newExpensiveType()); else return tuple(-1, Option.None); } I prefer the above as it's more readable IMO (we REALLY should get a much better tuple syntax though ....) I do agree that this won't work when interfacing with C but IMO we shouldn't design D around limitations of C.
Apr 30 2012
prev sibling next sibling parent deadalnix <deadalnix gmail.com> writes:
Le 28/04/2012 20:47, Walter Bright a écrit :
 Andrei and I had a fun discussion last night about this question. The
 idea was which features in D are redundant and/or do not add significant
 value?

 A couple already agreed upon ones are typedef and the cfloat, cdouble
 and creal types.

 What's your list?
Ho god D is HUGE ! OK a last one, synchronized on objects. Most of them are not even shared so it is useless, and is is bad separation of concerns between OOP and multithreading. If you want a mutex, declaring it explicitly is the best option.
Apr 28 2012
prev sibling next sibling parent reply "F i L" <witte2008 gmail.com> writes:
On Saturday, 28 April 2012 at 18:48:18 UTC, Walter Bright wrote:
 Andrei and I had a fun discussion last night about this 
 question. The idea was which features in D are redundant and/or 
 do not add significant value?

 A couple already agreed upon ones are typedef and the cfloat, 
 cdouble and creal types.

 What's your list?
First, I completely agree with some points already made here, and I completely disagree with a few others. A modern compiler should be as powerful and convenient as possible, I completely disagree that a compiler can't do a broad range of things very efficiently _and_ with a smooth learning. Indeed this is what attracted me to D in the first place, the idea that it has the low level power of C++ when you get down to it, but it's also attractive and initially easy to use. What I think should be removed/changed: - Drop is( ... ) and extend "__traits()" (however "__traits" should become .metaof or something along those lines). Also, a easy to understand traits lib should be imported by default like Object.d - Enum as manifest constant - I agree, this is better as "static x = 10" or equivalent. I was actually confused at first when I realized enum's where what was *supposed* to be used for that. - foreach_reverse. Dmitry's gave a good alternative. Though, I think a more intelligent 'foreach' (or even 'for') statement could address this as well. Something like: for (key, value of range, step) { ... } // Where step values which can be deduced at compile time // are used to produce the most optimizated code. - version statements - this would be a lot more consistent as a static if() I think. But it does need a more obvious syntax, possibly something like: static if ("foo" in Compiler.flags) { ... } - .di files - I agree with foobar here. Other language have had this for awhile, and it makes linking a much easier concept. - NaN as default - I've said this before on here, but I think it deserves being said again. FP values defaulting to Nan is a debugging feature, and should be explicitly expressed in areas which need to guarantee a variable is set after declaration. A useful, and consistent default should be used instead. Ints (the other number type) default to zero, and because zero is the most practical and commonly understood, FP values should start here as well. - commas - should be use for tuples and parameters, not as ending marks: int, int foo() { return 5, 6; } auto x, y = 2; // x = 0, y = 2 auto x, y = 2, 3; // x = 2, y = 3 x, y = foo(); // x = 5, y = 6 What should stay: - foreach (or an intelligent 'for' as exampled above). This is an incredibly convenient, tried 'n true feature. - built-in Associative Arrays - one of D's sexiest features. It's very useful for many things, and always having it at your disposal is a logical choice. - properties - another incredibly convenient feature. I think a more sexy implementation of properties are in order, but the construct is great. It would be nice to have properties as a language type, rather than a attribute: struct Foo { property int x { get; private set; } property int y { get() { return x; } set(T t) { x = t; } } } // Or the syntax could follow Types: property x : int { ... } // Which could be templated: property y(T = int) : int { static if (T.isType!int) { ... } else { ... } } - with statement - no reason to kill it really and it's useful in some places. Helps keep code short and readable. - Anonymous class - There's no reason to remove this feature, it's not hurting anyone and it could allow for interesting frameworks similar to jQuery. Other things that would be cool: - static foreach
Apr 28 2012
next sibling parent Manu <turkeyman gmail.com> writes:
On 29 April 2012 01:09, F i L <witte2008 gmail.com> wrote:

 On Saturday, 28 April 2012 at 18:48:18 UTC, Walter Bright wrote:

 Andrei and I had a fun discussion last night about this question. The
 idea was which features in D are redundant and/or do not add significant
 value?

 A couple already agreed upon ones are typedef and the cfloat, cdouble and
 creal types.

 What's your list?
First, I completely agree with some points already made here, and I completely disagree with a few others. A modern compiler should be as powerful and convenient as possible, I completely disagree that a compiler can't do a broad range of things very efficiently _and_ with a smooth learning. Indeed this is what attracted me to D in the first place, the idea that it has the low level power of C++ when you get down to it, but it's also attractive and initially easy to use. What I think should be removed/changed: - Drop is( ... ) and extend "__traits()" (however "__traits" should become .metaof or something along those lines). Also, a easy to understand traits lib should be imported by default like Object.d - Enum as manifest constant - I agree, this is better as "static x = 10" or equivalent. I was actually confused at first when I realized enum's where what was *supposed* to be used for that. - foreach_reverse. Dmitry's gave a good alternative. Though, I think a more intelligent 'foreach' (or even 'for') statement could address this as well. Something like: for (key, value of range, step) { ... } // Where step values which can be deduced at compile time // are used to produce the most optimizated code. - version statements - this would be a lot more consistent as a static if() I think. But it does need a more obvious syntax, possibly something like: static if ("foo" in Compiler.flags) { ... } - .di files - I agree with foobar here. Other language have had this for awhile, and it makes linking a much easier concept. - NaN as default - I've said this before on here, but I think it deserves being said again. FP values defaulting to Nan is a debugging feature, and should be explicitly expressed in areas which need to guarantee a variable is set after declaration. A useful, and consistent default should be used instead. Ints (the other number type) default to zero, and because zero is the most practical and commonly understood, FP values should start here as well. - commas - should be use for tuples and parameters, not as ending marks: int, int foo() { return 5, 6; } auto x, y = 2; // x = 0, y = 2 auto x, y = 2, 3; // x = 2, y = 3 x, y = foo(); // x = 5, y = 6 What should stay: - foreach (or an intelligent 'for' as exampled above). This is an incredibly convenient, tried 'n true feature. - built-in Associative Arrays - one of D's sexiest features. It's very useful for many things, and always having it at your disposal is a logical choice. - properties - another incredibly convenient feature. I think a more sexy implementation of properties are in order, but the construct is great. It would be nice to have properties as a language type, rather than a attribute: struct Foo { property int x { get; private set; } property int y { get() { return x; } set(T t) { x = t; } } } // Or the syntax could follow Types: property x : int { ... } // Which could be templated: property y(T = int) : int { static if (T.isType!int) { ... } else { ... } } - with statement - no reason to kill it really and it's useful in some places. Helps keep code short and readable. - Anonymous class - There's no reason to remove this feature, it's not hurting anyone and it could allow for interesting frameworks similar to jQuery. Other things that would be cool: - static foreach
Hear hear. I completely agree with everything you just said.
Apr 28 2012
prev sibling next sibling parent reply "Francois Chabot" <francois.chabot.dev gmail.com> writes:
 - properties - another incredibly convenient feature. I think a 
 more sexy implementation of properties are in order, but the 
 construct is great. It would be nice to have properties as a 
 language type, rather than a attribute:
To me, properties are much more than a convenience. The important part of it comes from its existence, not its usage. Quite simply, having properties mean that using public member variables does not break encapsulation (as long as having them part of the public interface is intentional). Without properties, you MUST write accessors for all of them on the off chance that you might want to refactor/delegate them in the future. This adds a huge amount of boilerplate code that ends up wasted time 98% of the time. In short, properties existing, even if not used, end up improving both my efficiency and the legibility of my code.
Apr 28 2012
parent reply Jacob Carlborg <doob me.com> writes:
On 2012-04-29 04:32, Francois Chabot wrote:
 - properties - another incredibly convenient feature. I think a more
 sexy implementation of properties are in order, but the construct is
 great. It would be nice to have properties as a language type, rather
 than a attribute:
To me, properties are much more than a convenience. The important part of it comes from its existence, not its usage. Quite simply, having properties mean that using public member variables does not break encapsulation (as long as having them part of the public interface is intentional). Without properties, you MUST write accessors for all of them on the off chance that you might want to refactor/delegate them in the future. This adds a huge amount of boilerplate code that ends up wasted time 98% of the time. In short, properties existing, even if not used, end up improving both my efficiency and the legibility of my code.
In principle I agree with you. But in practice this doesn't always work. Take this for example: struct Point { int x; int y; } class Widget { Point point; } void main() { auto w = new Widget; writeln(w.point.x); w.point.x++; writeln(w.point.x); } Prints "0" and "1" as expected. If we now change "point" to a property like this: class Widget { //Point point; Point point_; property Point point () { return point_; } property Point point (Point point) { return point_ = point; } } It will now print "0" and "0". This is a silently breaking change. Sure you can change "point" to return by reference: class Widget { Point point_; property ref Point point () { return point_; } property ref Point point (Point point) { writeln("foo"); point_ = point; return point_; } } Which will print "0" and "1" again. But it won't print "foo", meaning you bypassed the getter. To solve this the compiler would need to perform some kind of property rewriting. Translating: w.point.x++; To: auto __p = w.point; __p.x++; w.point = __p; Also you might need to just as well use properties from the beginning because you need virtual properties. It would help if this was allowed: class Widget { property Point point; } Which would translate to: property Point point () { return point_; } property Point point (Point point) { return point_ = point; } -- /Jacob Carlborg
Apr 29 2012
next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 4/29/12, Jacob Carlborg <doob me.com> wrote:
 In principle I agree with you. But in practice this doesn't always work.
 Take this for example:
 Prints "0" and "1" as expected. If we now change "point" to a property
 like this:
 It will now print "0" and "0". This is a silently breaking change. Sure
 you can change "point" to return by reference..
This is a great point and an issue I've ran into and talked about before. The compiler really ought to try and convert a call like this: foo.property++; foo.property+=10; into e.g.: foo.property = foo.property.opAdd(1); foo.property = foo.property.opAdd(10); It would make for some really nice APIs if this feature was available. Otherwise I have to resort to template magic and delegate calls such as: class Widget { Notify!Point pos; this() { pos.init(&posSet); } // if pos changes, invoke posChange void posChange(ref Point newPos) { newPos.normalize(); } // e.g. if out of bounds } Unfortunately that template broke in an earlier compiler regression that I haven't noticed until recently (http://d.puremagic.com/issues/show_bug.cgi?id=7991)
Apr 29 2012
prev sibling parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Sun, Apr 29, 2012 at 08:42:23PM +0200, Andrej Mitrovic wrote:
 On 4/29/12, Jacob Carlborg <doob me.com> wrote:
 In principle I agree with you. But in practice this doesn't always
 work.  Take this for example: Prints "0" and "1" as expected. If we
 now change "point" to a property like this: It will now print "0"
 and "0". This is a silently breaking change. Sure you can change
 "point" to return by reference..
This is a great point and an issue I've ran into and talked about before. The compiler really ought to try and convert a call like this: foo.property++; foo.property+=10; into e.g.: foo.property = foo.property.opAdd(1); foo.property = foo.property.opAdd(10); It would make for some really nice APIs if this feature was available.
[...] To me, the compiler needs to be fixed so that anytime the return value of a property is used as an lvalue, it should always try to call the setter function, or some kind of setter function, instead of the getter (unless there's no setter, in which case it's OK to call the getter). I chalk this up to a compiler issue, not a language issue. T -- Let X be the set not defined by this sentence...
Apr 29 2012
parent =?ISO-8859-1?Q?Alex_R=F8nne_Petersen?= <xtzgzorex gmail.com> writes:
On 30-04-2012 04:37, H. S. Teoh wrote:
 On Sun, Apr 29, 2012 at 08:42:23PM +0200, Andrej Mitrovic wrote:
 On 4/29/12, Jacob Carlborg<doob me.com>  wrote:
 In principle I agree with you. But in practice this doesn't always
 work.  Take this for example: Prints "0" and "1" as expected. If we
 now change "point" to a property like this: It will now print "0"
 and "0". This is a silently breaking change. Sure you can change
 "point" to return by reference..
This is a great point and an issue I've ran into and talked about before. The compiler really ought to try and convert a call like this: foo.property++; foo.property+=10; into e.g.: foo.property = foo.property.opAdd(1); foo.property = foo.property.opAdd(10); It would make for some really nice APIs if this feature was available.
[...] To me, the compiler needs to be fixed so that anytime the return value of a property is used as an lvalue, it should always try to call the setter function, or some kind of setter function, instead of the getter (unless there's no setter, in which case it's OK to call the getter). I chalk this up to a compiler issue, not a language issue. T
What you just talked about = semantics. So, it is a language issue. -- - Alex
Apr 29 2012
prev sibling parent reply "Nick Sabalausky" <SeeWebsiteToContactMe semitwist.com> writes:
"F i L" <witte2008 gmail.com> wrote in message 
news:oakvbobsvtawtdcasglk forum.dlang.org...
 Other things that would be cool:

 - static foreach
We sort of do: // Unrolled at compile-time foreach(T; TypeTuple!(int, string, BigInt)) { ... } I'm not sure that's valid outside a function, though.
Apr 29 2012
parent "bearophile" <bearophileHUGS lycos.com> writes:
Nick Sabalausky:

 I'm not sure that's valid outside a function, though.
It doesn't work outside functions. More info: http://d.puremagic.com/issues/show_bug.cgi?id=4085 Bye, bearophile
Apr 29 2012
prev sibling next sibling parent reply Manu <turkeyman gmail.com> writes:
On 28 April 2012 21:47, Walter Bright <newshound2 digitalmars.com> wrote:

 Andrei and I had a fun discussion last night about this question. The idea
 was which features in D are redundant and/or do not add significant value?

 A couple already agreed upon ones are typedef and the cfloat, cdouble and
 creal types.

 What's your list?
I personally find the wealth of features in D to be one of it's major selling points. It helps simplify user code a lot, but I think there is room for some things to be more consistent: * version refuses to allow boolean logic, I need boolean logic, thus version is redundant to me. I find myself using static if almost exclusively in its place. I like the *idea*, but it's un-usably limited. * Consolidation of meta/introspection: __traits(), std.traits, is(), and a few other tricks, I often don't know where I should look to perform a particular introspection task. __traits is unsightly, it looks more like a hack rather than a feature, but it fills perhaps one of the most vital roles in the language. * D has a lot of attributes, many of which I haven't used + don't understand. I suspect many of them could be removed and implemented in the library with a proper user attribute system (which would be really useful to compliment D's introspection anyway). This would also free those keywords when those libraries aren't imported/used. * I don't know the value of AA's in the language, I've only used them once or twice. Because AA's can be implemented in numerous ways (map, hash table, etc), and may be ordered or unordered, the the choice of which to use is actually important to the problem more often than not. As long as the same convenience can be achieved in the library (literal expression?), maybe it should be there.
Apr 28 2012
parent =?UTF-8?B?QWxleCBSw7hubmUgUGV0ZXJzZW4=?= <xtzgzorex gmail.com> writes:
On 29-04-2012 00:18, Manu wrote:
 On 28 April 2012 21:47, Walter Bright <newshound2 digitalmars.com
 <mailto:newshound2 digitalmars.com>> wrote:

     Andrei and I had a fun discussion last night about this question.
     The idea was which features in D are redundant and/or do not add
     significant value?

     A couple already agreed upon ones are typedef and the cfloat,
     cdouble and creal types.

     What's your list?


 I personally find the wealth of features in D to be one of it's major
 selling points. It helps simplify user code a lot, but I think there is
 room for some things to be more consistent:

 * version refuses to allow boolean logic, I need boolean logic, thus
 version is redundant to me. I find myself using static if almost
 exclusively in its place. I like the *idea*, but it's un-usably limited.
+1.
 * Consolidation of meta/introspection: __traits(), std.traits, is(), and
 a few other tricks, I often don't know where I should look to perform a
 particular introspection task. __traits is unsightly, it looks more like
 a hack rather than a feature, but it fills perhaps one of the most vital
 roles in the language.
 * D has a lot of attributes, many of which I haven't used + don't
 understand. I suspect many of them could be removed and implemented in
 the library with a proper user attribute system (which would be really
 useful to compliment D's introspection anyway). This would also free
 those keywords when those libraries aren't imported/used.
 * I don't know the value of AA's in the language, I've only used them
 once or twice. Because AA's can be implemented in numerous ways (map,
 hash table, etc), and may be ordered or unordered, the the choice of
 which to use is actually important to the problem more often than not.
 As long as the same convenience can be achieved in the library (literal
 expression?), maybe it should be there.
-- - Alex
Apr 29 2012
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Saturday, April 28, 2012 13:43:27 H. S. Teoh wrote:
 D has typedef?? Wow. And I thought I had a good grasp of D.
It did, but it won't. It's either already been deprecated or will be soon. - Jonathan M Davis
Apr 28 2012
prev sibling next sibling parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On Saturday, April 28, 2012 11:47:31 Walter Bright wrote:
 Andrei and I had a fun discussion last night about this question. The idea
 was which features in D are redundant and/or do not add significant value?
 
 A couple already agreed upon ones are typedef and the cfloat, cdouble and
 creal types.
 
 What's your list?
Well, that's a hard one. There isn't much in the language that I'd remove even if we were doing a complete redesign without caring about backwards compatibility. Most of the stuff that I'd change is already being (or has been) changed. And while D isn't exactly big, it doesn't tend to have dark corners like C++ does. I'm sure that I don't fully grasp everything in D, but it's fairly rare that I run into something that surprises me or that I thought that I understood but don't (though it still does happen sometimes). With C++, it always feels like there's some new detail that pops up that I didn't have a clue about - or that maybe I _did_ know about but had forgotten because of the insane number of little details that C++ has. One _big_ difference between D and C++ as far as complexity goes is that in C++, a _lot_ of the complexity comes from weird things in the language and knowing about how certain things can go horribly wrong (e.g. I can never remember all of the details on how horribly broken multiple inheritence is). It's frequently not an issue of knowing how to do things in the language but rather an issue of knowing what weird side effects an problems happen with certain stuff. With D, on the other hand, the complexity tends to be in just knowing what all of the features are and what they can do. The only feature that comes to mind as probably being overly complex is is expressions, but that complexity can really come in handy sometimes. std.traits should probably do more to alleviate the need for is expressions though so that odds of needing some of the more complicated stuff are lessened. * As for redundant features, the first one that really comes to mind is WYSIWYG string literals. There are what, 4 different types of delimiters for string literals? I don't even remember all of the options. I just always use ` if I don't want any escaping in string literal and " if I do. The others may be valuable enough to have in some contexts, but I _never_ use them. * version vs static if seems kind of redundant, but it isn't really. version is used for a very specific subset of conditional code compilation, and you can define versions on the command line, whereas static if generally checks code properties (like if a type meets certain conditions). So, I think that they should probably be left as is. There would be some value in allowing a list of versions to be given (rather than using logical operators) in order to avoid duplicate code - e.g. version(linux, FreeBSD) {} else version(MacOSX) {} else version(Windows) {} else static assert(0); but that's about the only thing that I'd change with version. And I wouldn't want to get rid of it. * foreach_reverse is essentially redudant at this point (not to mention confusing if combined with delegates), since we have retro. But we might already be planning to get rid of that. I'm not sure though. * I hate C style struct initializers and would really like to see them go, but for reasons that I don't understand, people actually use them rather than using a proper constructor call, so I doubt that we could get rid of them without a fair bit of complaining. I think that they're completely redundant and very _un_D. * There seem to be too many ways to do variadic functions. We have to allow C style variadics for extern(C), but having 3 of our own seems like a bit much. Variadic templates are generally all that we need. The others don't seem necessary for the most part. But unfortunately, they should probably be left in so that classes can use them with virtual functions, since they can't use templates. * As for features that add little value, the first one that comes to mind is with. I think that I've used it all of once, and I don't think that I've seen it in other people's code very often. It's hard to grep for (since with is used in comments quite often), but it wouldn't surprise me at all if Phobos doesn't use it at all. Also, I fear that not only does it add little value but that it has a tendency to make code less readable. * Increasingly, I don't like UFCS. I think that in most cases, it complicates code for little value. And I _really_ don't like how it results in people flipping chains of a(b(c(d(5)))) calls into something like d(5).c().b.().a(). I think that it makes the code way harder to read. The code is completely backwards. But I appear to be in the minority with that opinion. I also don't like how it creates so many ways to write exactly the same code. It harms readibility. But as much as I dislike many of the applications of UFCS, it _does_ appear to be quite popular. And upon occasion, it may be useful, but I _am_ wishing that we hadn't added it. There are definitely features that I never use (e.g. opDispatch), but for the most part, I think that they're stuff that adds real value for certain types of stuff that I just don't do, so removing them wouldn't really make any sense. Overall, I think that D's feature set is fairly solid. It's mostly just the implementation of said features which is a problem - though some minor tweaks are probably in order (e.g. as Bearophile suggests, make it so that adjacent string literals don't concatenate). - Jonathan M Davis
Apr 28 2012
parent reply "bearophile" <bearophileHUGS lycos.com> writes:
Jonathan M Davis:

 * foreach_reverse is essentially redudant at this point (not to 
 mention
 confusing if combined with delegates), since we have retro.
retro() can't replace foreach_reverse until the front-end demonstrability produces asm code equally efficient. Loops _must_ be fully efficient, they are a basic language construct, this is very important. Even foreach() is sometimes not equally efficient as a for() in some cases...
 * I hate C style struct initializers and would really like to 
 see them go, but
 for reasons that I don't understand, people actually use them 
 rather than using a proper constructor call,
For single structs I prefer D-style initialization. But take a look at this code, if you replace those C-style initializers with D-style, even using aliases to shorten the code to single letters, that data section becomes more noisy: http://rosettacode.org/wiki/Ray-casting_algorithm#D
 * As for features that add little value, the first one that 
 comes to mind is
 with. I think that I've used it all of once, and I don't think 
 that I've seen
 it in other people's code very often.
It's rather common in Pascal/Delphi programming. I use it now and then. For a case where it's very handy see here, with an enumeration: http://rosettacode.org/wiki/Stable_marriage_problem#Alternative_version
 It's hard to grep for (since with is
 used in comments quite often),
Try to search for "with(" or "with\s(", that are less common in normal text.
 * Increasingly, I don't like UFCS. I think that in most cases, 
 it complicates
 code for little value. And I _really_ don't like how it results 
 in people
 flipping chains of a(b(c(d(5)))) calls into something like 
 d(5).c().b.().a(). I
 think that it makes the code way harder to read.
For me it makes that kind of code way simpler to read...
 The code is completely backwards.
It means call d on 5, then call c on the result, then call b on the result, and then call a on the result. It's better than before :-) Bye, bearophile
Apr 28 2012
next sibling parent "Era Scarecrow" <rtcvb32 yahoo.com> writes:
On Sunday, 29 April 2012 at 01:06:54 UTC, bearophile wrote:
 * I hate C style struct initializers and would really like to 
 see them go, but
 for reasons that I don't understand, people actually use them 
 rather than using a proper constructor call,
For single structs I prefer D-style initialization. But take a look at this code, if you replace those C-style initializers with D-style, even using aliases to shorten the code to single letters, that data section becomes more noisy: http://rosettacode.org/wiki/Ray-casting_algorithm#D
I have one source file called staticdata.d; Here immutable global data is stored. It's literally pages and pages of data and i only using static this() when building an AA. //excerpt: /NP and VT aliases. immutable SubRecordParts subParts[] = [ {"AADT", "", 16, [ //alchemy (apparatus) NP(VT.ranged_32, "Apparatus"), NP(VT.float_32, "Quality"), NP(VT.float_32, "Weight"), NP(VT.i_32, "uses")]}, {"AODT", "", 24, [ //armor NP(VT.ranged_32, "Armor Body Type"), NP(VT.float_32, "Weight"), NP(VT.i_32, "Value"), NP(VT.i_32, "Health"), NP(VT.i_32, "Enchant Points"), NP(VT.i_32, "Armour")]}, {"BKDT", "", 20, [ //book NP(VT.float_32, "Weight"), NP(VT.i_32, "Value"), NP(VT.i_32, "isScroll"), NP(VT.ranged_32, "Skill ID"), NP(VT.i_32, "Enchantment points")]}]; Would you really force me to use fully named and qualified for every element? More verbose but helps not at all. immutable SubRecordParts subParts[] = [ SubRecordParts("AADT", "", 16, [ //alchemy (apparatus) NotePart(ValueType.ranged_32, "Apparatus"), NotePart(ValueType.float_32, "Quality"), NotePart(ValueType.float_32, "Weight"), NotePart(ValueType.i_32, "uses")]), SubRecordParts("AODT", "", 24, [ //armor NotePart(ValueType.ranged_32, "Armor Body Type"), NotePart(ValueType.float_32, "Weight"), NotePart(ValueType.i_32, "Value"), NotePart(ValueType.i_32, "Health"), NotePart(ValueType.i_32, "Enchant Points"), NotePart(ValueType.i_32, "Armour")]), SubRecordParts("BKDT", "", 20, [ //book NotePart(ValueType.float_32, "Weight"), NotePart(ValueType.i_32, "Value"), NotePart(ValueType.i_32, "isScroll"), NotePart(ValueType.ranged_32, "Skill ID"), NotePart(ValueType.i_32, "Enchantment points")]) ];
Apr 28 2012
prev sibling next sibling parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On Sunday, April 29, 2012 03:06:53 bearophile wrote:
 * Increasingly, I don't like UFCS. I think that in most cases,
 it complicates
 code for little value. And I _really_ don't like how it results
 in people
 flipping chains of a(b(c(d(5)))) calls into something like
 d(5).c().b.().a(). I
 think that it makes the code way harder to read.
For me it makes that kind of code way simpler to read...
 The code is completely backwards.
It means call d on 5, then call c on the result, then call b on the result, and then call a on the result. It's better than before :-)
I know that you find easier to read. A number of people do. But it is just so backwards in comparison to how stuff normally works, that it hurts my brain. But I've done enough functional programming that I find something likea(b(c(d(5)))) to be completely straightforward, and for some reason not everyone does. And while I _never_ intend to use UFCS in this manner, I'm going to forever have to read the code of others who do, which I find to be a major negative. But regardless of my personal opinion on the matter, it's clear that enough people like UFCS that it's not going anywhere unless something seriously wrong is found with it which makes it untenable. - Jonathan M Davis
Apr 28 2012
parent =?UTF-8?B?QWxleCBSw7hubmUgUGV0ZXJzZW4=?= <xtzgzorex gmail.com> writes:
On 29-04-2012 03:40, Jonathan M Davis wrote:
 On Sunday, April 29, 2012 03:06:53 bearophile wrote:
 * Increasingly, I don't like UFCS. I think that in most cases,
 it complicates
 code for little value. And I _really_ don't like how it results
 in people
 flipping chains of a(b(c(d(5)))) calls into something like
 d(5).c().b.().a(). I
 think that it makes the code way harder to read.
For me it makes that kind of code way simpler to read...
 The code is completely backwards.
It means call d on 5, then call c on the result, then call b on the result, and then call a on the result. It's better than before :-)
I know that you find easier to read. A number of people do. But it is just so backwards in comparison to how stuff normally works, that it hurts my brain. But I've done enough functional programming that I find something likea(b(c(d(5)))) to be completely straightforward, and for some reason not everyone does. And while I _never_ intend to use UFCS in this manner, I'm going to forever have to read the code of others who do, which I find to be a major negative.
like |> and <|.
 But regardless of my personal opinion on the matter, it's clear that enough
 people like UFCS that it's not going anywhere unless something seriously wrong
 is found with it which makes it untenable.

 - Jonathan M Davis
-- - Alex
Apr 29 2012
prev sibling next sibling parent reply Dmitry Olshansky <dmitry.olsh gmail.com> writes:
On 29.04.2012 5:06, bearophile wrote:
 Jonathan M Davis:

 * foreach_reverse is essentially redudant at this point (not to mention
 confusing if combined with delegates), since we have retro.
retro() can't replace foreach_reverse until the front-end demonstrability produces asm code equally efficient.
bleh C++ doesn't have reverse loop in the language. all there is rbegin() and rend(). And this attitude reminds me of the old STL days. What's wrong with you people? Am I back to 90s ?
 Loops _must_ be fully efficient, they are a basic language construct,
 this is very important. Even foreach() is sometimes not equally
 efficient as a for() in some cases...
Doesn't have to do anything with the LANGUAGE. Yesterday I tried GDC. Damn I didn't regret it :)
 * I hate C style struct initializers and would really like to see them
 go, but
 for reasons that I don't understand, people actually use them rather
 than using a proper constructor call,
For single structs I prefer D-style initialization. But take a look at this code, if you replace those C-style initializers with D-style, even using aliases to shorten the code to single letters, that data section becomes more noisy: http://rosettacode.org/wiki/Ray-casting_algorithm#D
Such code (tables) is usually generated anyway. [snip reasonable parts ;)] -- Dmitry Olshansky
Apr 28 2012
parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Sun, Apr 29, 2012 at 10:03:43AM +0400, Dmitry Olshansky wrote:
 On 29.04.2012 5:06, bearophile wrote:
[...]
Loops _must_ be fully efficient, they are a basic language construct,
this is very important. Even foreach() is sometimes not equally
efficient as a for() in some cases...
Doesn't have to do anything with the LANGUAGE. Yesterday I tried GDC. Damn I didn't regret it :)
[...] Unfortunately, even GDC doesn't inline opApply and its delegate for the simplest of loops: struct S { int data[]; int opApply(int delegate(ref int) dg) { foreach (d; data) { if (auto r = dg(d)) return r; } return 0; } } void main() { S s; foreach (e; s) { writeln(e); } } I think it's because the front-end always generates the full delegate passing code without inlining anything. IMO, this case *need* to be aggressively inlined in order to make D's generic programming capabilities a stronger selling point. T -- "Computer Science is no more about computers than astronomy is about telescopes." -- E.W. Dijkstra
Apr 29 2012
parent deadalnix <deadalnix gmail.com> writes:
Le 30/04/2012 04:52, H. S. Teoh a écrit :
 On Sun, Apr 29, 2012 at 10:03:43AM +0400, Dmitry Olshansky wrote:
 On 29.04.2012 5:06, bearophile wrote:
[...]
 Loops _must_ be fully efficient, they are a basic language construct,
 this is very important. Even foreach() is sometimes not equally
 efficient as a for() in some cases...
Doesn't have to do anything with the LANGUAGE. Yesterday I tried GDC. Damn I didn't regret it :)
[...] Unfortunately, even GDC doesn't inline opApply and its delegate for the simplest of loops: struct S { int data[]; int opApply(int delegate(ref int) dg) { foreach (d; data) { if (auto r = dg(d)) return r; } return 0; } } void main() { S s; foreach (e; s) { writeln(e); } } I think it's because the front-end always generates the full delegate passing code without inlining anything. IMO, this case *need* to be aggressively inlined in order to make D's generic programming capabilities a stronger selling point. T
It is an implementation issue (a real and serious one, but still). It should be fixed by implementation, not language design.
Apr 30 2012
prev sibling next sibling parent "David Nadlinger" <see klickverbot.at> writes:
On Sunday, 29 April 2012 at 01:06:54 UTC, bearophile wrote:
 retro() can't replace foreach_reverse until the front-end 
 demonstrability produces asm code equally efficient.
 Loops _must_ be fully efficient, they are a basic language 
 construct, this is very important. Even foreach() is sometimes 
 not equally efficient as a for() in some cases...
Slightly related: For this: --- import core.stdc.stdio; import std.algorithm; import std.range; void main() { int sum; foreach (i; retro(iota(11))) sum += i; printf("%d\n", sum); } --- LDC produces --- __Dmain: pushq %rax movl $0x00000037,%esi xorb %al,%al callq _printf xorl %esi,%esi movl %eax,0x04(%rsp) movl %esi,%eax popq %rdx ret --- Now that's constant folding… ;) David
Apr 29 2012
prev sibling next sibling parent =?UTF-8?B?QWxleCBSw7hubmUgUGV0ZXJzZW4=?= <xtzgzorex gmail.com> writes:
On 29-04-2012 03:06, bearophile wrote:
 Jonathan M Davis:

 * foreach_reverse is essentially redudant at this point (not to mention
 confusing if combined with delegates), since we have retro.
retro() can't replace foreach_reverse until the front-end demonstrability produces asm code equally efficient. Loops _must_ be fully efficient, they are a basic language construct, this is very important. Even foreach() is sometimes not equally efficient as a for() in some cases...
 * I hate C style struct initializers and would really like to see them
 go, but
 for reasons that I don't understand, people actually use them rather
 than using a proper constructor call,
For single structs I prefer D-style initialization. But take a look at this code, if you replace those C-style initializers with D-style, even using aliases to shorten the code to single letters, that data section becomes more noisy: http://rosettacode.org/wiki/Ray-casting_algorithm#D
 * As for features that add little value, the first one that comes to
 mind is
 with. I think that I've used it all of once, and I don't think that
 I've seen
 it in other people's code very often.
It's rather common in Pascal/Delphi programming. I use it now and then. For a case where it's very handy see here, with an enumeration: http://rosettacode.org/wiki/Stable_marriage_problem#Alternative_version
 It's hard to grep for (since with is
 used in comments quite often),
Try to search for "with(" or "with\s(", that are less common in normal text.
 * Increasingly, I don't like UFCS. I think that in most cases, it
 complicates
 code for little value. And I _really_ don't like how it results in people
 flipping chains of a(b(c(d(5)))) calls into something like
 d(5).c().b.().a(). I
 think that it makes the code way harder to read.
For me it makes that kind of code way simpler to read...
Completely agree.
 The code is completely backwards.
It means call d on 5, then call c on the result, then call b on the result, and then call a on the result. It's better than before :-)
Amen.
 Bye,
 bearophile
-- - Alex
Apr 29 2012
prev sibling next sibling parent reply deadalnix <deadalnix gmail.com> writes:
Le 29/04/2012 03:06, bearophile a écrit :
 Jonathan M Davis:

 * foreach_reverse is essentially redudant at this point (not to mention
 confusing if combined with delegates), since we have retro.
retro() can't replace foreach_reverse until the front-end demonstrability produces asm code equally efficient. Loops _must_ be fully efficient, they are a basic language construct, this is very important. Even foreach() is sometimes not equally efficient as a for() in some cases...
This is an implementation issue and shouldn't be an argument for language design.
Apr 29 2012
parent reply "Peter Alexander" <peter.alexander.au gmail.com> writes:
On Sunday, 29 April 2012 at 21:18:40 UTC, deadalnix wrote:
 Le 29/04/2012 03:06, bearophile a écrit :
 Jonathan M Davis:

 * foreach_reverse is essentially redudant at this point (not 
 to mention
 confusing if combined with delegates), since we have retro.
retro() can't replace foreach_reverse until the front-end demonstrability produces asm code equally efficient. Loops _must_ be fully efficient, they are a basic language construct, this is very important. Even foreach() is sometimes not equally efficient as a for() in some cases...
This is an implementation issue and shouldn't be an argument for language design.
The 'sufficiently smart compiler' argument is old and invalid. Please do not use it.
Apr 29 2012
next sibling parent =?UTF-8?B?QWxleCBSw7hubmUgUGV0ZXJzZW4=?= <xtzgzorex gmail.com> writes:
On 29-04-2012 23:54, Peter Alexander wrote:
 On Sunday, 29 April 2012 at 21:18:40 UTC, deadalnix wrote:
 Le 29/04/2012 03:06, bearophile a écrit :
 Jonathan M Davis:

 * foreach_reverse is essentially redudant at this point (not to mention
 confusing if combined with delegates), since we have retro.
retro() can't replace foreach_reverse until the front-end demonstrability produces asm code equally efficient. Loops _must_ be fully efficient, they are a basic language construct, this is very important. Even foreach() is sometimes not equally efficient as a for() in some cases...
This is an implementation issue and shouldn't be an argument for language design.
The 'sufficiently smart compiler' argument is old and invalid. Please do not use it.
Indeed; at some point, you have to admit that implementation will have some impact on design. We don't live an ideal world, unfortunately. ;) -- - Alex
Apr 29 2012
prev sibling next sibling parent reply Dmitry Olshansky <dmitry.olsh gmail.com> writes:
On 30.04.2012 1:54, Peter Alexander wrote:
 On Sunday, 29 April 2012 at 21:18:40 UTC, deadalnix wrote:
 Le 29/04/2012 03:06, bearophile a écrit :
 Jonathan M Davis:

 * foreach_reverse is essentially redudant at this point (not to mention
 confusing if combined with delegates), since we have retro.
retro() can't replace foreach_reverse until the front-end demonstrability produces asm code equally efficient. Loops _must_ be fully efficient, they are a basic language construct, this is very important. Even foreach() is sometimes not equally efficient as a for() in some cases...
This is an implementation issue and shouldn't be an argument for language design.
The 'sufficiently smart compiler' argument is old and invalid. Please do not use it.
Right, nowdays any compiler is either smart enough or a dead meat that nobody uses. P.S. dmd is kind of work in progress ;) -- Dmitry Olshansky
Apr 30 2012
parent reply "SomeDude" <lovelydear mailmetrash.com> writes:
On Monday, 30 April 2012 at 07:37:13 UTC, Dmitry Olshansky wrote:

 Right, nowdays any compiler is either smart enough or a dead 
 meat that nobody uses.
 P.S. dmd is kind of work in progress ;)
A smart enough compiler would understand natural language and turn it into efficient assembly. :o)
Apr 30 2012
parent Dmitry Olshansky <dmitry.olsh gmail.com> writes:
On 30.04.2012 13:21, SomeDude wrote:
 On Monday, 30 April 2012 at 07:37:13 UTC, Dmitry Olshansky wrote:

 Right, nowdays any compiler is either smart enough or a dead meat that
 nobody uses.
 P.S. dmd is kind of work in progress ;)
A smart enough compiler would understand natural language and turn it into efficient assembly. :o)
Yeah, unless it decides to take a vacation. :) Or you know such a compiler may have a lot of more interesting things to do so our mundane ideas may just have to wait for a while. -- Dmitry Olshansky
Apr 30 2012
prev sibling parent deadalnix <deadalnix gmail.com> writes:
Le 29/04/2012 23:54, Peter Alexander a écrit :
 On Sunday, 29 April 2012 at 21:18:40 UTC, deadalnix wrote:
 Le 29/04/2012 03:06, bearophile a écrit :
 Jonathan M Davis:

 * foreach_reverse is essentially redudant at this point (not to mention
 confusing if combined with delegates), since we have retro.
retro() can't replace foreach_reverse until the front-end demonstrability produces asm code equally efficient. Loops _must_ be fully efficient, they are a basic language construct, this is very important. Even foreach() is sometimes not equally efficient as a for() in some cases...
This is an implementation issue and shouldn't be an argument for language design.
The 'sufficiently smart compiler' argument is old and invalid. Please do not use it.
This is a case by case issue. You should consider fixing implementation issue with implementation, and consider language design if that first one fail. If you don't think this is right, the only rational solution you have is to use assembly directly. As you fail to show how this is something that isn't reasonably implementable, you have no argument.
Apr 30 2012
prev sibling next sibling parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Sun, Apr 29, 2012 at 03:06:53AM +0200, bearophile wrote:
 Jonathan M Davis:
 
* foreach_reverse is essentially redudant at this point (not to
mention
confusing if combined with delegates), since we have retro.
retro() can't replace foreach_reverse until the front-end demonstrability produces asm code equally efficient. Loops _must_ be fully efficient, they are a basic language construct, this is very important. Even foreach() is sometimes not equally efficient as a for() in some cases...
[...] IMO, the compiler needs to _aggressively_ inline opApply() delegates, unless it's impossible (e.g. opApply is recursive), or perhaps exceeds some reasonable size limit for loop inlining). It's rather disheartening to design a great abstract type for manipulating collections, only to have opApply always incur the overhead of allocating and invoking a delegate _every loop iteration_, even when opApply is as simple as: int opApply(int delegate(ref T arg) dg) { someSetupCode(); for (i=0; i<n; i++) { dg(element[i]); } someCleanupCode(); } As far as I'm concerned, the compiler *should* just inline the whole thing (both opApply and the delegate body) when you write foreach(c; container) {...}. There's no reason for such a trivial loop to incur a call to a delegate every iteration. Powerful abstractions such as opApply need to be optimized to the max, so that D's generic programming capabilities can be a strong selling point. T -- Nearly all men can stand adversity, but if you want to test a man's character, give him power. -- Abraham Lincoln
Apr 29 2012
parent Timon Gehr <timon.gehr gmx.ch> writes:
On 04/30/2012 04:47 AM, H. S. Teoh wrote:
 On Sun, Apr 29, 2012 at 03:06:53AM +0200, bearophile wrote:
 Jonathan M Davis:

 * foreach_reverse is essentially redudant at this point (not to
 mention
 confusing if combined with delegates), since we have retro.
retro() can't replace foreach_reverse until the front-end demonstrability produces asm code equally efficient. Loops _must_ be fully efficient, they are a basic language construct, this is very important. Even foreach() is sometimes not equally efficient as a for() in some cases...
[...] IMO, the compiler needs to _aggressively_ inline opApply() delegates, unless it's impossible (e.g. opApply is recursive), or perhaps exceeds some reasonable size limit for loop inlining). It's rather disheartening to design a great abstract type for manipulating collections, only to have opApply always incur the overhead of allocating
Use a scope delegate in the opApply signature to avoid the allocation.
 and invoking a
 delegate _every loop iteration_, even when opApply is as simple as:

 	int opApply(int delegate(ref T arg) dg) {
 		someSetupCode();
 		for (i=0; i<n; i++) {
 			dg(element[i]);
 		}
 		someCleanupCode();
 	}

 As far as I'm concerned, the compiler *should* just inline the whole
 thing (both opApply and the delegate body) when you write foreach(c;
 container) {...}. There's no reason for such a trivial loop to incur a
 call to a delegate every iteration.

 Powerful abstractions such as opApply need to be optimized to the max,
 so that D's generic programming capabilities can be a strong selling
 point.


 T
Apr 30 2012
prev sibling parent "akaz" <nemo utopia.com> writes:
 It's hard to grep for (since with is
 used in comments quite often),
Try to search for "with(" or "with\s(", that are less common in normal text.
There is no tool (maybe the compiler could provide such a tool) to remove all comments? That way, you could do: cat file.d | tool | grep whatever
May 03 2012
prev sibling next sibling parent reply ponce <spam spam.org> writes:
Le 28/04/2012 20:47, Walter Bright a écrit :
 What's your list?
- builtin complex types (I don't _need_ be able to write "4 + 5i") - builtin associative arrays - some builtin properties like arr.sort - lazy, I use it only for logging - foreach_reverse, never used it - comma operator: when do you ever need it? - in operator Other than that, as a user I can't say having a lot of features is a big problem, it's a major selling point.
Apr 28 2012
parent reply =?ISO-8859-1?Q?Alex_R=F8nne_Petersen?= <xtzgzorex gmail.com> writes:
On 29-04-2012 03:20, ponce wrote:
 Le 28/04/2012 20:47, Walter Bright a écrit :
 What's your list?
- builtin complex types (I don't _need_ be able to write "4 + 5i")
+1.
 - builtin associative arrays
 - some builtin properties like arr.sort
+1, and .reverse. I'm also against .dup and .idup being properties, but these don't modify the array in place, so I take less issue with them.
 - lazy, I use it only for logging
lazy is horribly broken in many ways. Try to make a lazy value where the producing delegate is pure. (Hint: You can't.)
 - foreach_reverse, never used it
 - comma operator: when do you ever need it?
I've never used it intentionally, ever, but have been bitten in the ass countless times because of it.
 - in operator
Disagree. However, I do think it needs to made more useful (for instance, I simply don't understand why I can't use in to test for existence in an array).
 Other than that, as a user I can't say having a lot of features is a big
 problem, it's a major selling point.
-- - Alex
Apr 29 2012
next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
Alex Rønne Petersen:

 - lazy, I use it only for logging
lazy is horribly broken in many ways.<
Sometimes I use std.exception.enforce(), that uses lazy. Bye, bearophile
Apr 29 2012
prev sibling parent reply "Jesse Phillips" <jessekphillips+D gmail.com> writes:
On Sunday, 29 April 2012 at 20:50:02 UTC, Alex Rønne Petersen 
wrote:

 - in operator
Disagree. However, I do think it needs to made more useful (for instance, I simply don't understand why I can't use in to test for existence in an array).
Complexity of the operation. in on an array is not nearly the same as with an associative array.
Apr 30 2012
parent reply =?UTF-8?B?QWxleCBSw7hubmUgUGV0ZXJzZW4=?= <xtzgzorex gmail.com> writes:
On 01-05-2012 03:41, Jesse Phillips wrote:
 On Sunday, 29 April 2012 at 20:50:02 UTC, Alex Rønne Petersen wrote:

 - in operator
Disagree. However, I do think it needs to made more useful (for instance, I simply don't understand why I can't use in to test for existence in an array).
Complexity of the operation. in on an array is not nearly the same as with an associative array.
I know, but it's very intuitive still; see Python. -- - Alex
Apr 30 2012
parent reply "SomeDude" <lovelydear mailmetrash.com> writes:
On Tuesday, 1 May 2012 at 02:26:53 UTC, Alex Rønne Petersen 
wrote:
 On 01-05-2012 03:41, Jesse Phillips wrote:
 Complexity of the operation. in on an array is not nearly the 
 same as
 with an associative array.
I know, but it's very intuitive still; see Python.
And that's why it's somewhat dangerous. Because it's so easy to use, someone that doesn't pay enough attention may overlook the fact that he is not using the right data structure. If he often has to do that more than once, he is using the wrong tool for the job. I agree it would be syntaxically nice, but I worry giving this syntactic sugar for what's a for loop with lots of comparisons isn't such a good idea. And the comparisons themselves are subject to caution. If for instance it's an array of floats, or some custom objects, it's very unlikely that you are going to compare bit by bit. So basically, this would be useful only for integers and chars.
Apr 30 2012
parent reply =?UTF-8?B?QWxleCBSw7hubmUgUGV0ZXJzZW4=?= <xtzgzorex gmail.com> writes:
On 01-05-2012 06:44, SomeDude wrote:
 On Tuesday, 1 May 2012 at 02:26:53 UTC, Alex Rønne Petersen wrote:
 On 01-05-2012 03:41, Jesse Phillips wrote:
 Complexity of the operation. in on an array is not nearly the same as
 with an associative array.
I know, but it's very intuitive still; see Python.
And that's why it's somewhat dangerous. Because it's so easy to use, someone that doesn't pay enough attention may overlook the fact that he is not using the right data structure. If he often has to do that more than once, he is using the wrong tool for the job. I agree it would be syntaxically nice, but I worry giving this syntactic sugar for what's a for loop with lots of comparisons isn't such a good idea. And the comparisons themselves are subject to caution. If for instance it's an array of floats, or some custom objects, it's very unlikely that you are going to compare bit by bit. So basically, this would be useful only for integers and chars.
1) So because some people might use a feature incorrectly due to lack of knowledge in algorithms and data structures, we should cripple the language? 2) The same holds true for AAs keyed by floats. -- - Alex
May 01 2012
next sibling parent reply "SomeDude" <lovelydear mailmetrash.com> writes:
On Tuesday, 1 May 2012 at 14:31:25 UTC, Alex Rønne Petersen 
wrote:
 1) So because some people might use a feature incorrectly due 
 to lack of knowledge in algorithms and data structures, we 
 should cripple the language?
It's not crippling the language. Nothing prevents you from writing a loop. Or using a library find function that does the same thing. But the name "find" gives you a hint that it's not magical and that it has a cost, while with "if( foo in bar)", it is too easy to forget that we are actually potentially performing an O(n) operation. In an AA, the 'in' keyword performs a O(1) operation, so that's ok to use it as a syntactic sugar.
May 01 2012
next sibling parent reply =?UTF-8?B?QWxleCBSw7hubmUgUGV0ZXJzZW4=?= <xtzgzorex gmail.com> writes:
On 01-05-2012 16:41, SomeDude wrote:
 On Tuesday, 1 May 2012 at 14:31:25 UTC, Alex Rønne Petersen wrote:
 1) So because some people might use a feature incorrectly due to lack
 of knowledge in algorithms and data structures, we should cripple the
 language?
It's not crippling the language. Nothing prevents you from writing a loop. Or using a library find function that does the same thing. But the name "find" gives you a hint that it's not magical and that it has a cost, while with "if( foo in bar)", it is too easy to forget that we are actually potentially performing an O(n) operation. In an AA, the 'in' keyword performs a O(1) operation, so that's ok to use it as a syntactic sugar.
No, it is not an O(1) operation, it is *close* to O(1) (as much sense as that statement can make). I don't know why you associate any particular complexity with 'in' in the first place. And I do think we're crippling the language, considering Python (and probably other languages) has had this feature since forever. I'm seriously worried. It seems to me like we're trying to cater to people who can't reason about the types in their program and the complexities of performing various operations on them. Since when did algorithmic complexity become a reason to take away syntax sugar? -- - Alex
May 01 2012
parent reply "Tobias Pankrath" <tobias pankrath.net> writes:
 No, it is not an O(1) operation, it is *close* to O(1) (as much 
 sense as that statement can make). I don't know why you 
 associate any particular complexity with 'in' in the first 
 place. And I do think we're crippling the language, considering 
 Python (and probably other languages) has had this feature 
 since forever.

 I'm seriously worried. It seems to me like we're trying to 
 cater to people who can't reason about the types in their 
 program and the complexities of performing various operations 
 on them. Since when did algorithmic complexity become a reason 
 to take away syntax sugar?
+1 I do argee. opIn is handy for arrays, too. That the complexity would be linear and thus it should be disallowed is not a valid argument in my opinion, because with the exact same argument you could kick std.algorithm.find out of phobos. It is just obvious to every trained programmer that finding an element in an unordered list takes O(n).
May 02 2012
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 5/2/12 6:15 AM, Tobias Pankrath wrote:
 No, it is not an O(1) operation, it is *close* to O(1) (as much sense
 as that statement can make). I don't know why you associate any
 particular complexity with 'in' in the first place. And I do think
 we're crippling the language, considering Python (and probably other
 languages) has had this feature since forever.

 I'm seriously worried. It seems to me like we're trying to cater to
 people who can't reason about the types in their program and the
 complexities of performing various operations on them. Since when did
 algorithmic complexity become a reason to take away syntax sugar?
+1 I do argee. opIn is handy for arrays, too. That the complexity would be linear and thus it should be disallowed is not a valid argument in my opinion, because with the exact same argument you could kick std.algorithm.find out of phobos. It is just obvious to every trained programmer that finding an element in an unordered list takes O(n).
The problem here is making complexity an implementation detail of a uniform interface (e.g. over hashes and linear containers). That is fail. Andrei
May 02 2012
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 05/02/2012 04:01 PM, Andrei Alexandrescu wrote:
 On 5/2/12 6:15 AM, Tobias Pankrath wrote:
 No, it is not an O(1) operation, it is *close* to O(1) (as much sense
 as that statement can make). I don't know why you associate any
 particular complexity with 'in' in the first place. And I do think
 we're crippling the language, considering Python (and probably other
 languages) has had this feature since forever.

 I'm seriously worried. It seems to me like we're trying to cater to
 people who can't reason about the types in their program and the
 complexities of performing various operations on them. Since when did
 algorithmic complexity become a reason to take away syntax sugar?
+1 I do argee. opIn is handy for arrays, too. That the complexity would be linear and thus it should be disallowed is not a valid argument in my opinion, because with the exact same argument you could kick std.algorithm.find out of phobos. It is just obvious to every trained programmer that finding an element in an unordered list takes O(n).
The problem here is making complexity an implementation detail of a uniform interface (e.g. over hashes and linear containers). That is fail. Andrei
The interface is different: void main(){ int[] a = [0,0,0]; a[2] = 3; assert(2 !in a); } vs. void main(){ int[int] aa; aa[2] = 3; assert(2 in aa); }
May 02 2012
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 5/2/12 10:20 AM, Timon Gehr wrote:
 The interface is different:

 void main(){
 int[] a = [0,0,0];
 a[2] = 3;
 assert(2 !in a);
 }

 vs.

 void main(){
 int[int] aa;
 aa[2] = 3;
 assert(2 in aa);
 }
The syntactic interface is the same. That would be the semantic interface, which makes the idea twice as bad. Andrei
May 02 2012
parent Timon Gehr <timon.gehr gmx.ch> writes:
On 05/02/2012 05:25 PM, Andrei Alexandrescu wrote:
 On 5/2/12 10:20 AM, Timon Gehr wrote:
 The interface is different:

 void main(){
     int[] a = [0,0,0];
     a[2] = 3;
     assert(2 !in a);
 }

 vs.

 void main(){
     int[int] aa;
     aa[2] = 3;
     assert(2 in aa);
 }
The syntactic interface is the same.
Encapsulation of complexity is a problem if it is not obvious to the programmer. I am not sure it can even be called such if the semantics is different.
 That would be the semantic interface, which makes the idea twice as bad.

 Andrei
I tend to agree, but I think that the two points are mutually exclusive.
May 02 2012
prev sibling parent "so" <so so.so> writes:
On Tuesday, 1 May 2012 at 14:41:43 UTC, SomeDude wrote:
 On Tuesday, 1 May 2012 at 14:31:25 UTC, Alex Rønne Petersen 
 wrote:
 1) So because some people might use a feature incorrectly due 
 to lack of knowledge in algorithms and data structures, we 
 should cripple the language?
It's not crippling the language. Nothing prevents you from writing a loop. Or using a library find function that does the same thing. But the name "find" gives you a hint that it's not magical and that it has a cost, while with "if( foo in bar)", it is too easy to forget that we are actually potentially performing an O(n) operation. In an AA, the 'in' keyword performs a O(1) operation, so that's ok to use it as a syntactic sugar.
I remember this was the argument Andrei also came up. Still can't make any sense out of it. If someone have some detailed reference please share! If you have it just for a niche usage, why do you have it at all? With UFCS "bar.contains(foo)" precise enough. You can make same argument for every operator in any language if you have operator overloading. And it would be against operator overloading, not particularly "in". -- Didn't know "http://forum.dlang.org/" adopted that unreadable/annoying to no end captchas.
May 01 2012
prev sibling parent reply "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Tuesday, May 01, 2012 16:31:25 Alex Rønne Petersen wrote:
 1) So because some people might use a feature incorrectly due to lack of
 knowledge in algorithms and data structures, we should cripple the language?
If in is not restricted to a particular level Big-O complexity, then you cannot safely use it in generic code. That's why all of the functions in std.container give their Big-O complexity. In C++ [] is supposed to be O(log n) at worst. I would expect it to be the same in D, and since in is doing essentially the same operation, I would expect it to have the same Big-O complexity. No, nothing is stopping a programmer from giving it horrible complexity, but the standard library and language should _definitely_ stick to O(log n) worst case for in and []. It would be a disaster for generic algorithms if in worked on normal arrays, because it would not be possible to maintain the required Big-O complexity. - Jonathan M Davis
May 01 2012
parent reply =?UTF-8?B?QWxleCBSw7hubmUgUGV0ZXJzZW4=?= <xtzgzorex gmail.com> writes:
On 01-05-2012 19:09, Jonathan M Davis wrote:
 On Tuesday, May 01, 2012 16:31:25 Alex Rønne Petersen wrote:
 1) So because some people might use a feature incorrectly due to lack of
 knowledge in algorithms and data structures, we should cripple the language?
If in is not restricted to a particular level Big-O complexity, then you cannot safely use it in generic code. That's why all of the functions in std.container give their Big-O complexity.
I don't think 'in' is actually used in any generic code (other than code specifically written for AAs, in which it *does* have a specific complexity in any case). I know I wouldn't use 'in' in truly generic code in any case, exactly because it has no defined complexity (even today; it's overloadable just like most other binary operators).
 In C++ [] is supposed to be O(log n) at worst. I would expect it to be the
 same in D, and since in is doing essentially the same operation, I would
 expect it to have the same Big-O complexity.
This is a good point, but not one I would subscribe to; it only holds true if you consider 'in' to be an operation purely limited to AAs. But this is already not the case given that it can be overloaded. So, I don't think that it having different complexity for arrays is a big deal. Personally, I consider 'in' to be syntax sugar for the language user. To me, it does not seem like a feature that a library of generic algorithms should be using at all.
 No, nothing is stopping a programmer from giving it horrible complexity, but
 the standard library and language should _definitely_ stick to O(log n) worst
 case for in and []. It would be a disaster for generic algorithms if in worked
 on normal arrays, because it would not be possible to maintain the required
 Big-O complexity.
I agree that any overload of [] and 'in' that Phobos does should stick to that constraint when possible (I say when possible, because sometimes innovative uses of these operators can't stick to this rather strict and mundane constraint; consider for example interaction with a database or what do I know...). But again, I don't think 'in' is something a generic algorithm should be using. We have the functions in std.algorithm and std.container if we need to write generic code. Also, I don't think language design should be *too* biased by the standard library's preferences. Not everyone agrees with Phobos conventions and we have to respect that IMHO. Just because it's a standard library doesn't mean that it should dictate users of the language who don't use the standard library.
 - Jonathan M Davis
-- - Alex
May 01 2012
parent reply "foobar" <foo bar.com> writes:
On Tuesday, 1 May 2012 at 17:50:38 UTC, Alex Rønne Petersen
wrote:
 On 01-05-2012 19:09, Jonathan M Davis wrote:
 On Tuesday, May 01, 2012 16:31:25 Alex Rønne Petersen wrote:
 1) So because some people might use a feature incorrectly due 
 to lack of
 knowledge in algorithms and data structures, we should 
 cripple the language?
If in is not restricted to a particular level Big-O complexity, then you cannot safely use it in generic code. That's why all of the functions in std.container give their Big-O complexity.
I don't think 'in' is actually used in any generic code (other than code specifically written for AAs, in which it *does* have a specific complexity in any case). I know I wouldn't use 'in' in truly generic code in any case, exactly because it has no defined complexity (even today; it's overloadable just like most other binary operators).
 In C++ [] is supposed to be O(log n) at worst. I would expect 
 it to be the
 same in D, and since in is doing essentially the same 
 operation, I would
 expect it to have the same Big-O complexity.
This is a good point, but not one I would subscribe to; it only holds true if you consider 'in' to be an operation purely limited to AAs. But this is already not the case given that it can be overloaded. So, I don't think that it having different complexity for arrays is a big deal. Personally, I consider 'in' to be syntax sugar for the language user. To me, it does not seem like a feature that a library of generic algorithms should be using at all.
 No, nothing is stopping a programmer from giving it horrible 
 complexity, but
 the standard library and language should _definitely_ stick to 
 O(log n) worst
 case for in and []. It would be a disaster for generic 
 algorithms if in worked
 on normal arrays, because it would not be possible to maintain 
 the required
 Big-O complexity.
I agree that any overload of [] and 'in' that Phobos does should stick to that constraint when possible (I say when possible, because sometimes innovative uses of these operators can't stick to this rather strict and mundane constraint; consider for example interaction with a database or what do I know...). But again, I don't think 'in' is something a generic algorithm should be using. We have the functions in std.algorithm and std.container if we need to write generic code. Also, I don't think language design should be *too* biased by the standard library's preferences. Not everyone agrees with Phobos conventions and we have to respect that IMHO. Just because it's a standard library doesn't mean that it should dictate users of the language who don't use the standard library.
 - Jonathan M Davis
vote++ I like your POV that operators are useful shortcuts (syntax sugar) meant for the end user whereas library authors should use the full function names for generic code. IIRC C++'s STL does the same - for instance the map::operator[] is a simple wrapper around map's functions. Is this included in D's style guide?
May 01 2012
parent "SomeDude" <lovelydear mailmetrash.com> writes:
On Tuesday, 1 May 2012 at 21:03:35 UTC, foobar wrote:
 vote++

 I like your POV that operators are useful shortcuts (syntax
 sugar) meant for the end user whereas library authors should use
 the full function names for generic code. IIRC C++'s STL does 
 the
 same - for instance the map::operator[] is a simple wrapper
 around map's functions.

 Is this included in D's style guide?
vote------------- If something is a bad idea for a library, I don't see why it could be a good idea for the user code. After all, the standard library IS user code. The fact that it's in a library or not doesn't change anything to the fact that your syntactic sugar is hiding a potential problem.
May 01 2012
prev sibling next sibling parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Sat, Apr 28, 2012 at 04:56:52PM -0700, Jonathan M Davis wrote:
[...]
 One _big_ difference between D and C++ as far as complexity goes is
 that in C++, a _lot_ of the complexity comes from weird things in the
 language and knowing about how certain things can go horribly wrong
 (e.g. I can never remember all of the details on how horribly broken
 multiple inheritence is). 
Ugh. C++ multiple inheritance is a labyrinth, nay, a veritable minefield of subtle tripwires, inconvenient limitations, and a source of hair-tearing headaches. It's one of the bigger problems with C++'s OO implementation. Java's idea of single inheritance, multiple interfaces is a much better concept.
 It's frequently not an issue of knowing how to do things in the
 language but rather an issue of knowing what weird side effects an
 problems happen with certain stuff. With D, on the other hand, the
 complexity tends to be in just knowing what all of the features are
 and what they can do.
Except is() expressions, which appear to be totally arbitrary to me. As far as I'm concerned, it's just "memorize these bunch of arbitrary special rules".
 The only feature that comes to mind as probably being overly complex
 is is expressions, but that complexity can really come in handy
 sometimes.  std.traits should probably do more to alleviate the need
 for is expressions though so that odds of needing some of the more
 complicated stuff are lessened.
Needing to rely on std.traits is backwards, IMO. It's the compiler that knows all this stuff about types, why should we need to consult a library to get at the information? But anyway, the *functionality* of is-expressions are very useful, and, I'd argue, necessary. It's just that the syntax is atrocious and needs fixing.
 * As for redundant features, the first one that really comes to mind
 is WYSIWYG string literals. There are what, 4 different types of
 delimiters for string literals?
Only 4? I thought there were more. Last I looked, there were like 6 separate cases.
 I don't even remember all of the options. I just always use ` if I
 don't want any escaping in string literal and " if I do. The others
 may be valuable enough to have in some contexts, but I _never_ use
 them.
Yeah, I agree we should merge some of the string literal syntaxes. Some of them are useful (I'm a sucker for heredoc syntax) but currently it seems like just way too many options for something that should be really straightforward. [...]
 * I hate C style struct initializers and would really like to see them
 go, but for reasons that I don't understand, people actually use them
 rather than using a proper constructor call, so I doubt that we could
 get rid of them without a fair bit of complaining. I think that
 they're completely redundant and very _un_D.
It's annoying to have to write a constructor whose only purpose is to copy arguments into field members. Many uses of structs don't need the encapsulation that ctors were intended for.
 * There seem to be too many ways to do variadic functions. We have to
 allow C style variadics for extern(C), but having 3 of our own seems
 like a bit much.  Variadic templates are generally all that we need.
 The others don't seem necessary for the most part. But unfortunately,
 they should probably be left in so that classes can use them with
 virtual functions, since they can't use templates.
IMO we should unify variadic syntax into one (or perhaps leave the C variadics separate, since they're just for compatibility with C), and let the compiler implement each appropriately for the given context. [...]
 * Increasingly, I don't like UFCS. I think that in most cases, it
 complicates code for little value. And I _really_ don't like how it
 results in people flipping chains of a(b(c(d(5)))) calls into
 something like d(5).c().b.().a(). I think that it makes the code way
 harder to read. The code is completely backwards. But I appear to be
 in the minority with that opinion. I also don't like how it creates so
 many ways to write exactly the same code. It harms readibility. But as
 much as I dislike many of the applications of UFCS, it _does_ appear
 to be quite popular. And upon occasion, it may be useful, but I _am_
 wishing that we hadn't added it.
Strange, I like it a lot because unifying function calls makes it very easy to write generic code without sprinkling static ifs everywhere. [...]
 Overall, I think that D's feature set is fairly solid. It's mostly
 just the implementation of said features which is a problem - though
 some minor tweaks are probably in order (e.g. as Bearophile suggests,
 make it so that adjacent string literals don't concatenate).
[...] I thought adjacent string lits have been deprecated or no longer supported? Personally I like it; it lets you format long literals over multiple lines without needing a ~ in between. And also, recently I found this annoyance: throw new Exception("A very long message (%s) that is "~ "broken across multiple (%d) lines".format(msg,count)); This doesn't work because ~ has lower precedence than ., so you need extra parentheses around the strings: throw new Exception(("A very long message (%s) that is "~ "broken across multiple (%d) lines").format(msg,count)); Whereas being able to concatenate adjacent literals would've been this a lot more readable. T -- I don't trust computers, I've spent too long programming to think that they can get anything right. -- James Miller
Apr 28 2012
parent "bearophile" <bearophileHUGS lycos.com> writes:
H. S. Teoh:

 It's annoying to have to write a constructor whose only purpose 
 is to copy arguments into field members.
This is not needed in D for structs. Try it.
 I thought adjacent string lits have been deprecated or no longer
 supported?
Walter accepted to deprecate it lot of time ago, but it's not implemented yet.
 Personally I like it; it lets you format long literals over 
 multiple lines without needing a ~ in between.
If you write an array literal with many strings inside, and you forget a comma, you get less strings, silently. This is a source
 And also, recently I found this annoyance:
Right, the precedence of the ~ operator different from the precedence of the invisible space operator. This causes some disadvantages. But I think the advantages in gained correctness are more important. Bye, bearophile
Apr 28 2012
prev sibling next sibling parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On Saturday, April 28, 2012 18:24:20 H. S. Teoh wrote:
 * I hate C style struct initializers and would really like to see them
 go, but for reasons that I don't understand, people actually use them
 rather than using a proper constructor call, so I doubt that we could
 get rid of them without a fair bit of complaining. I think that
 they're completely redundant and very _un_D.
It's annoying to have to write a constructor whose only purpose is to copy arguments into field members. Many uses of structs don't need the encapsulation that ctors were intended for.
You don't have to. If you have struct S { int field1; float field2; string field3; } then you can do auto s = S(5, 7.2, "hello"); The ability to do S s = {5, 7.2, "hello"}; gains you _nothing_. - Jonathan M Davis
Apr 28 2012
parent "Era Scarecrow" <rtcvb32 yahoo.com> writes:
On Sunday, 29 April 2012 at 01:36:10 UTC, Jonathan M Davis wrote:
 On Saturday, April 28, 2012 18:24:20 H. S. Teoh wrote:
 then you can do

 auto s = S(5, 7.2, "hello");

 The ability to do

 S s = {5, 7.2, "hello"};

 gains you _nothing_.
Depends on how many levels you are using on a array. I've noted in another part of this topic where I have pages and pages of the data. Forcing me to qualify it with a name when the compiler/structure already knows just seems like an annoyance. True it removes the {}'s, but I think I have 3 levels of deep. S[] s = [S(),S(),S()]; vs S[] s = [{},{},{}]; If they are more complex, then indenting and separation makes sense. And the size of the name I don't want to have to Alias my structures to something tiny and a little obfuscate in order to keep it compact and simple. That's my thoughts anyways. If the language later disallows it, I'll have to change my code to compensate for it.
Apr 28 2012
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 4/29/12, Jonathan M Davis <jmdavisProg gmx.com> wrote:
 struct S
 {
     int field1;
     float field2;
     string field3;
 }
 then you can do

 auto s = S(5, 7.2, "hello");

 The ability to do

 S s = {5, 7.2, "hello"};

 gains you _nothing_.
That's not really the benefit of those initializers. This is: S[] arr = [{field2 = 1.0}, {field2 = 0.5}]; It's a real benefit when unittesting because it allows me to quickly create variables with some interesting state which I can then test.
Apr 28 2012
prev sibling next sibling parent "Francois Chabot" <francois.chabot.dev gmail.com> writes:
 What's your list?
- The is expressions are confusing as hell, and it seems to me that it's serving a purpose that should be handled by __traits (which has its own set of issues in my mind, but is a solid idea) - On the subject, as much as I love __traits(), its dumping grounds nature is problematic. It should be limited to accessing traits of types, or changed to a more representative name. It's not redundant or anything, but is prone to bloating by its design. - I am on the version hate boat. To me, it's redundant with static if(). - as many have said, the comma operator is problematic by nature and should probably go. I haven't been into D for very long, so I'll probably run into more stuff eventually, but that's what comes off the top of my head...
Apr 28 2012
prev sibling next sibling parent reply Paulo Pinto <pjmlp progtools.org> writes:
Am 28.04.2012 20:47, schrieb Walter Bright:
 Andrei and I had a fun discussion last night about this question. The
 idea was which features in D are redundant and/or do not add significant
 value?

 A couple already agreed upon ones are typedef and the cfloat, cdouble
 and creal types.

 What's your list?
- two different ways of creating function pointers is confusing (function and delegate) I understand the reasoning, but makes one think all the time when to use what. - sometimes D code looks like template and mixins gone mad While I do appreciate the power, it can be quite confusing to try to understand what the code does. Specially with the lack of support in mixin's debugging - __traits should be given a proper name It looks out of place in regard with the rest of the language, by making use of the underscores - AA should be a library type I am on the C++ and Scala camp where the language should be extendable via the library - misuse of enum to declare constants I prefer that the use of const would be possible - conditional compilation is hard to follow without syntax highlighting Other languages with conditional compilation make it easier to follow - unit tests I would rather have them as a library. While it is fun to discuss what we like and not like, I vote that priority should be given to make the language stable and have better tooling. We need to have safer languages with native code generation for systems programming in the mainstream OS, that take us away from the buffer overflow exploits and dagling pointers legacy that C and C++ brought upon us. Someone that does not know D and sees the amount of bugs still existing, or this type of discussions, will run away to Go or some future version I don't agree D is complex, any language that aims to be used in large application domains, needs a certain set of abstractions. If it does not support them, it is condemmend to keep getting new features until it turns in what the language designers were fighting against. -- Paulo
Apr 28 2012
next sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 04/29/2012 08:31 AM, Paulo Pinto wrote:
 Am 28.04.2012 20:47, schrieb Walter Bright:
 Andrei and I had a fun discussion last night about this question. The
 idea was which features in D are redundant and/or do not add significant
 value?

 A couple already agreed upon ones are typedef and the cfloat, cdouble
 and creal types.

 What's your list?
- two different ways of creating function pointers is confusing (function and delegate) I understand the reasoning, but makes one think all the time when to use what.
'delegate' is more powerful, 'function' is more efficient. If you don't want to think about it, just use 'delegate'. I'd rather see 'function' implicitly convert to 'delegate' than to have it gone. D can be used for systems programming after all!
 - sometimes D code looks like template and mixins gone mad
 While I do appreciate the power, it can be quite confusing to try
 to understand what the code does. Specially with the lack of support
 in mixin's debugging
pragma(msg, ...) ?
 - misuse of enum to declare constants
 I prefer that the use of const would be possible
const infects the type and const-qualified data can exist at runtime, so it is not possible.
 - conditional compilation is hard to follow without syntax highlighting
 Other languages with conditional compilation make it easier to follow

That is not a language issue.
 While it is fun to discuss what we like and not like, I vote that
 priority should be given to make the language stable and have better
 tooling.

 We need to have safer languages with native code generation for systems
 programming in the mainstream OS, that take us away from the buffer
 overflow exploits and dagling pointers legacy that C and C++ brought
 upon us.

 Someone that does not know D and sees the amount of bugs still existing,
 or this type of discussions, will run away to Go or some future version


 I don't agree D is complex, any language that aims to be used in large
 application domains, needs a certain set of abstractions. If it does not
 support them, it is condemmend to keep getting new features until it
 turns in what the language designers were fighting against.
I agree with this section.
Apr 29 2012
parent reply Paulo Pinto <pjmlp progtools.org> writes:
Am 29.04.2012 10:42, schrieb Timon Gehr:
 On 04/29/2012 08:31 AM, Paulo Pinto wrote:
 Am 28.04.2012 20:47, schrieb Walter Bright:
 Andrei and I had a fun discussion last night about this question. The
 idea was which features in D are redundant and/or do not add significant
 value?

 A couple already agreed upon ones are typedef and the cfloat, cdouble
 and creal types.

 What's your list?
- two different ways of creating function pointers is confusing (function and delegate) I understand the reasoning, but makes one think all the time when to use what.
'delegate' is more powerful, 'function' is more efficient. If you don't want to think about it, just use 'delegate'. I'd rather see 'function' implicitly convert to 'delegate' than to have it gone. D can be used for systems programming after all!
That is what I mean. The compiler could make the distinction between function and delegate itself. I am not arguing to remove the feature, rather to have the compiler check it for me. Surely it can see if I am passing the delegate to D code or extern C/C++ code and act accordingly.
 - sometimes D code looks like template and mixins gone mad
 While I do appreciate the power, it can be quite confusing to try
 to understand what the code does. Specially with the lack of support
 in mixin's debugging
pragma(msg, ...) ?
Too low level?
 - misuse of enum to declare constants
 I prefer that the use of const would be possible
const infects the type and const-qualified data can exist at runtime, so it is not possible.
Yeah, but it brings me back bad memories from the early days, when C++ compilers did not fully support C++98, and we had to resort to the enum trick to create constants.
 - conditional compilation is hard to follow without syntax highlighting
 Other languages with conditional compilation make it easier to follow

That is not a language issue.
How come? In the languages mentioned above, the conditional compilation stands out in clear text that is doing something at compile time. In D you need to be aware which statements are compile time and which are not. Not a big deal to argue about, but easy trap for D newbies. -- Paulo
Apr 29 2012
parent reply "David Nadlinger" <see klickverbot.at> writes:
On Sunday, 29 April 2012 at 12:41:37 UTC, Paulo Pinto wrote:
 I am not arguing to remove the feature, rather to have the 
 compiler check it for me. Surely it can see if I am passing the 
 delegate to D code or extern C/C++ code and act accordingly.
How would this work? Function pointers are only a single word in D code as well (and a single unconditional jump to that address) , whereas delegates are two words. What is if a function accepts a delegate, but a function pointer is passed? What is if a delegate is passed to a (possibly C) function – does the compiler automatically emit a thunk for that? David
Apr 29 2012
parent Paulo Pinto <pjmlp progtools.org> writes:
Am 29.04.2012 15:24, schrieb David Nadlinger:
 On Sunday, 29 April 2012 at 12:41:37 UTC, Paulo Pinto wrote:
 I am not arguing to remove the feature, rather to have the compiler
 check it for me. Surely it can see if I am passing the delegate to D
 code or extern C/C++ code and act accordingly.
How would this work? Function pointers are only a single word in D code as well (and a single unconditional jump to that address) , whereas delegates are two words. What is if a function accepts a delegate, but a function pointer is passed? What is if a delegate is passed to a (possibly C) function – does the compiler automatically emit a thunk for that? David
Yes, that is what I had in mind. That is what is done in .NET as far as I am aware.
Apr 29 2012
prev sibling parent reply =?ISO-8859-1?Q?Alex_R=F8nne_Petersen?= <xtzgzorex gmail.com> writes:
On 29-04-2012 08:31, Paulo Pinto wrote:
 Am 28.04.2012 20:47, schrieb Walter Bright:
 Andrei and I had a fun discussion last night about this question. The
 idea was which features in D are redundant and/or do not add significant
 value?

 A couple already agreed upon ones are typedef and the cfloat, cdouble
 and creal types.

 What's your list?
- two different ways of creating function pointers is confusing (function and delegate) I understand the reasoning, but makes one think all the time when to use what. - sometimes D code looks like template and mixins gone mad While I do appreciate the power, it can be quite confusing to try to understand what the code does. Specially with the lack of support in mixin's debugging - __traits should be given a proper name It looks out of place in regard with the rest of the language, by making use of the underscores - AA should be a library type I am on the C++ and Scala camp where the language should be extendable via the library - misuse of enum to declare constants I prefer that the use of const would be possible - conditional compilation is hard to follow without syntax highlighting Other languages with conditional compilation make it easier to follow - unit tests I would rather have them as a library.
D unit tests were never really useful for anything beyond single-library projects IMHO. They don't scale for large, real-world application projects with lots of libraries and executables.
 While it is fun to discuss what we like and not like, I vote that
 priority should be given to make the language stable and have better
 tooling.

 We need to have safer languages with native code generation for systems
 programming in the mainstream OS, that take us away from the buffer
 overflow exploits and dagling pointers legacy that C and C++ brought
 upon us.

 Someone that does not know D and sees the amount of bugs still existing,
 or this type of discussions, will run away to Go or some future version


 I don't agree D is complex, any language that aims to be used in large
 application domains, needs a certain set of abstractions. If it does not
 support them, it is condemmend to keep getting new features until it
 turns in what the language designers were fighting against.

 --
 Paulo
-- - Alex
Apr 29 2012
next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
Alex Rønne Petersen:

 D unit tests were never really useful for anything beyond 
 single-library projects IMHO. They don't scale for large, 
 real-world application projects with lots of libraries and 
 executables.
I think D has to offers means to library writers to instrument the built-in unit-testing machinery, to allow the implementation of a good unit testing system. Bye, bearophile
Apr 29 2012
prev sibling next sibling parent "SomeDude" <lovelydear mailmetrash.com> writes:
On Sunday, 29 April 2012 at 20:54:11 UTC, Alex Rønne Petersen 
wrote:
 - unit tests
 I would rather have them as a library.
D unit tests were never really useful for anything beyond single-library projects IMHO. They don't scale for large, real-world application projects with lots of libraries and executables.
What's the problem ? What prevents you to put the unit tests in other modules if you don't want to put them with the code ?
Apr 29 2012
prev sibling parent reply deadalnix <deadalnix gmail.com> writes:
Le 29/04/2012 22:54, Alex Rønne Petersen a écrit :
 D unit tests were never really useful for anything beyond single-library
 projects IMHO. They don't scale for large, real-world application
 projects with lots of libraries and executables.
+1 A good std.unittest + attributes is probably a better approach.
Apr 29 2012
next sibling parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Sun, Apr 29, 2012 at 11:39:02PM +0200, deadalnix wrote:
 Le 29/04/2012 22:54, Alex Rønne Petersen a écrit :
D unit tests were never really useful for anything beyond
single-library projects IMHO. They don't scale for large, real-world
application projects with lots of libraries and executables.
+1 A good std.unittest + attributes is probably a better approach.
The only reason I actually write unittests for D code is because unittest{} is so convenient. If I had to import std.unittest, most likely my code will have no unittests at all. I find that because unittest{} makes it so convenient to write unittests, it's just embarrassing to not write them. Which is kinda the point, 'cos in my experience the act of writing a unittest automatically makes you think about corner cases in the code you just wrote (or just about to write), which means there will be less bugs from the get-go. Also, unittest is just that: for _unit_ tests. If you start needing an entire framework for them, then you're no longer talking about _unit_ tests, you're talking about module- or package-level testing frameworks, and you should be using something more suitable for that, not unittest. T -- Windows: the ultimate triumph of marketing over technology. -- Adrian von Bidder
Apr 29 2012
next sibling parent reply =?ISO-8859-1?Q?Alex_R=F8nne_Petersen?= <xtzgzorex gmail.com> writes:
On 30-04-2012 05:03, H. S. Teoh wrote:
 On Sun, Apr 29, 2012 at 11:39:02PM +0200, deadalnix wrote:
 Le 29/04/2012 22:54, Alex Rønne Petersen a écrit :
 D unit tests were never really useful for anything beyond
 single-library projects IMHO. They don't scale for large, real-world
 application projects with lots of libraries and executables.
+1 A good std.unittest + attributes is probably a better approach.
The only reason I actually write unittests for D code is because unittest{} is so convenient. If I had to import std.unittest, most likely my code will have no unittests at all. I find that because unittest{} makes it so convenient to write unittests, it's just embarrassing to not write them. Which is kinda the point, 'cos in my experience the act of writing a unittest automatically makes you think about corner cases in the code you just wrote (or just about to write), which means there will be less bugs from the get-go. Also, unittest is just that: for _unit_ tests. If you start needing an entire framework for them, then you're no longer talking about _unit_ tests, you're talking about module- or package-level testing frameworks, and you should be using something more suitable for that, not unittest. T
The problem with D's unit test support is that it doesn't integrate well into real world build processes. I usually have debug and release configurations, and that's it. No test configuration; not only does that over-complicate things, but it also isn't really useful. I want my unit testing to be exhaustive; i.e. I want to test my code in debug and release builds, because those are the builds people are going to be using. Not a test build. So, this means that writing unit tests inline is a no-go because that would require either always building with unit tests in all configurations (madness) or having a test configuration (see above). Given the above, I've resorted to having a "tester" executable which links in all libraries in my project and tests every module. This means that I have to write my unit tests inside this helper executable, making much of the gain in D's unittest blocks go away. And no, the fact that I link libraries into the helper executable doesn't mean that I can just write the unit tests in the libraries in the first place. Doing so would require building them twice: Once for the normal build and once for the "tester" executable. (And yes, build times matter when your project gets large enough, even in D.) -- - Alex
Apr 29 2012
next sibling parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Mon, Apr 30, 2012 at 05:16:55AM +0200, Alex Rønne Petersen wrote:
 On 30-04-2012 05:03, H. S. Teoh wrote:
[...]
Also, unittest is just that: for _unit_ tests. If you start needing
an entire framework for them, then you're no longer talking about
_unit_ tests, you're talking about module- or package-level testing
frameworks, and you should be using something more suitable for that,
not unittest.
[...]
 
 The problem with D's unit test support is that it doesn't integrate
 well into real world build processes. I usually have debug and release
 configurations, and that's it. No test configuration; not only does
 that over-complicate things, but it also isn't really useful. I want
 my unit testing to be exhaustive; i.e. I want to test my code in debug
 and release builds, because those are the builds people are going to
 be using. Not a test build.
I see. Personally, I just use a more flexible build system where I can specify an argument to indicate whether or not to compile with -unittest. But you may have other reasons why this is not a good thing.
 So, this means that writing unit tests inline is a no-go because that
 would require either always building with unit tests in all
 configurations (madness) or having a test configuration (see above).
I wonder if dmd (or rdmd) should have a mode where it *only* compiles unittest code (i.e., no main() -- the resulting exe just runs unittests and nothing else). But then again, it sounds like you have an extensive testing framework in place, and if you have that already, then might as well use it.
 Given the above, I've resorted to having a "tester" executable which
 links in all libraries in my project and tests every module. This
 means that I have to write my unit tests inside this helper
 executable, making much of the gain in D's unittest blocks go away.
 
 And no, the fact that I link libraries into the helper executable
 doesn't mean that I can just write the unit tests in the libraries in
 the first place. Doing so would require building them twice: Once for
 the normal build and once for the "tester" executable.
 
 (And yes, build times matter when your project gets large enough, even
 in D.)
[...] True. T -- "I speak better English than this villain Bush" -- Mohammed Saeed al-Sahaf, Iraqi Minister of Information
Apr 29 2012
prev sibling next sibling parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On Sunday, April 29, 2012 21:56:08 H. S. Teoh wrote:
 I wonder if dmd (or rdmd) should have a mode where it *only* compiles
 unittest code (i.e., no main() -- the resulting exe just runs unittests
 and nothing else).
It wouldn't make sense. It's nowhere near as bad as C++, but dmd has to recompile modules all the time unless you compile the entire program at once. When you run a build, every single module on the command line and all of the imported modules get compiled. Object code is generated only for those on the command line, but the others are still compiled. Any imported module which uses a .di file won't have as much to compile, and any templated code that doesn't get used in those modules won't get compiled, but there's still lots of recompilation going on if you compile your program incrementally. And D just isn't set up to compile only a portion of a module. - Jonathan M Davis
Apr 29 2012
parent Timon Gehr <timon.gehr gmx.ch> writes:
On 04/30/2012 07:03 AM, Jonathan M Davis wrote:
 On Sunday, April 29, 2012 21:56:08 H. S. Teoh wrote:
 I wonder if dmd (or rdmd) should have a mode where it *only* compiles
 unittest code (i.e., no main() -- the resulting exe just runs unittests
 and nothing else).
It wouldn't make sense. It's nowhere near as bad as C++, but dmd has to recompile modules all the time unless you compile the entire program at once. When you run a build, every single module on the command line and all of the imported modules get compiled.
Only the symbols that need to be analysed actually get analysed (eg. CTFE, instantiated templates.) The other symbols are merely parsed, and parsing is quite cheap.
 Object code is generated only for those on the
 command line, but the others are still compiled.
I think 'compiled' would imply that some output code is generated.
 Any imported module which
 uses a .di file won't have as much to compile,
There is no difference between .d files and .di files except that the compiler prefers the .di file for imports.
 and any templated code that
 doesn't get used in those modules won't get compiled,  but there's still lots
 of recompilation going on if you compile your program incrementally.
It depends on how much CTFE is performed on the module interface level.
 And D
DMD.
 just isn't set up to compile only a portion of a module.

 - Jonathan M Davis
If that is necessary then the module is too big.
Apr 30 2012
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 4/30/12, Jonathan M Davis <jmdavisProg gmx.com> wrote:
 On Sunday, April 29, 2012 21:56:08 H. S. Teoh wrote:
 I wonder if dmd (or rdmd) should have a mode where it *only* compiles
 unittest code (i.e., no main() -- the resulting exe just runs unittests
 and nothing else).
For RDMD you can do: version(unittest) { } else void main() { // regular code here } And then you can invoke rdmd with --unittest and --main to insert an empty main function when unittesting. Personally I put in a stub main so I don't depend on rdmd features like --main: version(unittest) { void main(string[] args) { } } // stub main else void main() { // regular code here }
Apr 29 2012
prev sibling next sibling parent reply "SomeDude" <lovelydear mailmetrash.com> writes:
On Monday, 30 April 2012 at 03:16:57 UTC, Alex Rønne Petersen 
wrote:
 The problem with D's unit test support is that it doesn't 
 integrate well into real world build processes. I usually have 
 debug and release configurations, and that's it. No test 
 configuration; not only does that over-complicate things, but 
 it also isn't really useful. I want my unit testing to be 
 exhaustive; i.e. I want to test my code in debug and release 
 builds, because those are the builds people are going to be 
 using. Not a test build.

 So, this means that writing unit tests inline is a no-go 
 because that would require either always building with unit 
 tests in all configurations (madness) or having a test 
 configuration (see above).

 Given the above, I've resorted to having a "tester" executable 
 which links in all libraries in my project and tests every 
 module. This means that I have to write my unit tests inside 
 this helper executable, making much of the gain in D's unittest 
 blocks go away.

 And no, the fact that I link libraries into the helper 
 executable doesn't mean that I can just write the unit tests in 
 the libraries in the first place. Doing so would require 
 building them twice: Once for the normal build and once for the 
 "tester" executable.
OK, that makes sense. What a test framework could do, although it's kind of ugly, is first copy the unittest() sections into separate test files, compile them and then link with the tested module code. You would keep the advantage of having test code close to source code, and still compile the real code without -unittest switch.
 (And yes, build times matter when your project gets large 
 enough, even in D.)
Just for information, how big is your project (how many files), and how long does a full build take ? I have no idea how fast the compiler really is (is it GDC or DMD you are using ?).
Apr 30 2012
parent reply =?UTF-8?B?QWxleCBSw7hubmUgUGV0ZXJzZW4=?= <xtzgzorex gmail.com> writes:
On 30-04-2012 11:46, SomeDude wrote:
 On Monday, 30 April 2012 at 03:16:57 UTC, Alex Rønne Petersen wrote:
 The problem with D's unit test support is that it doesn't integrate
 well into real world build processes. I usually have debug and release
 configurations, and that's it. No test configuration; not only does
 that over-complicate things, but it also isn't really useful. I want
 my unit testing to be exhaustive; i.e. I want to test my code in debug
 and release builds, because those are the builds people are going to
 be using. Not a test build.

 So, this means that writing unit tests inline is a no-go because that
 would require either always building with unit tests in all
 configurations (madness) or having a test configuration (see above).

 Given the above, I've resorted to having a "tester" executable which
 links in all libraries in my project and tests every module. This
 means that I have to write my unit tests inside this helper
 executable, making much of the gain in D's unittest blocks go away.

 And no, the fact that I link libraries into the helper executable
 doesn't mean that I can just write the unit tests in the libraries in
 the first place. Doing so would require building them twice: Once for
 the normal build and once for the "tester" executable.
OK, that makes sense. What a test framework could do, although it's kind of ugly, is first copy the unittest() sections into separate test files, compile them and then link with the tested module code. You would keep the advantage of having test code close to source code, and still compile the real code without -unittest switch.
 (And yes, build times matter when your project gets large enough, even
 in D.)
Just for information, how big is your project (how many files), and how long does a full build take ? I have no idea how fast the compiler really is (is it GDC or DMD you are using ?).
I don't have a clone of my repo from where I am now, so I can't count, but it usually takes around ~30 seconds with DMD, ~2 minutes with GDC. -- - Alex
Apr 30 2012
parent reply "SomeDude" <lovelydear mailmetrash.com> writes:
On Monday, 30 April 2012 at 15:19:29 UTC, Alex Rønne Petersen 
wrote:
 On 30-04-2012 11:46, SomeDude wrote:

 I don't have a clone of my repo from where I am now, so I can't 
 count, but it usually takes around ~30 seconds with DMD, ~2 
 minutes with GDC.
For how many files/lines of code ?
Apr 30 2012
parent reply "SomeDude" <lovelydear mailmetrash.com> writes:
On Monday, 30 April 2012 at 16:14:58 UTC, SomeDude wrote:
 On Monday, 30 April 2012 at 15:19:29 UTC, Alex Rønne Petersen 
 wrote:
 On 30-04-2012 11:46, SomeDude wrote:

 I don't have a clone of my repo from where I am now, so I 
 can't count, but it usually takes around ~30 seconds with DMD, 
 ~2 minutes with GDC.
For how many files/lines of code ?
And on what hardware ? I'd like to have a bit of an idea of how fast the compilers really are.
Apr 30 2012
next sibling parent reply Iain Buclaw <ibuclaw ubuntu.com> writes:
On 30 April 2012 17:16, SomeDude <lovelydear mailmetrash.com> wrote:
 On Monday, 30 April 2012 at 16:14:58 UTC, SomeDude wrote:
 On Monday, 30 April 2012 at 15:19:29 UTC, Alex R=F8nne Petersen wrote:
 On 30-04-2012 11:46, SomeDude wrote:

 I don't have a clone of my repo from where I am now, so I can't count,
 but it usually takes around ~30 seconds with DMD, ~2 minutes with GDC.
For how many files/lines of code ?
And on what hardware ? I'd like to have a bit of an idea of how fast the compilers really are.
That sort of speed difference sounds about right. I'm not sure how the DMD backend works, but I assume that there is no more than about 3 passes. A conversion from D Frontend AST to DM Backend AST, possibly a peephole optimiser, then an output to object code. GCC backend has some 50+ passes it processes the generated AST through passed from GDC. Not to mention it only outputs assembly code. So there is some overhead for calling AS to compile to object code (something that DMD just compiles straight to), and double overhead for calling LD to link the resultant binary/library. Regards --=20 Iain Buclaw *(p < e ? p++ : p) =3D (c & 0x0f) + '0';
Apr 30 2012
parent Jacob Carlborg <doob me.com> writes:
On 2012-04-30 18:44, Iain Buclaw wrote:

 GCC backend has some 50+ passes it processes the generated AST through
 passed from GDC. Not to mention it only outputs assembly code.  So
 there is some overhead for calling AS to compile to object code
 (something that DMD just compiles straight to), and double overhead
 for calling LD to link the resultant binary/library.
DMD calls GCC which calls LD. Unless your using the -lib flag. -- /Jacob Carlborg
Apr 30 2012
prev sibling next sibling parent reply Iain Buclaw <ibuclaw ubuntu.com> writes:
On 30 April 2012 17:44, Iain Buclaw <ibuclaw ubuntu.com> wrote:
 On 30 April 2012 17:16, SomeDude <lovelydear mailmetrash.com> wrote:
 On Monday, 30 April 2012 at 16:14:58 UTC, SomeDude wrote:
 On Monday, 30 April 2012 at 15:19:29 UTC, Alex R=F8nne Petersen wrote:
 On 30-04-2012 11:46, SomeDude wrote:

 I don't have a clone of my repo from where I am now, so I can't count,
 but it usually takes around ~30 seconds with DMD, ~2 minutes with GDC.
For how many files/lines of code ?
And on what hardware ? I'd like to have a bit of an idea of how fast the compilers really are.
That sort of speed difference sounds about right. =A0I'm not sure how the DMD backend works, but I assume that there is no more than about 3 passes. =A0A conversion from D Frontend AST to DM Backend AST, possibly a peephole optimiser, then an output to object code. GCC backend has some 50+ passes it processes the generated AST through passed from GDC. Not to mention it only outputs assembly code. =A0So there is some overhead for calling AS to compile to object code (something that DMD just compiles straight to), and double overhead for calling LD to link the resultant binary/library.
Having said that, I did produce a report from GDC once with a list of times it takes to compile D2 code (in this instance, libphobos and druntime). http://iainbuclaw.files.wordpress.com/2010/09/d2-time-report2.pdf TOTAL is the total time taken (ie: 0.08 seconds in the first file), and the other elements are a breakdown of what passes took the longest amount of processing time during the entire compilation. If you could get DMD to pull off a similar report, you'd have something nice to compare to. ;-) Regards --=20 Iain Buclaw *(p < e ? p++ : p) =3D (c & 0x0f) + '0';
Apr 30 2012
parent "SomeDude" <lovelydear mailmetrash.com> writes:
On Monday, 30 April 2012 at 16:54:48 UTC, Iain Buclaw wrote:
 Having said that, I did produce a report from GDC once with a 
 list of
 times it takes to compile D2 code (in this instance, libphobos 
 and
 druntime).

 http://iainbuclaw.files.wordpress.com/2010/09/d2-time-report2.pdf

 TOTAL is the total time taken (ie: 0.08 seconds in the first 
 file),
 and the other elements are a breakdown of what passes took the 
 longest
 amount of processing time during the entire compilation.


 If you could get DMD to pull off a similar report, you'd have
 something nice to compare to. ;-)


 Regards
Thx, that's interesting.
Apr 30 2012
prev sibling next sibling parent reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 4/30/12, SomeDude <lovelydear mailmetrash.com> wrote:
 I'd like to have a bit of an idea of how
 fast the compilers really are.
Personally my gripe with compilation times is that I get very used to having fast build times where I can go through an edit+compile+run cycle really fast, but after a while build times get slower (especially when templates get in the mix) and this really throws me off. Sometimes I wish I could just interpret D code at runtime just to save on compilation time, because I might just be testing the semantics of code and not necessarily its performance at a time.
Apr 30 2012
parent reply "SomeDude" <lovelydear mailmetrash.com> writes:
On Monday, 30 April 2012 at 19:08:54 UTC, Andrej Mitrovic wrote:
 On 4/30/12, SomeDude <lovelydear mailmetrash.com> wrote:
 I'd like to have a bit of an idea of how
 fast the compilers really are.
Personally my gripe with compilation times is that I get very used to having fast build times where I can go through an edit+compile+run cycle really fast, but after a while build times get slower (especially when templates get in the mix) and this really throws me off. Sometimes I wish I could just interpret D code at runtime just to save on compilation time, because I might just be testing the semantics of code and not necessarily its performance at a time.
Yeah, templates is what slows everything down. I'd be very wary of using Boost in C++, for instance, because heavy usage of templates in C++ can slow your development cycle to a crawl in a large project. But in D, the risk of recompilation is limited by the module system, right ?
Apr 30 2012
parent "SomeDude" <lovelydear mailmetrash.com> writes:
On Monday, 30 April 2012 at 21:11:20 UTC, SomeDude wrote:
 But in D, the risk of recompilation is limited by the module 
 system, right ?
Also, in D, bugs in the CTFE slows everything down, in particular this one: http://d.puremagic.com/issues/show_bug.cgi?id=6498
Apr 30 2012
prev sibling parent reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 4/30/12, Andrej Mitrovic <andrej.mitrovich gmail.com> wrote:
 Personally my gripe with compilation times is that I get very used to
 having fast build times where I can go through an edit+compile+run
 cycle really fast, but after a while build times get slower
Also since 2.059 error reporting is *completely* broken. I have to wait 5 seconds just to get this error message itself to print to the screen: http://pastebin.com/y93GEPAf 500 lines of errors even though only the first line is an actual error. What in the actual fuck are all those other error messages? The only problem was this line in a main file: CppGen gen; and CppGen was undefined because I've missed an import. And if I remove the only import left (std.range), I get much less garbage but I still get unrelated errors: main.d(80): Error: undefined identifier CppGen D:\DMD\dmd2\windows\bin\..\..\src\phobos\std\conv.d(244): Error: template std.conv.toImpl does not match any function template declaration D:\DMD\dmd2\windows\bin\..\..\src\phobos\std\conv.d(244): Error: template std.conv.toImpl cannot deduce template function from argument types !(string)(long) D:\DMD\dmd2\windows\bin\..\..\src\phobos\std\conv.d(244): Error: template instance toImpl!(string) errors instantiating template loader\gcc.d(167): Error: template instance std.conv.to!(string).to!(long) error instantiating 2.058 error reporting worked fine, I don't know what someone did to screw this up so massively.
May 08 2012
parent reply Don Clugston <dac nospam.com> writes:
On 08/05/12 09:56, Andrej Mitrovic wrote:
 On 4/30/12, Andrej Mitrovic<andrej.mitrovich gmail.com>  wrote:
 Personally my gripe with compilation times is that I get very used to
 having fast build times where I can go through an edit+compile+run
 cycle really fast, but after a while build times get slower
Also since 2.059 error reporting is *completely* broken. I have to wait 5 seconds just to get this error message itself to print to the screen: http://pastebin.com/y93GEPAf 500 lines of errors even though only the first line is an actual error. What in the actual fuck are all those other error messages? The only problem was this line in a main file: CppGen gen; and CppGen was undefined because I've missed an import. And if I remove the only import left (std.range), I get much less garbage but I still get unrelated errors: main.d(80): Error: undefined identifier CppGen D:\DMD\dmd2\windows\bin\..\..\src\phobos\std\conv.d(244): Error: template std.conv.toImpl does not match any function template declaration D:\DMD\dmd2\windows\bin\..\..\src\phobos\std\conv.d(244): Error: template std.conv.toImpl cannot deduce template function from argument types !(string)(long) D:\DMD\dmd2\windows\bin\..\..\src\phobos\std\conv.d(244): Error: template instance toImpl!(string) errors instantiating template loader\gcc.d(167): Error: template instance std.conv.to!(string).to!(long) error instantiating 2.058 error reporting worked fine, I don't know what someone did to screw this up so massively.
That bug was fixed in git not long after release. Unfortunately it seems that there are not enough people doing beta testing. As for why it happened -- previously the compiler used a hack to prevent the flood of error messages (and the hack didn't work properly in the case where errors were gagged, like in is(typeof()) ). Now it does it properly.
May 08 2012
parent reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 5/8/12, Don Clugston <dac nospam.com> wrote:
 That bug was fixed in git not long after release.
I still get it with this version: http://d.puremagic.com/test-results/test_data.ghtml?dataid=180993 Same errors: http://pastebin.com/8uqgskHd
May 08 2012
parent reply Don Clugston <dac nospam.com> writes:
On 08/05/12 14:50, Andrej Mitrovic wrote:
 On 5/8/12, Don Clugston<dac nospam.com>  wrote:
 That bug was fixed in git not long after release.
I still get it with this version: http://d.puremagic.com/test-results/test_data.ghtml?dataid=180993 Same errors: http://pastebin.com/8uqgskHd
OK, looks like it's a different bug. Please put in bugzilla, with status of regression.
May 09 2012
next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 5/9/12, Don Clugston <dac nospam.com> wrote:
 OK, looks like it's a different bug. Please put in bugzilla, with status
 of regression.
It turns out it's not a regression: http://d.puremagic.com/issues/show_bug.cgi?id=8082 Something odd about module compilation order which makes unrelated modules error out.
May 11 2012
prev sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 5/11/12, Andrej Mitrovic <andrej.mitrovich gmail.com> wrote:
 It turns out it's not a regression:
 http://d.puremagic.com/issues/show_bug.cgi?id=8082
 Something odd about module compilation order which makes unrelated
 modules error out.
In my project making sure my main.d file is compiled *last* reduces the error count from ~400 lines to just 2 error lines.
May 11 2012
prev sibling parent Jacob Carlborg <doob me.com> writes:
On 2012-04-30 05:16, Alex Rønne Petersen wrote:
 On 30-04-2012 05:03, H. S. Teoh wrote:
 On Sun, Apr 29, 2012 at 11:39:02PM +0200, deadalnix wrote:
 Le 29/04/2012 22:54, Alex Rønne Petersen a écrit :
 D unit tests were never really useful for anything beyond
 single-library projects IMHO. They don't scale for large, real-world
 application projects with lots of libraries and executables.
+1 A good std.unittest + attributes is probably a better approach.
The only reason I actually write unittests for D code is because unittest{} is so convenient. If I had to import std.unittest, most likely my code will have no unittests at all. I find that because unittest{} makes it so convenient to write unittests, it's just embarrassing to not write them. Which is kinda the point, 'cos in my experience the act of writing a unittest automatically makes you think about corner cases in the code you just wrote (or just about to write), which means there will be less bugs from the get-go. Also, unittest is just that: for _unit_ tests. If you start needing an entire framework for them, then you're no longer talking about _unit_ tests, you're talking about module- or package-level testing frameworks, and you should be using something more suitable for that, not unittest. T
The problem with D's unit test support is that it doesn't integrate well into real world build processes. I usually have debug and release configurations, and that's it. No test configuration; not only does that over-complicate things, but it also isn't really useful. I want my unit testing to be exhaustive; i.e. I want to test my code in debug and release builds, because those are the builds people are going to be using. Not a test build. So, this means that writing unit tests inline is a no-go because that would require either always building with unit tests in all configurations (madness) or having a test configuration (see above). Given the above, I've resorted to having a "tester" executable which links in all libraries in my project and tests every module. This means that I have to write my unit tests inside this helper executable, making much of the gain in D's unittest blocks go away. And no, the fact that I link libraries into the helper executable doesn't mean that I can just write the unit tests in the libraries in the first place. Doing so would require building them twice: Once for the normal build and once for the "tester" executable. (And yes, build times matter when your project gets large enough, even in D.)
-- /Jacob Carlborg
Apr 30 2012
prev sibling parent deadalnix <deadalnix gmail.com> writes:
Le 30/04/2012 05:03, H. S. Teoh a écrit :
 On Sun, Apr 29, 2012 at 11:39:02PM +0200, deadalnix wrote:
 Le 29/04/2012 22:54, Alex Rønne Petersen a écrit :
 D unit tests were never really useful for anything beyond
 single-library projects IMHO. They don't scale for large, real-world
 application projects with lots of libraries and executables.
+1 A good std.unittest + attributes is probably a better approach.
The only reason I actually write unittests for D code is because unittest{} is so convenient. If I had to import std.unittest, most likely my code will have no unittests at all.
Is unittest on top of a function much more difficult ?
 I find that because unittest{} makes it so convenient to write
 unittests, it's just embarrassing to not write them. Which is kinda the
 point, 'cos in my experience the act of writing a unittest automatically
 makes you think about corner cases in the code you just wrote (or just
 about to write), which means there will be less bugs from the get-go.
Agreed.
 Also, unittest is just that: for _unit_ tests. If you start needing an
 entire framework for them, then you're no longer talking about _unit_
 tests, you're talking about module- or package-level testing frameworks,
 and you should be using something more suitable for that, not unittest.
Consider cases like checking if Liskov substitution principle is fallowed in a class hierarchy running the same unitest on various instantiations in that hierarchy. This is common need and still fall in the unittest bag.
Apr 30 2012
prev sibling parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On Sunday, April 29, 2012 20:03:44 H. S. Teoh wrote:
 On Sun, Apr 29, 2012 at 11:39:02PM +0200, deadalnix wrote:
 Le 29/04/2012 22:54, Alex R=C3=B8nne Petersen a =C3=A9crit :
D unit tests were never really useful for anything beyond
single-library projects IMHO. They don't scale for large, real-wor=
ld
application projects with lots of libraries and executables.
=20 +1 A good std.unittest + attributes is probably a better approach.
=20 The only reason I actually write unittests for D code is because unittest{} is so convenient. If I had to import std.unittest, most likely my code will have no unittests at all. =20 I find that because unittest{} makes it so convenient to write unittests, it's just embarrassing to not write them. Which is kinda t=
he
 point, 'cos in my experience the act of writing a unittest automatica=
lly
 makes you think about corner cases in the code you just wrote (or jus=
t
 about to write), which means there will be less bugs from the get-go.=
=20
 Also, unittest is just that: for _unit_ tests. If you start needing a=
n
 entire framework for them, then you're no longer talking about _unit_=
 tests, you're talking about module- or package-level testing framewor=
ks,
 and you should be using something more suitable for that, not unittes=
t. One common term for those is "component tests." Unit tests are for test= ing=20 individual functions and types, whereas component tests test inter-modu= le and=20 inter-program interactions. What D has with regards to unit tests works _very_ well for basic unit = tests=20 but does not attempt to support component tests at all beyond where uni= ttest=20 blocks could be used for the same purpose. The main place that D's unit= test=20 framework becomes problematic is when you need to run a subset of tests= - it's=20 designed to run everything at once. But compiling and running each modu= le=20 separately for unit tests allows you to control that through you build = system=20 or whatnot. As Walter has stated on several occasions, D's built-in unit testing fr= amework=20 is designed to be incredibly simple and easy so that they're so easy an= d=20 convenient to use that you have no excuse not to. If you want more comp= licated=20 unit testing frameworks, there's nothing stopping you from making your = own=20 like has to be done in other languges. For instance, cppunit and junit = aren't=20 built-in to their associated languages at all; they're 3rd party projec= ts. You=20 can do the same in D if you want fancier unit testing facilities. - Jonathan M Davis
Apr 29 2012
parent reply =?UTF-8?B?QWxleCBSw7hubmUgUGV0ZXJzZW4=?= <xtzgzorex gmail.com> writes:
On 30-04-2012 05:12, Jonathan M Davis wrote:
 On Sunday, April 29, 2012 20:03:44 H. S. Teoh wrote:
 On Sun, Apr 29, 2012 at 11:39:02PM +0200, deadalnix wrote:
 Le 29/04/2012 22:54, Alex Rønne Petersen a écrit :
 D unit tests were never really useful for anything beyond
 single-library projects IMHO. They don't scale for large, real-world
 application projects with lots of libraries and executables.
+1 A good std.unittest + attributes is probably a better approach.
The only reason I actually write unittests for D code is because unittest{} is so convenient. If I had to import std.unittest, most likely my code will have no unittests at all. I find that because unittest{} makes it so convenient to write unittests, it's just embarrassing to not write them. Which is kinda the point, 'cos in my experience the act of writing a unittest automatically makes you think about corner cases in the code you just wrote (or just about to write), which means there will be less bugs from the get-go. Also, unittest is just that: for _unit_ tests. If you start needing an entire framework for them, then you're no longer talking about _unit_ tests, you're talking about module- or package-level testing frameworks, and you should be using something more suitable for that, not unittest.
One common term for those is "component tests." Unit tests are for testing individual functions and types, whereas component tests test inter-module and inter-program interactions. What D has with regards to unit tests works _very_ well for basic unit tests but does not attempt to support component tests at all beyond where unittest blocks could be used for the same purpose. The main place that D's unit test framework becomes problematic is when you need to run a subset of tests - it's designed to run everything at once. But compiling and running each module separately for unit tests allows you to control that through you build system or whatnot. As Walter has stated on several occasions, D's built-in unit testing framework is designed to be incredibly simple and easy so that they're so easy and convenient to use that you have no excuse not to. If you want more complicated unit testing frameworks, there's nothing stopping you from making your own like has to be done in other languges. For instance, cppunit and junit aren't built-in to their associated languages at all; they're 3rd party projects. You can do the same in D if you want fancier unit testing facilities. - Jonathan M Davis
Except we can't do: test void myTest() { // ... } due to the current lack of annotations and discovery-based reflection. ;) *hint hint...* -- - Alex
Apr 29 2012
parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On Monday, April 30, 2012 05:20:21 Alex R=C3=B8nne Petersen wrote:
 Except we can't do:
=20
  test
 void myTest()
 {
      // ...
 }
=20
 due to the current lack of annotations and discovery-based reflection=
. ;)
=20
 *hint hint...*
What would that buy you? That's what unittest blocks are for. Yes, gett= ing=20 custom annotations would be great, and then you could use test for wha= tever=20 you need it for, but unittest blocks are the test functions, so I'm not= quite=20 sure what test would buy you. You _could_ just put a particular string= in a=20 name though (e.g. start all unit test functions with test) and use comp= ile- time reflection to find them if you really want to though (much as that= isn't as=20 nice as a user-defined attribute would be). - Jonathan M Davis
Apr 29 2012
parent =?UTF-8?B?QWxleCBSw7hubmUgUGV0ZXJzZW4=?= <xtzgzorex gmail.com> writes:
On 30-04-2012 05:34, Jonathan M Davis wrote:
 On Monday, April 30, 2012 05:20:21 Alex Rønne Petersen wrote:
 Except we can't do:

  test
 void myTest()
 {
       // ...
 }

 due to the current lack of annotations and discovery-based reflection. ;)

 *hint hint...*
What would that buy you? That's what unittest blocks are for. Yes, getting custom annotations would be great, and then you could use test for whatever you need it for, but unittest blocks are the test functions, so I'm not quite sure what test would buy you. You _could_ just put a particular string in a name though (e.g. start all unit test functions with test) and use compile- time reflection to find them if you really want to though (much as that isn't as nice as a user-defined attribute would be). - Jonathan M Davis
See my other reply to H. S. Teoh for why I'm not a fan of unittest blocks. -- - Alex
Apr 29 2012
prev sibling next sibling parent "Tove" <tove fransson.se> writes:
On Saturday, 28 April 2012 at 18:48:18 UTC, Walter Bright wrote:
 Andrei and I had a fun discussion last night about this 
 question. The idea was which features in D are redundant and/or 
 do not add significant value?

 A couple already agreed upon ones are typedef and the cfloat, 
 cdouble and creal types.

 What's your list?
garbage collector *duck and run* The point I'm trying to make is... normally I would use around 4-5 different languages depending on _what_ problem I'm currently solving... occasionally even languages I'm not particularly proficient with, just because a language might have an edge in a certain domain... however 'D' basically is good enough at "everything"... with some few exceptions. So what one person considers redundant, is integral to someone else with a different background... no, D doesn't have too many features.
Apr 29 2012
prev sibling next sibling parent reply "David Nadlinger" <see klickverbot.at> writes:
On Saturday, 28 April 2012 at 18:48:18 UTC, Walter Bright wrote:
 What's your list?
My personal list of features I could easily live without – some of these might be controversial, but yes, I have written non-trivial amounts of code in both D1 and D2: - Anonymous nested classes: They might be useful in Java, particularly in older incarnations, but not so much in D – never used them. - Comma operator: Kill it with extreme prejudice, it is an anti-feature (allow it in for loop expressions if you really want to, but I think there are better solutions). - Typesafe variadics: They look nice on paper, but I haven't used them once. Often, you either explicitly need C-style variadics, or you want to accept e.g. multiple ranges of the same element type, where you need template variadics anyway. - Unsigned right shift, but I can see how it can be useful (simply underused?). - HexString, DelimitedString, r""-WysiwigString, TokenString: I didn't ever use the former two (for including binary data in the program, ImportExpression is imho much easier than generating a source file containing a HexString). As for r"", every time I actually need WysiwigString, I use backticks, because such strings often contain quotes anyway. Regarding TokenString(i.e. q{}) – it is certainly a very nice idea, especially regarding syntax highlighting, and I occasionally use them for CTFE code generation. But without any kind of support for string interpolation, I typically find myself using normal strings for everything except small self-contained portions of code (where mixin templates would probably be cleaner). The problem is that can't just »interrupt« q{}s strings to do something like »q{…} ~ identifierName ~ q{…}«, because there will most likely be unmatched braces – but this is needed in assembling mixin strings all the time… - Concatenation of adjacent strings: Also an anti-feature, imho. - Floating point comparison operators like !<>= (yes, that _is_ valid D code): I must admit that I seldom write code relying on the finer details of IEEE-754 semantics, but can't they just be »lowered« to a combination of the more common ones? - »Short« floating point literals like .4 instead of 0.4 and 4. instead of 4.0 – the saved characters are not worth the syntax special cases, especially w.r.t. UFCS. - new/delete issues have been discussed many times - Built-in arrays and AAs: They are convenient to use, but as far as I can see the single biggest GC dependency in the language. Why not lower array and AA literals to expression tuples (or whatever) to make the convenient syntax usable with custom (possibly non-GC safe) containers as well? A GC'd default implementation could then be provided in druntime, just like today's arrays and AAs. - shared: TLS by default is great, but only __gshared is really usable right now. IMHO, shared had better been reserved for a comprehensive take on the subject, rather than the half-baked implementation we have right now. David
Apr 29 2012
next sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 04/29/2012 02:26 PM, David Nadlinger wrote:
 TokenString: [...]Regarding TokenString(i.e. q{}) – it is certainly a very
 nice idea, especially regarding syntax highlighting, and I occasionally
 use them for CTFE code generation. But without any kind of support for
 string interpolation, I typically find myself using normal strings for
 everything except small self-contained portions of code (where mixin
 templates would probably be cleaner). The problem is that can't just
 »interrupt« q{}s strings to do something like »q{…} ~ identifierName ~
 q{…}«, because there will most likely be unmatched braces – but this is
 needed in assembling mixin strings all the time…
Lack of string interpolation is not a reason to kill the token string, because CTFE lets you provide the interpolation manually. I use token strings often in this fashion for code generation.
 - Floating point comparison operators like !<>= (yes, that _is_ valid D
 code): I must admit that I seldom write code relying on the finer
 details of IEEE-754 semantics, but can't they just be »lowered« to a
 combination of the more common ones?
I kinda like those ;D.
Apr 29 2012
prev sibling next sibling parent "Adam D. Ruppe" <destructionator gmail.com> writes:
On Sunday, 29 April 2012 at 12:26:13 UTC, David Nadlinger wrote:
  - Anonymous nested classes: They might be useful in Java, 
 particularly in older incarnations, but not so much in D – 
 never used them.
I never used these until very recently. A couple weeks ago, I wanted to do some kind of range adapter kinda like Phobos does with the anon structs... but I wanted it to work with runtime too. So, I made an interface with empty, front, popFront, and then pulled out the old "return new class ByChunkRange" for the first time. I never expected that I'd use it, but it was nice to have for that time when I did decide I wanted it. That's my biggest concern with saying we have too many features. We might not use them often, but it would suck to say "that would be perfect" just to find it was removed later.
Apr 29 2012
prev sibling next sibling parent reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 4/29/12, David Nadlinger <see klickverbot.at> wrote:
 As for r"", every time I
 actually need WysiwigString, I use backticks, because such
 strings often contain quotes anyway.
IIRC I think the reason for this might be that some keyboards don't have the backtick key, or something like that.
 Regarding TokenString(i.e.
 q{}) .. The problem is that
 can't just =BBinterrupt=AB q{}s strings to do something like
 =BBq{=85} ~ identifierName ~ q{=85}=AB,
I typically use format for these purposes, e.g.: string x =3D format(q{ void %s() { } }, "foo"); Works fairly well for me.
   - Concatenation of adjacent strings: Also an anti-feature, imho.
Absolutely!
   - =BBShort=AB floating point literals like .4 instead of 0.4 and
 4. instead of 4.0 =96 the saved characters are not worth the
 syntax special cases, especially w.r.t. UFCS.
I think those are already deprecated? Or they're about to be anyway.
   - shared: TLS by default is great, but only __gshared is really
 usable right now.
Yep, and Phobos doesn't deal with shared all that well either. E.g. format() doesn't work on shared variables (http://d.puremagic.com/issues/show_bug.cgi?id=3D7036).
Apr 29 2012
parent reply "bearophile" <bearophileHUGS lycos.com> writes:
Andrej Mitrovic:

   - »Short« floating point literals like .4 instead of 0.4 
 and
 4. instead of 4.0 – the saved characters are not worth the
 syntax special cases, especially w.r.t. UFCS.
I think those are already deprecated? Or they're about to be anyway.
I have asked for it, but currently there are no plans in deprecating them, please vote if you agree and you have free votes left (already 7 votes! It's a lot): http://d.puremagic.com/issues/show_bug.cgi?id=6277 Bye, bearophile
Apr 29 2012
parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 4/29/12, bearophile <bearophileHUGS lycos.com> wrote:
 I have asked for it, but currently there are no plans in
 deprecating them, please vote if you agree and you have free
 votes left (already 7 votes! It's a lot):
Well I assumed they're on the way to deprecation when I've read this: http://dlang.org/changelog.html#new2_058: "Allow 1.userproperty syntax. NOTE: 1.f is no longer a float literal, add a 0."
Apr 29 2012
prev sibling next sibling parent reply "David Nadlinger" <see klickverbot.at> writes:
On Sunday, 29 April 2012 at 12:26:13 UTC, David Nadlinger wrote:
 On Saturday, 28 April 2012 at 18:48:18 UTC, Walter Bright wrote:
 What's your list?
My personal list of features I could easily live without – some of these might be controversial, but yes, I have written non-trivial amounts of code in both D1 and D2:
What I forgot to mention: - VersionCondition: Just provide a mechanism to map command line flags to constants, probably in a magic »version« namespace, and use static if (e.g. »version (Foo)« -> »static if (version.Foo)«, »version (unittest)« -> »static if (unittest)«). - DebugCondition: Hardly used in practice, at least not in ways that couldn't easily be replaced with a static if (resp. version). It is a frequent source of confusion for newcomers that -debug is orthogonal to -O/-release, and I'm not too fond of the purity »escape hatch« built in (why not just use casts in those rare cases?). David
Apr 29 2012
next sibling parent =?UTF-8?B?QWxleCBSw7hubmUgUGV0ZXJzZW4=?= <xtzgzorex gmail.com> writes:
On 29-04-2012 21:19, David Nadlinger wrote:
 On Sunday, 29 April 2012 at 12:26:13 UTC, David Nadlinger wrote:
 On Saturday, 28 April 2012 at 18:48:18 UTC, Walter Bright wrote:
 What's your list?
My personal list of features I could easily live without – some of these might be controversial, but yes, I have written non-trivial amounts of code in both D1 and D2:
What I forgot to mention: - VersionCondition: Just provide a mechanism to map command line flags to constants, probably in a magic »version« namespace, and use static if (e.g. »version (Foo)« -> »static if (version.Foo)«, »version (unittest)« -> »static if (unittest)«).
Something like that seems reasonable. At any rate, version in its current state is not very useful in practice.
 - DebugCondition: Hardly used in practice, at least not in ways that
 couldn't easily be replaced with a static if (resp. version). It is a
 frequent source of confusion for newcomers that -debug is orthogonal to
 -O/-release, and I'm not too fond of the purity »escape hatch« built in
 (why not just use casts in those rare cases?).
+1. And debug being a keyword is more annoying than you'd think.
 David
-- - Alex
Apr 29 2012
prev sibling parent reply "SomeDude" <lovelydear mailmetrash.com> writes:
On Sunday, 29 April 2012 at 19:19:51 UTC, David Nadlinger wrote:
 On Sunday, 29 April 2012 at 12:26:13 UTC, David Nadlinger wrote:
 What I forgot to mention:
  - VersionCondition: Just provide a mechanism to map command 
 line flags to constants, probably in a magic »version« 
 namespace, and use static if (e.g. »version (Foo)« -> 
 »static if (version.Foo)«, »version (unittest)« -> »static 
 if (unittest)«).
It sounds indeed nice, but I prefer convention over configuration. Experience has shown that it makes things simpler.
Apr 29 2012
parent "David Nadlinger" <see klickverbot.at> writes:
On Sunday, 29 April 2012 at 21:23:41 UTC, SomeDude wrote:
 On Sunday, 29 April 2012 at 19:19:51 UTC, David Nadlinger wrote:
 What I forgot to mention:
 - VersionCondition: Just provide a mechanism to map command 
 line flags to constants, probably in a magic »version« 
 namespace, and use static if (e.g. »version (Foo)« -> 
 »static if (version.Foo)«, »version (unittest)« -> 
 »static if (unittest)«).
It sounds indeed nice, but I prefer convention over configuration. Experience has shown that it makes things simpler.
What exactly does this have to do with »convention over configuration«? The big problem with version conditionals is that they introduce a heavily restricted subset of static if, i.e. a whole new language construct, for questionable benefits. David
Apr 29 2012
prev sibling next sibling parent reply =?UTF-8?B?QWxleCBSw7hubmUgUGV0ZXJzZW4=?= <xtzgzorex gmail.com> writes:
On 29-04-2012 14:26, David Nadlinger wrote:
 On Saturday, 28 April 2012 at 18:48:18 UTC, Walter Bright wrote:
 What's your list?
My personal list of features I could easily live without – some of these might be controversial, but yes, I have written non-trivial amounts of code in both D1 and D2: - Anonymous nested classes: They might be useful in Java, particularly in older incarnations, but not so much in D – never used them.
I use them. They can be useful when you're writing more object-oriented code than functional style code.
 - Comma operator: Kill it with extreme prejudice, it is an anti-feature
 (allow it in for loop expressions if you really want to, but I think
 there are better solutions).
+9001.
 - Typesafe variadics: They look nice on paper, but I haven't used them
 once. Often, you either explicitly need C-style variadics, or you want
 to accept e.g. multiple ranges of the same element type, where you need
 template variadics anyway.

 - Unsigned right shift, but I can see how it can be useful (simply
 underused?).
It's clear that arithmetic right shift is what the programmer usually wants, and yet, we use >> to denote what they don't want. It's completely counter-intuitive. So, +1.
 - HexString, DelimitedString, r""-WysiwigString, TokenString: I didn't
 ever use the former two (for including binary data in the program,
 ImportExpression is imho much easier than generating a source file
 containing a HexString). As for r"", every time I actually need
 WysiwigString, I use backticks, because such strings often contain
 quotes anyway. Regarding TokenString(i.e. q{}) – it is certainly a very
 nice idea, especially regarding syntax highlighting, and I occasionally
 use them for CTFE code generation. But without any kind of support for
 string interpolation, I typically find myself using normal strings for
 everything except small self-contained portions of code (where mixin
 templates would probably be cleaner). The problem is that can't just
 »interrupt« q{}s strings to do something like »q{…} ~ identifierName ~
 q{…}«, because there will most likely be unmatched braces – but this is
 needed in assembling mixin strings all the time…

 - Concatenation of adjacent strings: Also an anti-feature, imho.
+1.
 - Floating point comparison operators like !<>= (yes, that _is_ valid D
 code): I must admit that I seldom write code relying on the finer
 details of IEEE-754 semantics, but can't they just be »lowered« to a
 combination of the more common ones?
Why not just make them intrinsics? What are they doing in the language? You're rarely, if ever, going to actually be using these operators because NaN is, well, an invalid state, like null. +1.
 - »Short« floating point literals like .4 instead of 0.4 and 4. instead
 of 4.0 – the saved characters are not worth the syntax special cases,
 especially w.r.t. UFCS.
+1. I find it to be poor style to not include the ".0" in FP literals.
 - new/delete issues have been discussed many times

 - Built-in arrays and AAs: They are convenient to use, but as far as I
 can see the single biggest GC dependency in the language. Why not lower
 array and AA literals to expression tuples (or whatever) to make the
 convenient syntax usable with custom (possibly non-GC safe) containers
 as well? A GC'd default implementation could then be provided in
 druntime, just like today's arrays and AAs.
Sounds reasonable.
 - shared: TLS by default is great, but only __gshared is really usable
 right now. IMHO, shared had better been reserved for a comprehensive
 take on the subject, rather than the half-baked implementation we have
 right now.

 David
It's clear that shared is biased towards heavily templatized code. It's not useful in non-templatized code because such code can't accept both shared and non-shared values. shared looks neat in theory, but is a fallacy in practice. -- - Alex
Apr 29 2012
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 04/29/2012 10:59 PM, Alex Rønne Petersen wrote:
 On 29-04-2012 14:26, David Nadlinger wrote:
 - Unsigned right shift, but I can see how it can be useful (simply
 underused?).
It's clear that arithmetic right shift is what the programmer usually wants, and yet, we use >> to denote what they don't want. It's completely counter-intuitive. So, +1.
'>>' is arithmetic right shift.
 - shared: TLS by default is great, but only __gshared is really usable
 right now. IMHO, shared had better been reserved for a comprehensive
 take on the subject, rather than the half-baked implementation we have
 right now.

 David
It's clear that shared is biased towards heavily templatized code. It's not useful in non-templatized code because such code can't accept both shared and non-shared values.
Just cast it away if you do eg. locking. There is nothing wrong with it. Code that operates on both (actually) shared and unshared data should be uncommon anyway.
 shared looks neat in theory, but is a fallacy in practice.
unshared is what is important. There is no unshared if there is no shared.
Apr 29 2012
parent reply =?UTF-8?B?QWxleCBSw7hubmUgUGV0ZXJzZW4=?= <xtzgzorex gmail.com> writes:
On 30-04-2012 00:08, Timon Gehr wrote:
 On 04/29/2012 10:59 PM, Alex Rønne Petersen wrote:
 On 29-04-2012 14:26, David Nadlinger wrote:
 - Unsigned right shift, but I can see how it can be useful (simply
 underused?).
It's clear that arithmetic right shift is what the programmer usually wants, and yet, we use >> to denote what they don't want. It's completely counter-intuitive. So, +1.
'>>' is arithmetic right shift.
Sorry, I managed to get myself confused here. What I meant to say was that I think >> should do an arithmetic shift if the operands are signed; unsigned shift otherwise.
 - shared: TLS by default is great, but only __gshared is really usable
 right now. IMHO, shared had better been reserved for a comprehensive
 take on the subject, rather than the half-baked implementation we have
 right now.

 David
It's clear that shared is biased towards heavily templatized code. It's not useful in non-templatized code because such code can't accept both shared and non-shared values.
Just cast it away if you do eg. locking. There is nothing wrong with it. Code that operates on both (actually) shared and unshared data should be uncommon anyway.
The problem is that shared is supposed to insert memory barriers (I know it doesn't, but that's the goal/idea).
 shared looks neat in theory, but is a fallacy in practice.
unshared is what is important. There is no unshared if there is no shared.
I think this statement went over my head... -- - Alex
Apr 29 2012
parent reply "jerro" <a a.com> writes:
 Sorry, I managed to get myself confused here. What I meant to 
 say was that I think >> should do an arithmetic shift if the 
 operands are signed; unsigned shift otherwise.
It does arithmetic shift if the left operand is signed, unsigned shift otherwise. This code: void main() { int a = 0xffffffff; uint b = a; writefln("%x", a >> 1); writefln("%x", b >> 1); } prints ffffffff 7fffffff
Apr 29 2012
parent reply =?UTF-8?B?QWxleCBSw7hubmUgUGV0ZXJzZW4=?= <xtzgzorex gmail.com> writes:
On 30-04-2012 08:37, jerro wrote:
 Sorry, I managed to get myself confused here. What I meant to say was
 that I think >> should do an arithmetic shift if the operands are
 signed; unsigned shift otherwise.
It does arithmetic shift if the left operand is signed, unsigned shift otherwise. This code: void main() { int a = 0xffffffff; uint b = a; writefln("%x", a >> 1); writefln("%x", b >> 1); } prints ffffffff 7fffffff
The documentation disagrees: http://dlang.org/expression.html#ShiftExpression It claims that it always does arithmetic shift and >>> always does unsigned shift. -- - Alex
Apr 30 2012
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 04/30/2012 05:21 PM, Alex Rønne Petersen wrote:
 On 30-04-2012 08:37, jerro wrote:
 Sorry, I managed to get myself confused here. What I meant to say was
 that I think >> should do an arithmetic shift if the operands are
 signed; unsigned shift otherwise.
It does arithmetic shift if the left operand is signed, unsigned shift otherwise. This code: void main() { int a = 0xffffffff; uint b = a; writefln("%x", a >> 1); writefln("%x", b >> 1); } prints ffffffff 7fffffff
The documentation disagrees: http://dlang.org/expression.html#ShiftExpression It claims that it always does arithmetic shift and >>> always does unsigned shift.
http://d.puremagic.com/issues/show_bug.cgi?id=8007
Apr 30 2012
parent reply =?UTF-8?B?QWxleCBSw7hubmUgUGV0ZXJzZW4=?= <xtzgzorex gmail.com> writes:
On 30-04-2012 20:17, Timon Gehr wrote:
 On 04/30/2012 05:21 PM, Alex Rønne Petersen wrote:
 On 30-04-2012 08:37, jerro wrote:
 Sorry, I managed to get myself confused here. What I meant to say was
 that I think >> should do an arithmetic shift if the operands are
 signed; unsigned shift otherwise.
It does arithmetic shift if the left operand is signed, unsigned shift otherwise. This code: void main() { int a = 0xffffffff; uint b = a; writefln("%x", a >> 1); writefln("%x", b >> 1); } prints ffffffff 7fffffff
The documentation disagrees: http://dlang.org/expression.html#ShiftExpression It claims that it always does arithmetic shift and >>> always does unsigned shift.
http://d.puremagic.com/issues/show_bug.cgi?id=8007
Thanks; these kinds of documentation bugs can cause really nasty misunderstandings. -- - Alex
Apr 30 2012
parent Timon Gehr <timon.gehr gmx.ch> writes:
On 04/30/2012 08:30 PM, Alex Rønne Petersen wrote:
 On 30-04-2012 20:17, Timon Gehr wrote:
 On 04/30/2012 05:21 PM, Alex Rønne Petersen wrote:
 On 30-04-2012 08:37, jerro wrote:
 Sorry, I managed to get myself confused here. What I meant to say was
 that I think >> should do an arithmetic shift if the operands are
 signed; unsigned shift otherwise.
It does arithmetic shift if the left operand is signed, unsigned shift otherwise. This code: void main() { int a = 0xffffffff; uint b = a; writefln("%x", a >> 1); writefln("%x", b >> 1); } prints ffffffff 7fffffff
The documentation disagrees: http://dlang.org/expression.html#ShiftExpression It claims that it always does arithmetic shift and >>> always does unsigned shift.
http://d.puremagic.com/issues/show_bug.cgi?id=8007
Thanks; these kinds of documentation bugs can cause really nasty misunderstandings.
I don't trust the documentation. In my experience, it is usually best to rely on common sense to get a grasp for how a feature is supposed to behave (that works surprisingly well!) and occasionally file bug reports if either the documentation or DMD is strange in a certain aspect. (I'll probably file a bunch of implicit-conversion related bugs tomorrow.)
Apr 30 2012
prev sibling next sibling parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Sun, Apr 29, 2012 at 02:26:12PM +0200, David Nadlinger wrote:
[...]
  - Comma operator: Kill it with extreme prejudice, it is an
  anti-feature (allow it in for loop expressions if you really want to,
  but I think there are better solutions).
+1. The voice of reason. [...]
  - HexString, DelimitedString, r""-WysiwigString, TokenString: I
 didn't ever use the former two (for including binary data in the
 program, ImportExpression is imho much easier than generating a
 source file containing a HexString).
I found hexstrings useful for writing unittests for testing Unicode handling (I wanted to test both big- and little-endian UTF-16 and UTF-32, whereas currently string literals can only produce native endian). It might also be useful for unittesting code that takes binary input.
 As for r"", every time I actually need WysiwigString, I use backticks,
 because such strings often contain quotes anyway.
+1. I think r"" and `` should be merged. Having both is too much.
 Regarding TokenString(i.e. q{}) – it is certainly a very nice idea,
 especially regarding syntax highlighting, and I occasionally use them
 for CTFE code generation.
I use tokenstrings a lot for mixins. But arguably that use case would be obsolete when D finally finds a good macro system. [...]
  - Concatenation of adjacent strings: Also an anti-feature, imho.
I personally find them useful for nicely-formatting code that contains lots of long strings. But YMMV.
  - Floating point comparison operators like !<>= (yes, that _is_ valid
  D code): I must admit that I seldom write code relying on the finer
  details of IEEE-754 semantics, but can't they just be »lowered« to a
  combination of the more common ones?
Yeah when I was writing a D lexer (just as an exercise) I was flabbergasted at the sheer amount of comparison operators D has. I mean, I don't know if I will ever use *half* of them in my lifetime. After a while my eyes were just glazing over from all the ASCII UFO's that somehow flew into my code from outer space. If IEEE-754 support is what the intention was, I'd recommend putting them in std.math instead of loading the language with a bunch of apparently-oxymoronic operators like !<> and !<>=, that probably nothing outside of IEEE-754 buffs will ever even care about. [...]
  - Built-in arrays and AAs: They are convenient to use, but as far as
  I can see the single biggest GC dependency in the language. Why not
  lower array and AA literals to expression tuples (or whatever) to
  make the convenient syntax usable with custom (possibly non-GC safe)
  containers as well? A GC'd default implementation could then be
  provided in druntime, just like today's arrays and AAs.
[...] AA's are moving into druntime. Yours truly is supposed to make that happen eventually, but lately time hasn't been on my side. :-/ This is an interesting idea, though... once we've fully excised AA's from dmd (aside from convenient lowerings from native syntax), it will open up the possibility of writing a GC-less druntime replacement that also provides an alternate implementation of AA's that don't depend on the GC. T -- This is not a sentence.
Apr 29 2012
parent reply "David Nadlinger" <see klickverbot.at> writes:
On Monday, 30 April 2012 at 03:16:09 UTC, H. S. Teoh wrote:
 On Sun, Apr 29, 2012 at 02:26:12PM +0200, David Nadlinger wrote:
 […]
  - Built-in arrays and AAs: They are convenient to use, but as 
 far as
  I can see the single biggest GC dependency in the language. 
 Why not
  lower array and AA literals to expression tuples (or 
 whatever) to
  make the convenient syntax usable with custom (possibly 
 non-GC safe)
  containers as well? A GC'd default implementation could then 
 be
  provided in druntime, just like today's arrays and AAs.
[...] AA's are moving into druntime. Yours truly is supposed to make that happen eventually, but lately time hasn't been on my side. :-/
This moves the _implementation_ to druntime, but there is still realistically no way to use AA literals with my own non-GC'd version of hash maps without shipping a custom druntime (and thus modifying the semantics of an existing language construct). What I'm talking about would let you do things like MyVector!int stuff = [1, 2, 3, 4, 5]; without needing a (temporary) GC'd allocation, and thus please the GC-hater crowd because they can still have all the syntax candy with their own containers, even if they can't resp. don't want to use the default GC'd constructs. David
Apr 29 2012
parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Mon, Apr 30, 2012 at 07:07:53AM +0200, David Nadlinger wrote:
 On Monday, 30 April 2012 at 03:16:09 UTC, H. S. Teoh wrote:
On Sun, Apr 29, 2012 at 02:26:12PM +0200, David Nadlinger wrote:
[…]
 - Built-in arrays and AAs: They are convenient to use, but as
far as I can see the single biggest GC dependency in the language.
Why not lower array and AA literals to expression tuples (or
whatever) to make the convenient syntax usable with custom (possibly
non-GC safe) containers as well? A GC'd default implementation could
then be provided in druntime, just like today's arrays and AAs.
[...] AA's are moving into druntime. Yours truly is supposed to make that happen eventually, but lately time hasn't been on my side. :-/
This moves the _implementation_ to druntime, but there is still realistically no way to use AA literals with my own non-GC'd version of hash maps without shipping a custom druntime (and thus modifying the semantics of an existing language construct). What I'm talking about would let you do things like MyVector!int stuff = [1, 2, 3, 4, 5]; without needing a (temporary) GC'd allocation, and thus please the GC-hater crowd because they can still have all the syntax candy with their own containers, even if they can't resp. don't want to use the default GC'd constructs.
[...] I think you're talking about two orthogonal issues here. One is language-level support for arrays and AA's, which IMO are necessary and are even a plus (built-in AA's are one of the big reasons I chose D). The other is language-level support for literal syntax in user-defined types. I think the latter area has lots of room for improvement. From a theoretical standpoint, syntax like [1,2,3,4,5] really should not be prematurely tied to a specific type: at the most fundamental level, it's just specifying a list of things. How the abstract concept of a list of things should be implemented need not be constrained to concrete built-in types; I'd argue that the language should permit the realization of the concept in a user-defined type as well (i.e., the literal interpreted by a user type). Just off the top of my head, this might be achievable by introducing a fromList method in user-defined types that takes a compile-time parameter containing some representation of the list, say as a builtin array. This method then does whatever is needed to create an instance of the type accordingly. (Since the parameter is compile-time, this essentially just generates code to create the custom container directly.) The same thing can be done for custom floating-point literals, say. A fromFloat() method takes a compile-time string containing the literal, and creates an instance of the custom type. (A string is used here so that you can implement types that far exceed the maximum precision of any builtin type.) Ditto for AA literals: a fromAA() method takes a compile-time list of key/value pairs and does whatever it needs to do to create the appropriate runtime AA. In fact, such a construct would alleviate much of the need for compiler hacks to support AA's (both old and the prospective new replacement). There will be no unnecessary overhead of allocating runtime arrays, copying, etc.; the fromAA() method at compile-time generates whatever code is necessary to create the literal into the target object directly. This is a language enhancement issue, though, not really an issue about builtin AA's or arrays being "unnecessary features". T -- All men are mortal. Socrates is mortal. Therefore all men are Socrates.
Apr 29 2012
parent reply Dmitry Olshansky <dmitry.olsh gmail.com> writes:
On 30.04.2012 9:33, H. S. Teoh wrote:
 On Mon, Apr 30, 2012 at 07:07:53AM +0200, David Nadlinger wrote:
 On Monday, 30 April 2012 at 03:16:09 UTC, H. S. Teoh wrote:
 On Sun, Apr 29, 2012 at 02:26:12PM +0200, David Nadlinger wrote:
 […]
 - Built-in arrays and AAs: They are convenient to use, but as
 far as I can see the single biggest GC dependency in the language.
 Why not lower array and AA literals to expression tuples (or
 whatever) to make the convenient syntax usable with custom (possibly
 non-GC safe) containers as well? A GC'd default implementation could
 then be provided in druntime, just like today's arrays and AAs.
[...] AA's are moving into druntime. Yours truly is supposed to make that happen eventually, but lately time hasn't been on my side. :-/
This moves the _implementation_ to druntime, but there is still realistically no way to use AA literals with my own non-GC'd version of hash maps without shipping a custom druntime (and thus modifying the semantics of an existing language construct). What I'm talking about would let you do things like MyVector!int stuff = [1, 2, 3, 4, 5]; without needing a (temporary) GC'd allocation, and thus please the GC-hater crowd because they can still have all the syntax candy with their own containers, even if they can't resp. don't want to use the default GC'd constructs.
[...] I think you're talking about two orthogonal issues here. One is language-level support for arrays and AA's, which IMO are necessary and are even a plus (built-in AA's are one of the big reasons I chose D). The other is language-level support for literal syntax in user-defined types. I think the latter area has lots of room for improvement. From a theoretical standpoint, syntax like [1,2,3,4,5] really should not be prematurely tied to a specific type: at the most fundamental level, it's just specifying a list of things. How the abstract concept of a list of things should be implemented need not be constrained to concrete built-in types; I'd argue that the language should permit the realization of the concept in a user-defined type as well (i.e., the literal interpreted by a user type). Just off the top of my head, this might be achievable by introducing a fromList method in user-defined types that takes a compile-time parameter containing some representation of the list, say as a builtin array. This method then does whatever is needed to create an instance of the type accordingly. (Since the parameter is compile-time, this essentially just generates code to create the custom container directly.) The same thing can be done for custom floating-point literals, say. A fromFloat() method takes a compile-time string containing the literal, and creates an instance of the custom type. (A string is used here so that you can implement types that far exceed the maximum precision of any builtin type.) Ditto for AA literals: a fromAA() method takes a compile-time list of key/value pairs and does whatever it needs to do to create the appropriate runtime AA. In fact, such a construct would alleviate much of the need for compiler hacks to support AA's (both old and the prospective new replacement). There will be no unnecessary overhead of allocating runtime arrays, copying, etc.; the fromAA() method at compile-time generates whatever code is necessary to create the literal into the target object directly. This is a language enhancement issue, though, not really an issue about builtin AA's or arrays being "unnecessary features".
*cough* initializer lists *cough* Seriously let AA liters be an sorted initializer list (conceptual compile-time array) of pairs, and normal array literal just plain initializer list of common type. This also nails nicely strange use case of AA literal to build array (just the same sorted table of pairs!). The AA then is just initialized with sorted array at run-time. (as it does anyway) -- Dmitry Olshansky
Apr 30 2012
next sibling parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Mon, Apr 30, 2012 at 11:46:09AM +0400, Dmitry Olshansky wrote:
 On 30.04.2012 9:33, H. S. Teoh wrote:
[...]
I think the latter area has lots of room for improvement. From a
theoretical standpoint, syntax like [1,2,3,4,5] really should not be
prematurely tied to a specific type: at the most fundamental level,
it's just specifying a list of things. How the abstract concept of a
list of things should be implemented need not be constrained to
concrete built-in types; I'd argue that the language should permit
the realization of the concept in a user-defined type as well (i.e.,
the literal interpreted by a user type).

Just off the top of my head, this might be achievable by introducing
a fromList method in user-defined types that takes a compile-time
parameter containing some representation of the list, say as a
builtin array. This method then does whatever is needed to create an
instance of the type accordingly. (Since the parameter is
compile-time, this essentially just generates code to create the
custom container directly.)
[...]
 *cough* initializer lists *cough*
 
 Seriously let AA liters be an sorted initializer list (conceptual
 compile-time array) of pairs, and normal array literal just plain
 initializer list of common type.
 
 This also nails nicely strange use case of AA literal to build array
 (just the same sorted table of pairs!).  The AA then is just
 initialized with sorted array at run-time. (as it does anyway)
[...] +1, this is an excellent idea! It also solves the case of byte[], uint[], int[], etc., all being initializable by "[1,2,3]". Currently, subtle bugs are introduced in certain contexts by the compiler interpreting [1,2,3] to be int[] by default. What we really should do is to pass it in as a compile-time initializer list to the relevant ctors. So byte[].this() will interpret [1,2,3] as bytes, uint[].this() will interpret it as uints, etc.. Then you can write: uint[] a = [ 2: 100, 10: 200 ] and it will be equivalent to: uint[] a = [0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 200]; T -- The most powerful one-line C program: #include "/dev/tty" -- IOCCC
Apr 30 2012
prev sibling next sibling parent reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 4/30/12, H. S. Teoh <hsteoh quickfur.ath.cx> wrote:
 Then
 you can write:

 	uint[] a = [
 		2: 100,
 		10: 200
 	]

 and it will be equivalent to:

 	uint[] a = [0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 200];
But you can already use this syntax right now?
Apr 30 2012
parent "bearophile" <bearophileHUGS lycos.com> writes:
Andrej Mitrovic:

 	uint[] a = [0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 200];
But you can already use this syntax right now?
But there is a syntax problem: http://d.puremagic.com/issues/show_bug.cgi?id=4703 Bye, bearophile
Apr 30 2012
prev sibling parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Mon, Apr 30, 2012 at 09:06:06PM +0200, Andrej Mitrovic wrote:
 On 4/30/12, H. S. Teoh <hsteoh quickfur.ath.cx> wrote:
 Then
 you can write:

 	uint[] a = [
 		2: 100,
 		10: 200
 	]

 and it will be equivalent to:

 	uint[] a = [0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 200];
But you can already use this syntax right now?
Yes I know you can, it was more of using this syntax for user-defined types without allocating a temporary array. T -- Computers shouldn't beep through the keyhole.
Apr 30 2012
parent Dmitry Olshansky <dmitry.olsh gmail.com> writes:
On 30.04.2012 23:14, H. S. Teoh wrote:
 On Mon, Apr 30, 2012 at 09:06:06PM +0200, Andrej Mitrovic wrote:
 On 4/30/12, H. S. Teoh<hsteoh quickfur.ath.cx>  wrote:
 Then
 you can write:

 	uint[] a = [
 		2: 100,
 		10: 200
 	]

 and it will be equivalent to:

 	uint[] a = [0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 200];
But you can already use this syntax right now?
Yes I know you can, it was more of using this syntax for user-defined types without allocating a temporary array.
Yes I tried to point out that this also makes this code straight forward. AND allows other AA-like enitites to benefit from it. Most importantly it doesn't break a thing. Just generalizes. -- Dmitry Olshansky
Apr 30 2012
prev sibling parent Walter Bright <newshound2 digitalmars.com> writes:
On 4/29/2012 5:26 AM, David Nadlinger wrote:
 - Anonymous nested classes: They might be useful in Java, particularly in older
 incarnations, but not so much in D – never used them.
I don't like them, either, but they were put in at the recommendation of people who were porting large piles of Java code to D. It made semi-mechanical translation much more feasible. Using them for any other purpose is likely a bad idea, as the only reason they exist in Java is as a kludge to work around limitations in Java.
Apr 30 2012
prev sibling next sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2012-04-28 20:47, Walter Bright wrote:
 Andrei and I had a fun discussion last night about this question. The
 idea was which features in D are redundant and/or do not add significant
 value?

 A couple already agreed upon ones are typedef and the cfloat, cdouble
 and creal types.

 What's your list?
* Some of the built-in properties could probably be move to a library solution, specially now when we have UFCS. * The with-statement isn't particular useful. Although I've started to use it in one of my projects just so I don't have to use fully qualified enum names. * D embedded in HTML (don't know if this is still supported) * Multiple syntax for wysiwyg strings. I think the r"" syntax can be remove. * Do-while loops, how useful are those actually? Then I think some features could be replaced with library solutions if D got some other features. For example: * foreach(_reverse) * synchronized These could probably be removed in favor of library solutions. void foreach (T)(T[] arr, void delegate (ref T) dg) { for (size_t i = 0; i < arr.length; i++) dg(arr[i]); } foreach ([1, 2, 3, 4], (i) { writeln(i); }); The above already works today. If we can a bit syntax sugar for delegates and inlinable delegates we could have this: foreach ([1, 2, 3, 4] ; i) { writeln(i); } The above syntax would be very useful in other cases as well. The same could be done for "synchronized" as well. Might even be possible to remove the for-statement and just have "while" left. I we want get even more wild and crazy I think Scala's solution for operator overloading looks really good. But that would require several other features to work. Like: * Everything is an object (might not be needed with UFCS) * Everything is a method call on an object * Infix notation for calling any method taking one argument * Basically any symbol is allowed in method names That is: 1 + 2 foo bar foo_bar Would be translated to: 1.+(2) foo.bar(foo_bar) That is a very general way to handle operators and let the user create new operators, not just overloading existing ones. -- /Jacob Carlborg
Apr 29 2012
next sibling parent Dmitry Olshansky <dmitry.olsh gmail.com> writes:
On 29.04.2012 18:40, Jacob Carlborg wrote:

 1 + 2
 foo bar foo_bar

 Would be translated to:

 1.+(2)
 foo.bar(foo_bar)

 That is a very general way to handle operators and let the user create
 new operators, not just overloading existing ones.
warning(1): Smalltalk detected! [use -foop-only to ignore] Operator precedence would get real tricky (or stupid just like in Smalltalk). -- Dmitry Olshansky
Apr 29 2012
prev sibling next sibling parent reply "David Nadlinger" <see klickverbot.at> writes:
On Sunday, 29 April 2012 at 14:40:38 UTC, Jacob Carlborg wrote:
 foreach ([1, 2, 3, 4], (i)  { writeln(i); });

 The above already works today. If we can a bit syntax sugar for 
 delegates and inlinable delegates we could have this:

 foreach ([1, 2, 3, 4] ; i) {
     writeln(i);
 }
We'd still need a solution for continue and break, though. David
Apr 29 2012
next sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2012-04-29 17:07, David Nadlinger wrote:
 On Sunday, 29 April 2012 at 14:40:38 UTC, Jacob Carlborg wrote:
 foreach ([1, 2, 3, 4], (i) { writeln(i); });

 The above already works today. If we can a bit syntax sugar for
 delegates and inlinable delegates we could have this:

 foreach ([1, 2, 3, 4] ; i) {
 writeln(i);
 }
We'd still need a solution for continue and break, though. David
This has already been solved when using opApply, although quite an ugly solution. -- /Jacob Carlborg
Apr 29 2012
parent reply "David Nadlinger" <see klickverbot.at> writes:
On Sunday, 29 April 2012 at 16:10:40 UTC, Jacob Carlborg wrote:
 On 2012-04-29 17:07, David Nadlinger wrote:
 On Sunday, 29 April 2012 at 14:40:38 UTC, Jacob Carlborg wrote:
 foreach ([1, 2, 3, 4] ; i) {
 writeln(i);
 }
We'd still need a solution for continue and break, though. David
This has already been solved when using opApply, although quite an ugly solution.
Yes, but that requires the compiler to generate the return value »glue« code for continue/break inside an opApply foreach. If foreach is a library function and you pass an ordinary delegate, you have a problem in the current language since you can't know that a »return« statement inside that delegate really should return from the outer function. David
Apr 29 2012
parent Jacob Carlborg <doob me.com> writes:
On 2012-04-29 19:03, David Nadlinger wrote:

 Yes, but that requires the compiler to generate the return value »glue«
 code for continue/break inside an opApply foreach. If foreach is a
 library function and you pass an ordinary delegate, you have a problem
 in the current language since you can't know that a »return« statement
 inside that delegate really should return from the outer function.

 David
Yeah, that would need to be solved. In Ruby it works like this: [1, 2, 3, 4].each do |i| if i == 2 return end end Results in: LocalJumpError: unexpected return If you instead wrap it in method you can return from the each-block. So in Ruby it behaves just like having a "return" in a plain for-loop and not in a delegate. It would basically force a return in the "each" method. -- /Jacob Carlborg
Apr 29 2012
prev sibling parent reply "Era Scarecrow" <rtcvb32 yahoo.com> writes:
On Sunday, 29 April 2012 at 15:07:26 UTC, David Nadlinger wrote:
 On Sunday, 29 April 2012 at 14:40:38 UTC, Jacob Carlborg wrote:
 foreach ([1, 2, 3, 4], (i)  { writeln(i); });

 The above already works today. If we can a bit syntax sugar 
 for delegates and inlinable delegates we could have this:

 foreach ([1, 2, 3, 4] ; i) {
    writeln(i);
 }
We'd still need a solution for continue and break, though.
A thought coming to mind regarding this, is a special exception. If the compiler recognizes it's part of a foreach (or other loop) then continue gets converted to return, and and break throws an exception (caught by the foreach of course) But that involves more compiler magic.
Apr 29 2012
parent reply =?UTF-8?B?QWxleCBSw7hubmUgUGV0ZXJzZW4=?= <xtzgzorex gmail.com> writes:
On 30-04-2012 01:54, Era Scarecrow wrote:
 On Sunday, 29 April 2012 at 15:07:26 UTC, David Nadlinger wrote:
 On Sunday, 29 April 2012 at 14:40:38 UTC, Jacob Carlborg wrote:
 foreach ([1, 2, 3, 4], (i) { writeln(i); });

 The above already works today. If we can a bit syntax sugar for
 delegates and inlinable delegates we could have this:

 foreach ([1, 2, 3, 4] ; i) {
 writeln(i);
 }
We'd still need a solution for continue and break, though.
A thought coming to mind regarding this, is a special exception. If the compiler recognizes it's part of a foreach (or other loop) then continue gets converted to return, and and break throws an exception (caught by the foreach of course) But that involves more compiler magic.
And forced EH which is unacceptable in e.g. a kernel. -- - Alex
Apr 29 2012
parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Mon, Apr 30, 2012 at 01:57:58AM +0200, Alex Rønne Petersen wrote:
 On 30-04-2012 01:54, Era Scarecrow wrote:
On Sunday, 29 April 2012 at 15:07:26 UTC, David Nadlinger wrote:
On Sunday, 29 April 2012 at 14:40:38 UTC, Jacob Carlborg wrote:
[...]
We'd still need a solution for continue and break, though.
A thought coming to mind regarding this, is a special exception. If the compiler recognizes it's part of a foreach (or other loop) then continue gets converted to return, and and break throws an exception (caught by the foreach of course) But that involves more compiler magic.
And forced EH which is unacceptable in e.g. a kernel.
[...] Here's a wild idea: introduce the concept of the multi-return function (or, in this case, delegate). Unlike normal functions which returns to a single point when they end, usually by pushing the return address onto the runtime stack, a multi-return function is called by pushing _multiple_ return addresses onto the runtime stack. The function body decides which return address to use (it can only use one of them). Implementing break/continue then can be done like this: the loop body delegate will be a multi-return delegate, i.e., a delegate whose caller will provide multiple return addresses: one for each possible break/continue point. For example: outerLoop: foreach (a; containerA) { innerLoop: foreach (b; containerB) { if (condition1()) continue outerLoop; if (condition2()) break /* innerLoop */; if (condition3()) break outerLoop; } if (condition4()) break /* outerLoop */; } When containerA.opApply is called, it calls the outer loop body with two return addresses: the first is the usual return address from a function call, the second is the cleanup code at the end of opApply that performs any necessary cleanups and then returns. I.e., it simulates break. So when condition4 triggers, the outerLoop delegate returns to the second address. Now the outerLoop delegate itself calls containerB.opApply with a list of outer loop return addresses, i.e., (1) return to containerA.opApply's caller, that is, break outerLoop, (2) return to outerLoop delegate's cleanup code, i.e. continue OuterLoop. Then containerB.opApply prepends two more return addresses to this list, the usual return address to containerB.opApply, and its corresponding break return (prepend because the last return addressed pushed must correspond with the immediate containing scope of the called delegate, but if the delegate knows about outer scopes then it can return to those). Now the innerLoop delegate has four return addresses: return to containerB.opApply normally (continue innerLoop), return to containerB.opApply's cleanup code (break innerLoop), return to containerA.opApply normally (continue outerLoop), and return to containerA.opApply's cleanup code (break outerLoop). So break/continue works for all cases. (Of course, containerB.opApply doesn't actually just prepend return addresses to what the outerLoop delegate passes in, since when the innerLoop delegate wants to break outerLoop, it needs to cleanup the stack frames of the intervening call to containerB.opApply too. So containerB.opApply needs to insert its own cleanup code into the return address chain.) This is, at least, the *conceptual* aspect of things. In the actual implementation, the compiler may use the current scheme (return an int to indicate which return is desired) instead of doing what amounts to reinventing stack unwinding, but the important point is, this should be transparent to user code. As far as the user is concerned, they just call the delegate normally, no need to check return codes, etc., with the understanding that the said delegates have multiple return addresses. The compiler inserts the necessary scaffolding, checking for int returns, etc., to actually implement the concept. T -- WINDOWS = Will Install Needless Data On Whole System -- CompuMan
Apr 29 2012
parent deadalnix <deadalnix gmail.com> writes:
Le 30/04/2012 06:20, H. S. Teoh a écrit :
 On Mon, Apr 30, 2012 at 01:57:58AM +0200, Alex Rønne Petersen wrote:
 On 30-04-2012 01:54, Era Scarecrow wrote:
 On Sunday, 29 April 2012 at 15:07:26 UTC, David Nadlinger wrote:
 On Sunday, 29 April 2012 at 14:40:38 UTC, Jacob Carlborg wrote:
[...]
 We'd still need a solution for continue and break, though.
A thought coming to mind regarding this, is a special exception. If the compiler recognizes it's part of a foreach (or other loop) then continue gets converted to return, and and break throws an exception (caught by the foreach of course) But that involves more compiler magic.
And forced EH which is unacceptable in e.g. a kernel.
[...] Here's a wild idea: introduce the concept of the multi-return function (or, in this case, delegate). Unlike normal functions which returns to a single point when they end, usually by pushing the return address onto the runtime stack, a multi-return function is called by pushing _multiple_ return addresses onto the runtime stack. The function body decides which return address to use (it can only use one of them). Implementing break/continue then can be done like this: the loop body delegate will be a multi-return delegate, i.e., a delegate whose caller will provide multiple return addresses: one for each possible break/continue point. For example: outerLoop: foreach (a; containerA) { innerLoop: foreach (b; containerB) { if (condition1()) continue outerLoop; if (condition2()) break /* innerLoop */; if (condition3()) break outerLoop; } if (condition4()) break /* outerLoop */; } When containerA.opApply is called, it calls the outer loop body with two return addresses: the first is the usual return address from a function call, the second is the cleanup code at the end of opApply that performs any necessary cleanups and then returns. I.e., it simulates break. So when condition4 triggers, the outerLoop delegate returns to the second address. Now the outerLoop delegate itself calls containerB.opApply with a list of outer loop return addresses, i.e., (1) return to containerA.opApply's caller, that is, break outerLoop, (2) return to outerLoop delegate's cleanup code, i.e. continue OuterLoop. Then containerB.opApply prepends two more return addresses to this list, the usual return address to containerB.opApply, and its corresponding break return (prepend because the last return addressed pushed must correspond with the immediate containing scope of the called delegate, but if the delegate knows about outer scopes then it can return to those). Now the innerLoop delegate has four return addresses: return to containerB.opApply normally (continue innerLoop), return to containerB.opApply's cleanup code (break innerLoop), return to containerA.opApply normally (continue outerLoop), and return to containerA.opApply's cleanup code (break outerLoop). So break/continue works for all cases. (Of course, containerB.opApply doesn't actually just prepend return addresses to what the outerLoop delegate passes in, since when the innerLoop delegate wants to break outerLoop, it needs to cleanup the stack frames of the intervening call to containerB.opApply too. So containerB.opApply needs to insert its own cleanup code into the return address chain.) This is, at least, the *conceptual* aspect of things. In the actual implementation, the compiler may use the current scheme (return an int to indicate which return is desired) instead of doing what amounts to reinventing stack unwinding, but the important point is, this should be transparent to user code. As far as the user is concerned, they just call the delegate normally, no need to check return codes, etc., with the understanding that the said delegates have multiple return addresses. The compiler inserts the necessary scaffolding, checking for int returns, etc., to actually implement the concept.
This make sense. This seems to me like the way to go.
Apr 30 2012
prev sibling next sibling parent =?ISO-8859-1?Q?Alex_R=F8nne_Petersen?= <xtzgzorex gmail.com> writes:
On 29-04-2012 16:40, Jacob Carlborg wrote:
 On 2012-04-28 20:47, Walter Bright wrote:
 Andrei and I had a fun discussion last night about this question. The
 idea was which features in D are redundant and/or do not add significant
 value?

 A couple already agreed upon ones are typedef and the cfloat, cdouble
 and creal types.

 What's your list?
* Some of the built-in properties could probably be move to a library solution, specially now when we have UFCS.
+1.
 * The with-statement isn't particular useful. Although I've started to
 use it in one of my projects just so I don't have to use fully qualified
 enum names.
It is very useful in some cases where you operate a lot on the same object.
 * D embedded in HTML (don't know if this is still supported)
Madness... I think it's deprecated now.
 * Multiple syntax for wysiwyg strings. I think the r"" syntax can be
 remove.

 * Do-while loops, how useful are those actually?
I use them occasionally, but it's certainly true that they are rarely useful.
 Then I think some features could be replaced with library solutions if D
 got some other features. For example:

 * foreach(_reverse)
 * synchronized

 These could probably be removed in favor of library solutions.

 void foreach (T)(T[] arr, void delegate (ref T) dg)
 {
 for (size_t i = 0; i < arr.length; i++)
 dg(arr[i]);
 }

 foreach ([1, 2, 3, 4], (i) { writeln(i); });

 The above already works today. If we can a bit syntax sugar for
 delegates and inlinable delegates we could have this:

 foreach ([1, 2, 3, 4] ; i) {
 writeln(i);
 }

 The above syntax would be very useful in other cases as well.

 The same could be done for "synchronized" as well. Might even be
 possible to remove the for-statement and just have "while" left.

 I we want get even more wild and crazy I think Scala's solution for
 operator overloading looks really good. But that would require several
 other features to work. Like:

 * Everything is an object (might not be needed with UFCS)
 * Everything is a method call on an object
 * Infix notation for calling any method taking one argument
 * Basically any symbol is allowed in method names

 That is:

 1 + 2
 foo bar foo_bar

 Would be translated to:

 1.+(2)
 foo.bar(foo_bar)

 That is a very general way to handle operators and let the user create
 new operators, not just overloading existing ones.
-- - Alex
Apr 29 2012
prev sibling parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Sun, Apr 29, 2012 at 04:40:37PM +0200, Jacob Carlborg wrote:
[...]
 * Do-while loops, how useful are those actually?
OK, that got me all riled up about looping constructs, and now I'm provoked to rant: Since the advent of structured programming, looping constructs have always been somewhat b0rken. Yes they worked very well, they are clean, powerful, gets rid of almost all cases of needing goto's, etc.. But the point of a loop is that *the entry point does not always correspond with the exit point (where the loop condition is tested)*. The problem with both do-loops and while-loops is that they are just straitjacketed versions of a more general looping construct. At its most fundamental level, a loop consists of an entry point, a loop body, and some point within the loop body where the loop exits. Sometimes you need multiple exits, but most cases only need a single exit point. So a loop (unrolled) might look like this: codeBeforeLoop(); // Loop body begins here doSomething(); if (!loopCondition) goto exitLoop; doSomethingElse(); doSomething(); if (!loopCondition) goto exitLoop; doSomethingElse(); ... exitLoop: codeAfterLoop(); Note that I deliberately split the loop body into two parts, before the loop condition and after the loop condition. This is because you often have code like this: auto line = nextLine(); while (!eof()) { processLine(line); line = nextLine(); } Notice the duplicated nextLine() call. That's stupid, the initial call to nextLine() is actually already the beginning of the loop. Why do you need to repeat it again inside the loop? Because while-loops always tests the loop condition at the beginning of the loop. OK, what about using a do-loop instead? do { auto line = nextLine(); if (!eof()) processLine(line); } while (!eof()); OK, we got rid of the duplicated nextLine() call, but now we introduced a duplicated eof() test. This is also stupid. The only reason it has to be written in this stupid way is because do-loops always test the loop condition at the end of the loop body, but you need to evaluate the condition BEFORE the second half of the loop body (processLine) is run. But once you've evaluated that condition, the test at the end of the loop body is redundant. So you might say, OK, just write this then: for(;;) { auto line = nextLine(); if (eof()) break; processLine(line); } Well, finally you have something sane. The loop condition now correctly appears in the middle of the loop body, which is where it should've been all along. Only problem is, writing for(;;) is misleading, because you're not looping indefinitely, there's precisely one exit condition. Conveying intent is very important in writing good code, and this code breaks that principle. So really, what is needed is a sane looping construct that unifies while loops, do-loops, and exit-in-the-middle loops. Something like this: loop { // first part of loop body } exitWhen(!loopCondition) { // second part of loop body } It doesn't have to be this exact syntax, but the point is that you need to be able to express loop exits from the middle of a loop body without needing to resort to for(;;) and break, when the loop is a good ole simple loop with a single entry point and a single exit point. (More complex loops that need continue's and break's are, well, more complex, so it's OK to sprinkle if conditions in them like we do now.) </rant> [...]
 * Infix notation for calling any method taking one argument
 * Basically any symbol is allowed in method names
 
 That is:
 
 1 + 2
 foo bar foo_bar
 
 Would be translated to:
 
 1.+(2)
 foo.bar(foo_bar)
 
 That is a very general way to handle operators and let the user
 create new operators, not just overloading existing ones.
[...] While personally, I like the idea of being able to create new infix operators, it will cause too big a change to D syntax, and probably cause lots of breakages with existing code, as well as make the lexer/parser much harder to implement (given the existing D features). You also then have to deal with operator precedence between arbitrary user-defined operators, which is non-trivial in general (though it's workable if you impose some constrains -- but it's probably way beyond the scope of D2 or even D3). T -- Trying to define yourself is like trying to bite your own teeth. -- Alan Watts
Apr 29 2012
next sibling parent reply Don Clugston <dac nospam.com> writes:
On 30/04/12 05:45, H. S. Teoh wrote:
 On Sun, Apr 29, 2012 at 04:40:37PM +0200, Jacob Carlborg wrote:
 [...]
 * Do-while loops, how useful are those actually?
I grepped through the DMD source once, looking for how often Walter uses do..while. The answer: exactly zero.
 OK, that got me all riled up about looping constructs, and now I'm
 provoked to rant:

 Since the advent of structured programming, looping constructs have
 always been somewhat b0rken. Yes they worked very well, they are clean,
 powerful, gets rid of almost all cases of needing goto's, etc.. But the
 point of a loop is that *the entry point does not always correspond with
 the exit point (where the loop condition is tested)*. The problem with
 both do-loops and while-loops is that they are just straitjacketed
 versions of a more general looping construct.
Completely agree. Forth is one of the few languages which got it right. BEGIN .... cond WHILE ... REPEAT
Apr 30 2012
parent "bearophile" <bearophileHUGS lycos.com> writes:
Don Clugston:

 * Do-while loops, how useful are those actually?
I grepped through the DMD source once, looking for how often Walter uses do..while. The answer: exactly zero.
In my code I use one do-while about every 20 or 30 loops, so they aren't very common, but are useful. If I need a random 2D point on a disk, one method to produce it is by rejection, I use a do-while loop, I extract two coordinates in a square, and then test if they are inside the disk, otherwise I loop. But I have a problem with D-style do-while loops, that some time ago I have discussed a bit in D.learn: I can't use them like this, because the variables defined inside the loop are not visible in the loop test: do { // ... const x = compute something } while (predicate(x)); I have to use this, that is less handy: T x; do { // ... x = compute something } while (predicate(x)); Bye, bearophile
Apr 30 2012
prev sibling next sibling parent Dmitry Olshansky <dmitry.olsh gmail.com> writes:
On 30.04.2012 7:45, H. S. Teoh wrote:
 On Sun, Apr 29, 2012 at 04:40:37PM +0200, Jacob Carlborg wrote:
[snip]
 So you might say, OK, just write this then:

 	for(;;) {
 		auto line = nextLine();
 		if (eof())
 			break;
 		processLine(line);
 	}

 Well, finally you have something sane. The loop condition now correctly
 appears in the middle of the loop body, which is where it should've been
 all along. Only problem is, writing for(;;) is misleading, because
 you're not looping indefinitely, there's precisely one exit condition.
 Conveying intent is very important in writing good code, and this code
 breaks that principle.

 So really, what is needed is a sane looping construct that unifies while
 loops, do-loops, and exit-in-the-middle loops. Something like this:

 	loop {
 		// first part of loop body
 	} exitWhen(!loopCondition) {
 		// second part of loop body
 	}
You'd love PL/SQL. :) -- Dmitry Olshansky
Apr 30 2012
prev sibling next sibling parent Jacob Carlborg <doob me.com> writes:
On 2012-04-30 05:45, H. S. Teoh wrote:

 While personally, I like the idea of being able to create new infix
 operators, it will cause too big a change to D syntax, and probably
 cause lots of breakages with existing code, as well as make the
 lexer/parser much harder to implement (given the existing D features).

 You also then have to deal with operator precedence between arbitrary
 user-defined operators, which is non-trivial in general (though it's
 workable if you impose some constrains -- but it's probably way beyond
 the scope of D2 or even D3).
Yes, a language would basically need to be designed with this in mind from the start. That's what I'm thing sometimes, D could have gone down some other road in some cases but it's way too late to change it now. -- /Jacob Carlborg
Apr 30 2012
prev sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 04/30/2012 05:45 AM, H. S. Teoh wrote:
 On Sun, Apr 29, 2012 at 04:40:37PM +0200, Jacob Carlborg wrote:
 [...]

 So really, what is needed is a sane looping construct that unifies while
 loops, do-loops, and exit-in-the-middle loops. Something like this:

 	loop {
 		// first part of loop body
 	} exitWhen(!loopCondition) {
 		// second part of loop body
 	}

 It doesn't have to be this exact syntax, but the point is that you need
 to be able to express loop exits from the middle of a loop body without
 needing to resort to for(;;) and break, when the loop is a good ole
 simple loop with a single entry point and a single exit point. (More
 complex loops that need continue's and break's are, well, more complex,
 so it's OK to sprinkle if conditions in them like we do now.)

 </rant>
do{ // ... }while(cond){ // ... } I think the scoping rules of the do-while loop should be fixed such that the loop condition can refer to loop-local variables. Violates C backwards compatibility though...
 [...]
 * Infix notation for calling any method taking one argument
 * Basically any symbol is allowed in method names

 That is:

 1 + 2
 foo bar foo_bar

 Would be translated to:

 1.+(2)
 foo.bar(foo_bar)

 That is a very general way to handle operators and let the user
 create new operators, not just overloading existing ones.
[...] While personally, I like the idea of being able to create new infix operators, it will cause too big a change to D syntax, and probably cause lots of breakages with existing code, as well as make the lexer/parser much harder to implement (given the existing D features).
Should be trivial. (The parser can just defer operator precedence resolution to the analysis phase if necessary, and otherwise it is very simple anyway.)
 You also then have to deal with operator precedence between arbitrary
 user-defined operators, which is non-trivial in general (though it's
 workable if you impose some constrains
I kinda like the Scala-approach.
 -- but it's probably way beyond the scope of D2 or even D3).
An issue is that it clashes with eg. a+***ptrtoptrtoptrtodata.
Apr 30 2012
prev sibling next sibling parent reply Don <nospam nospam.com> writes:
On 28.04.2012 20:47, Walter Bright wrote:
 Andrei and I had a fun discussion last night about this question. The
 idea was which features in D are redundant and/or do not add significant
 value?

 A couple already agreed upon ones are typedef and the cfloat, cdouble
 and creal types.

 What's your list?
* The >>> operator, which does nothing except introduce bugs (It does NOT perform an unsigned shift). * package. I have no idea how a failed Java experiment got incorporated into D. * the zoo of parameter passing options * Most of the __traits are useless and redundant.
Apr 29 2012
next sibling parent reply "David Nadlinger" <see klickverbot.at> writes:
On Sunday, 29 April 2012 at 15:50:54 UTC, Don wrote:
 * package. I have no idea how a failed Java experiment got 
 incorporated into D.
+1, forgot to mention that one. David
Apr 29 2012
parent reply "SomeDude" <lovelydear mailmetrash.com> writes:
On Sunday, 29 April 2012 at 17:05:19 UTC, David Nadlinger wrote:
 On Sunday, 29 April 2012 at 15:50:54 UTC, Don wrote:
 * package. I have no idea how a failed Java experiment got 
 incorporated into D.
+1, forgot to mention that one. David
What's wrong with packages ?
Apr 29 2012
parent reply "David Nadlinger" <see klickverbot.at> writes:
On Sunday, 29 April 2012 at 18:39:49 UTC, SomeDude wrote:
 What's wrong with packages ?
Nothing – this is about the »package« protection level, not packages. ;) David
Apr 29 2012
parent reply "SomeDude" <lovelydear mailmetrash.com> writes:
On Sunday, 29 April 2012 at 18:47:11 UTC, David Nadlinger wrote:
 On Sunday, 29 April 2012 at 18:39:49 UTC, SomeDude wrote:
 What's wrong with packages ?
Nothing – this is about the »package« protection level, not packages. ;) David
Ah ok. But I'm not sure what's wrong with the package protection level either, actually.
Apr 29 2012
parent reply =?UTF-8?B?QWxleCBSw7hubmUgUGV0ZXJzZW4=?= <xtzgzorex gmail.com> writes:
On 29-04-2012 22:24, SomeDude wrote:
 On Sunday, 29 April 2012 at 18:47:11 UTC, David Nadlinger wrote:
 On Sunday, 29 April 2012 at 18:39:49 UTC, SomeDude wrote:
 What's wrong with packages ?
Nothing – this is about the »package« protection level, not packages. ;) David
Ah ok. But I'm not sure what's wrong with the package protection level either, actually.
Yes, me neither. And I have found many cases in my code where using it actually makes sense and helps encapsulation. -- - Alex
Apr 29 2012
parent "David Nadlinger" <see klickverbot.at> writes:
On Sunday, 29 April 2012 at 21:06:10 UTC, Alex Rønne Petersen 
wrote:
 On 29-04-2012 22:24, SomeDude wrote:
 Ah ok. But I'm not sure what's wrong with the package 
 protection level
 either, actually.
Yes, me neither. And I have found many cases in my code where using it actually makes sense and helps encapsulation.
See the Java discussion on »superpackages« – quite often, you want to share stuff in mylibrary.subpackage with the rest of mylibrary, but not the world. David
Apr 29 2012
prev sibling next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
Don:

 * package. I have no idea how a failed Java experiment got 
 incorporated into D.
Weren't Java designers thinking about adding superpackages too to Java?
 * the zoo of parameter passing options
Please explain, what do you mean? Bye, bearophile
Apr 29 2012
prev sibling next sibling parent reply Manu <turkeyman gmail.com> writes:
On 29 April 2012 18:50, Don <nospam nospam.com> wrote:

 On 28.04.2012 20:47, Walter Bright wrote:

 Andrei and I had a fun discussion last night about this question. The
 idea was which features in D are redundant and/or do not add significant
 value?

 A couple already agreed upon ones are typedef and the cfloat, cdouble
 and creal types.

 What's your list?
* The >>> operator, which does nothing except introduce bugs (It does NOT perform an unsigned shift).
What does it do? I use this all over the place, I assumed it worked... maybe I have bugs?
 * package. I have no idea how a failed Java experiment got incorporated
 into D.
package confuses me, it's poorly documented. What are the protections between packages, sub-packages. Can parent packages see sub-package contents? vice-versa? * Most of the __traits are useless and redundant.

Which traits are useless and redundant? I'm actually finding the set is
incomplete, and there are some missing (parameter list introspection,
current scope/object identification, current module/package)
Apr 29 2012
next sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 04/29/2012 08:08 PM, Manu wrote:
 On 29 April 2012 18:50, Don <nospam nospam.com
 <mailto:nospam nospam.com>> wrote:

     On 28.04.2012 20:47, Walter Bright wrote:

         Andrei and I had a fun discussion last night about this
         question. The
         idea was which features in D are redundant and/or do not add
         significant
         value?

         A couple already agreed upon ones are typedef and the cfloat,
         cdouble
         and creal types.

         What's your list?


     * The >>> operator, which does nothing except introduce bugs (It
     does NOT perform an unsigned shift).


 What does it do? I use this all over the place, I assumed it worked...
 maybe I have bugs?
It does work, but it behaves in unexpected ways for narrow signed integers (short/byte) because it sign-extends them before shifting. It works fine with int/uint/long/ulong.
     * Most of the __traits are useless and redundant.


 Which traits are useless and redundant? I'm actually finding the set is
 incomplete, and there are some missing (parameter list introspection,
 current scope/object identification, current module/package)
+1.
Apr 29 2012
prev sibling next sibling parent Paulo Pinto <pjmlp progtools.org> writes:
Am 29.04.2012 20:08, schrieb Manu:
 On 29 April 2012 18:50, Don <nospam nospam.com
 [...]
     * package. I have no idea how a failed Java experiment got
     incorporated into D.


 package confuses me, it's poorly documented. What are the protections
 between packages, sub-packages. Can parent packages see sub-package
 contents? vice-versa?
I've always assume that package is similar to what is available in another module based languages. Where you have a library (package) that is composed of several separated modules. In certain scenarios, you want to have symbols that are private to the library, but need to be marked public so that each module, that is part of the library, is able to see them. So you mark those symbols as package level access. This is usually done in "programming in the large" projects. Some examples where I think this concept might be visible, - .NET Modules (internal is used for visibility accross .dll) - default package access for Java common namespaces scattered across several jar files - Ada limited and child packages - Delphi packages -- Paulo
Apr 29 2012
prev sibling next sibling parent Robert Clipsham <robert octarineparrot.com> writes:
On 29/04/2012 19:08, Manu wrote:
 current module/package
http://dlang.org/phobos/std_traits#packageName http://dlang.org/phobos/std_traits#moduleName -- Robert http://octarineparrot.com/
Apr 29 2012
prev sibling next sibling parent Jacob Carlborg <doob me.com> writes:
On 2012-04-29 20:08, Manu wrote:

 package confuses me, it's poorly documented. What are the protections
 between packages, sub-packages. Can parent packages see sub-package
 contents? vice-versa?
As far as I know it works like this: pack |- pack1 |- foo.d |- bar.d |- pack2 |- a.d |- pack3 |- b.d |- c.d // pack.pack1.foo package int x = 3; // pack.pack1.bar x = 4; // this is fine since it's in the same package. // pack.pack1.pack2.a x = 5; // error, cannot access package protected variable. // pack.pack3.b x = 6; // error, cannot access package protected variable. // pack.c x = 7; // error, cannot access package protected variable. Oh, and "package" is non-virtual, for some reason. -- /Jacob Carlborg
Apr 29 2012
prev sibling parent reply Don Clugston <dac nospam.com> writes:
On 29/04/12 20:08, Manu wrote:
 On 29 April 2012 18:50, Don <nospam nospam.com
 <mailto:nospam nospam.com>> wrote:

     On 28.04.2012 20:47, Walter Bright wrote:

         Andrei and I had a fun discussion last night about this
         question. The
         idea was which features in D are redundant and/or do not add
         significant
         value?

         A couple already agreed upon ones are typedef and the cfloat,
         cdouble
         and creal types.

         What's your list?


     * The >>> operator, which does nothing except introduce bugs (It
     does NOT perform an unsigned shift).


 What does it do? I use this all over the place, I assumed it worked...
 maybe I have bugs?
It works only for two types: int and long. For everything else, it is identical to >> So for short and byte, and in generic code, it's ALWAYS a bug.
Apr 30 2012
parent reply Manu <turkeyman gmail.com> writes:
On 30 April 2012 10:32, Don Clugston <dac nospam.com> wrote:

 On 29/04/12 20:08, Manu wrote:

 On 29 April 2012 18:50, Don <nospam nospam.com
 <mailto:nospam nospam.com>> wrote:


    On 28.04.2012 20:47, Walter Bright wrote:

        Andrei and I had a fun discussion last night about this
        question. The
        idea was which features in D are redundant and/or do not add
        significant
        value?

        A couple already agreed upon ones are typedef and the cfloat,
        cdouble
        and creal types.

        What's your list?


    * The >>> operator, which does nothing except introduce bugs (It
    does NOT perform an unsigned shift).


 What does it do? I use this all over the place, I assumed it worked...
 maybe I have bugs?
It works only for two types: int and long. For everything else, it is identical to >> So for short and byte, and in generic code, it's ALWAYS a bug.
O_O Is that intentional? Or is it... a bug? I smiled when I saw >>> in the language, I appreciate its presence. It's not necessary, but it cuts down on some ugly explicit casting (which theoretically makes generic code simpler).
Apr 30 2012
parent reply Don Clugston <dac nospam.com> writes:
On 30/04/12 12:27, Manu wrote:
 On 30 April 2012 10:32, Don Clugston <dac nospam.com
 <mailto:dac nospam.com>> wrote:

     On 29/04/12 20:08, Manu wrote:

         On 29 April 2012 18:50, Don <nospam nospam.com
         <mailto:nospam nospam.com>
         <mailto:nospam nospam.com <mailto:nospam nospam.com>>> wrote:


             On 28.04.2012 20:47, Walter Bright wrote:

                 Andrei and I had a fun discussion last night about this
                 question. The
                 idea was which features in D are redundant and/or do not add
                 significant
                 value?

                 A couple already agreed upon ones are typedef and the
         cfloat,
                 cdouble
                 and creal types.

                 What's your list?


             * The >>> operator, which does nothing except introduce bugs (It
             does NOT perform an unsigned shift).


         What does it do? I use this all over the place, I assumed it
         worked...
         maybe I have bugs?


     It works only for two types: int and long.
     For everything else, it is identical to >>
     So for short and byte, and in generic code, it's ALWAYS a bug.


 O_O
 Is that intentional? Or is it... a bug?
 I smiled when I saw >>> in the language, I appreciate its presence. It's
 not necessary, but it cuts down on some ugly explicit casting (which
 theoretically makes generic code simpler).
It's not a bug, it's a design flaw. The buggy behaviour is explicitly tested in the test suite. The problem is that the C promotion rules also apply, just as for >> and <<. But they are fundamentally incompatible with unsigned shift. So short and byte get promoted to int *by sign extension*, then the int gets an unsigned shift. Which means that the short or byte gets a signed shift instead of an unsigned one. I used to use >>> in my code, because as you say, it is a nice idea, but after having a few bugs with short, and working out what the semantics actually were, I suddenly realized it was a landmine, and I removed every instance of it from my code. (cast(ulong)x) >> 3 is safer than x >>> 3, unfortunately.
Apr 30 2012
next sibling parent ponce <spam spam.org> writes:
Le 30/04/2012 14:44, Don Clugston a écrit :
 It's not a bug, it's a design flaw. The buggy behaviour is explicitly
 tested in the test suite.
 The problem is that the C promotion rules also apply, just as for >> and
 <<. But they are fundamentally incompatible with unsigned shift.
 So short and byte get promoted to int *by sign extension*,
 then the int gets an unsigned shift.
 Which means that the short or byte gets a signed shift instead of an
 unsigned one.
Thanks for pointing that out. Sadly, it makes some sense with the C integer promotion rules.
May 01 2012
prev sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 04/30/2012 02:44 PM, Don Clugston wrote:
 (cast(ulong)x) >> 3 is safer than x >>> 3, unfortunately.
In what way is it safer? void main() { short x = -1; assert((cast(ulong)x) >> 3 == cast(long)x >>> 3); }
May 01 2012
prev sibling parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On Sunday, April 29, 2012 17:50:48 Don wrote:
 * package. I have no idea how a failed Java experiment got incorporated
 into D.
Really? In some cases, it's indispensable. For instance, once std.datetime has been split up, it will require it, or it would have duplicate a bunch of implementation-specific stuff which has no business in the public API. - Jonathan M Davis
Apr 29 2012
next sibling parent reply "Kapps" <opantm2+spam gmail.com> writes:
On Monday, 30 April 2012 at 01:08:28 UTC, Jonathan M Davis wrote:
 On Sunday, April 29, 2012 17:50:48 Don wrote:
 * package. I have no idea how a failed Java experiment got 
 incorporated
 into D.
Really? In some cases, it's indispensable. For instance, once std.datetime has been split up, it will require it, or it would have duplicate a bunch of implementation-specific stuff which has no business in the public API. - Jonathan M Davis
It's entirely dependent on your coding style. For example, when you look at Phobos you rarely (if ever?) see package functions. This is because it's entirely module based with a strong degree of separation between modules. awful. I personally use package quite often. For the most part, I stick to one major class per file, and separate things across library. There are plenty of things that I want other classes in the package/static-library to use, but don't want to expose to the public, and thus use package for.
Apr 29 2012
next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Monday, April 30, 2012 05:12:27 Kapps wrote:
 On Monday, 30 April 2012 at 01:08:28 UTC, Jonathan M Davis wrote:
 On Sunday, April 29, 2012 17:50:48 Don wrote:
 * package. I have no idea how a failed Java experiment got
 incorporated
 into D.
Really? In some cases, it's indispensable. For instance, once std.datetime has been split up, it will require it, or it would have duplicate a bunch of implementation-specific stuff which has no business in the public API. - Jonathan M Davis
It's entirely dependent on your coding style. For example, when you look at Phobos you rarely (if ever?) see package functions. This is because it's entirely module based with a strong degree of separation between modules. awful. I personally use package quite often. For the most part, I stick to one major class per file, and separate things across library. There are plenty of things that I want other classes in the package/static-library to use, but don't want to expose to the public, and thus use package for.
It's a question of how inter-dependent your modules are (which is partly a question of style). If you have a bunch of closely related functionality that should be in separate modules, then it can be quite easy for it to need have stuff which it needs to share but shouldn't be public. This happens much more easily if you follow a style of putting one class per module as you _must_ do Phobos doesn't have all that many types in it (though that's changing as it grows). Historically, it's been (and mostly still is) a collection of free functions which have been organized in modules with related functions sharing modules. However, free functions tend to be quite independent. At most, they may share some private helpers. They rarely need to share stuff across modules. On top of that, Phobos has historically avoided creating sub-modules in favor of a flat hierarchy (though that's starting to change) The result of this is that package hasn't been needed in Phobos. I suspect that Don's take on things comes from that (and he probably hasn't needed package in his own stuff either). But I don't think that it's very hard at all to come up with examples where package level access can be invaluable. - Jonathan M Davis
Apr 29 2012
prev sibling parent reply deadalnix <deadalnix gmail.com> writes:
Le 30/04/2012 05:12, Kapps a écrit :
 On Monday, 30 April 2012 at 01:08:28 UTC, Jonathan M Davis wrote:
 On Sunday, April 29, 2012 17:50:48 Don wrote:
 * package. I have no idea how a failed Java experiment got incorporated
 into D.
Really? In some cases, it's indispensable. For instance, once std.datetime has been split up, it will require it, or it would have duplicate a bunch of implementation-specific stuff which has no business in the public API. - Jonathan M Davis
It's entirely dependent on your coding style. For example, when you look at Phobos you rarely (if ever?) see package functions. This is because it's entirely module based with a strong degree of separation between modules. personally use package quite often. For the most part, I stick to one major class per file, and separate things across library. There are plenty of things that I want other classes in the package/static-library to use, but don't want to expose to the public, and thus use package for.
Phobos is a really good example. Modules tend to become more and more fat. And to split them up, package is mandatory.
Apr 30 2012
parent "David Nadlinger" <see klickverbot.at> writes:
On Monday, 30 April 2012 at 12:35:24 UTC, deadalnix wrote:
 Phobos is a really good example. Modules tend to become more 
 and more fat. And to split them up, package is mandatory.
Except that it doesn't work if the module you want to refactor into a sub-package already used »package«… David
Apr 30 2012
prev sibling parent reply "David Nadlinger" <see klickverbot.at> writes:
On Monday, 30 April 2012 at 01:08:28 UTC, Jonathan M Davis wrote:
 On Sunday, April 29, 2012 17:50:48 Don wrote:
 * package. I have no idea how a failed Java experiment got 
 incorporated
 into D.
Really? In some cases, it's indispensable. For instance, once std.datetime has been split up, it will require it, or it would have duplicate a bunch of implementation-specific stuff which has no business in the public API.
But what happens if std.datetime grows so large that you want to have e.g. a std.datetime.system package, the content of which is accessible from std.datetime.*, but not the rest of the world? This is not an artificial problem, e.g. consider Thrift, where I have e.g. thrift.internal.endian (predating endian stuff in Phobos) which is used from modules in thrift.async, thrift.server, and thrift.protocol, or thrift.internal.socket (containing some more OS abstractions than std.socket does), which is used from modules in thrift.async, thrift.server, and thrift.transport, but both are not part of the public API. The logical »package« to restrict access to would be »thrift.*« here, but there is no way to restrict access to that, I have to resort to hoping users understand that they should not use »thrift.internal.xyz« directly. Phobos has the same problem with std.internal. I think in Java this problem was the reason for »super packages« to be discussed which (I think, haven't followed it the developments closely) ended up being incorporated in the upcoming Module System feature. David
Apr 29 2012
parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On Monday, April 30, 2012 06:58:18 David Nadlinger wrote:
 On Monday, 30 April 2012 at 01:08:28 UTC, Jonathan M Davis wrote:
 On Sunday, April 29, 2012 17:50:48 Don wrote:
 * package. I have no idea how a failed Java experiment got
 incorporated
 into D.
=20 Really? In some cases, it's indispensable. For instance, once std.datetime has been split up, it will require it, or it would have duplicate a bunch of implementation-specific stuff which has no business in the public API.
=20 But what happens if std.datetime grows so large that you want to have e.g. a std.datetime.system package, the content of which is accessible from std.datetime.*, but not the rest of the world? =20 This is not an artificial problem, e.g. consider Thrift, where I have e.g. thrift.internal.endian (predating endian stuff in Phobos) which is used from modules in thrift.async, thrift.server, and thrift.protocol, or thrift.internal.socket (containing some more OS abstractions than std.socket does), which is used from modules in thrift.async, thrift.server, and thrift.transport, but both are not part of the public API. =20 The logical =C2=BBpackage=C2=AB to restrict access to would be =C2=BBthrift.*=C2=AB here, but there is no way to restrict access to that, I have to resort to hoping users understand that they should not use =C2=BBthrift.internal.xyz=C2=AB directly. Phobos has t=
he
 same problem with std.internal.
=20
 I think in Java this problem was the reason for =C2=BBsuper
 packages=C2=AB to be discussed which (I think, haven't followed it
 the developments closely) ended up being incorporated in the
 upcoming Module System feature.
I'm not claiming that package solves all such issues (and you do give s= ome=20 good examples where it would be a problem), but not having it would mak= e the=20 problem even worse. I think that this is one area though where the Wind= ows=20 folks take advantage of their export nonsense and just don't export the= =20 internal stuff. - Jonathan M Davis
Apr 29 2012
parent "Paulo Pinto" <pjmlp progtools.org> writes:
I don't see export as nonsense. :)

"Jonathan M Davis"  wrote in message 
news:mailman.137.1335762449.24740.digitalmars-d puremagic.com...

On Monday, April 30, 2012 06:58:18 David Nadlinger wrote:
 On Monday, 30 April 2012 at 01:08:28 UTC, Jonathan M Davis wrote:
 On Sunday, April 29, 2012 17:50:48 Don wrote:
 * package. I have no idea how a failed Java experiment got
 incorporated
 into D.
Really? In some cases, it's indispensable. For instance, once std.datetime has been split up, it will require it, or it would have duplicate a bunch of implementation-specific stuff which has no business in the public API.
But what happens if std.datetime grows so large that you want to have e.g. a std.datetime.system package, the content of which is accessible from std.datetime.*, but not the rest of the world? This is not an artificial problem, e.g. consider Thrift, where I have e.g. thrift.internal.endian (predating endian stuff in Phobos) which is used from modules in thrift.async, thrift.server, and thrift.protocol, or thrift.internal.socket (containing some more OS abstractions than std.socket does), which is used from modules in thrift.async, thrift.server, and thrift.transport, but both are not part of the public API. The logical »package« to restrict access to would be »thrift.*« here, but there is no way to restrict access to that, I have to resort to hoping users understand that they should not use »thrift.internal.xyz« directly. Phobos has the same problem with std.internal. I think in Java this problem was the reason for »super packages« to be discussed which (I think, haven't followed it the developments closely) ended up being incorporated in the upcoming Module System feature.
I'm not claiming that package solves all such issues (and you do give some good examples where it would be a problem), but not having it would make the problem even worse. I think that this is one area though where the Windows folks take advantage of their export nonsense and just don't export the internal stuff. - Jonathan M Davis
Apr 30 2012
prev sibling next sibling parent reply "bearophile" <bearophileHUGS lycos.com> writes:
Walter:

 What's your list?
This thread now has something like 240 answers (and probably few more will come), and despite some variability in the answers, we have seen several recurring patterns too. So what are the conclusions, take-home insights, and the to-do's to make something in practice, from Walter & Andrei? Bye, bearophile
Apr 29 2012
next sibling parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On Monday, April 30, 2012 01:41:45 bearophile wrote:
 Walter:
 What's your list?
This thread now has something like 240 answers (and probably few more will come), and despite some variability in the answers, we have seen several recurring patterns too. So what are the conclusions, take-home insights, and the to-do's to make something in practice, from Walter & Andrei?
Honestly, I don't think that you _can_ take much from this thread other than the fact that pretty _every_ feature is wanted and used by someone, even if other people hate it. Pretty much every feature listed as undesirable by someone was listed as desirable by someone else. As for TODOs, the impression that I got from Walter's post was that he wanted to know what people thought out of curiosity or just for "lessons learned" from the design process of D and not that he was really looking to remove anything from the language. So, I don't think that it was ever his intention to create a TODO list from this (though I could be wrong). There may be some minor things that get changed (such as making it so that adjacent string literals don't get automatically concatenated), but I don't think that D is really going to have any of its features removed at this point. - Jonathan M Davis
Apr 29 2012
next sibling parent reply Dmitry Olshansky <dmitry.olsh gmail.com> writes:
On 30.04.2012 10:55, Jonathan M Davis wrote:
 On Monday, April 30, 2012 01:41:45 bearophile wrote:
 Walter:
 What's your list?
This thread now has something like 240 answers (and probably few more will come), and despite some variability in the answers, we have seen several recurring patterns too. So what are the conclusions, take-home insights, and the to-do's to make something in practice, from Walter& Andrei?
Honestly, I don't think that you _can_ take much from this thread other than the fact that pretty _every_ feature is wanted and used by someone, even if other people hate it. Pretty much every feature listed as undesirable by someone was listed as desirable by someone else.
foreach_reverse, comma operator, etc.
 As for TODOs, the impression that I got from Walter's post was that he wanted
 to know what people thought out of curiosity or just for "lessons learned"
 from the design process of D and not that he was really looking to remove
 anything from the language. So, I don't think that it was ever his intention
 to create a TODO list from this (though I could be wrong). There may be some
 minor things that get changed (such as making it so that adjacent string
 literals don't get automatically concatenated), but I don't think that D is
 really going to have any of its features removed at this point.

 - Jonathan M Davis
-- Dmitry Olshansky
Apr 30 2012
parent "SomeDude" <lovelydear mailmetrash.com> writes:
On Monday, 30 April 2012 at 07:52:10 UTC, Dmitry Olshansky wrote:
 On 30.04.2012 10:55, Jonathan M Davis wrote:
 On Monday, April 30, 2012 01:41:45 bearophile wrote:
 Walter:
 What's your list?
This thread now has something like 240 answers (and probably few more will come), and despite some variability in the answers, we have seen several recurring patterns too. So what are the conclusions, take-home insights, and the to-do's to make something in practice, from Walter& Andrei?
Honestly, I don't think that you _can_ take much from this thread other than the fact that pretty _every_ feature is wanted and used by someone, even if other people hate it. Pretty much every feature listed as undesirable by someone was listed as desirable by someone else.
foreach_reverse, comma operator, etc.
These are the only two I can count that nobody felt eager to keep. Yet these are only nitpicks. Also, both work, so the benefit of removing them vs breaking code... I would be glad to remove the current comma operator if its semantic was changed for something like this: http://forum.dlang.org/post/ajdmseliewbindkkoxxj forum.dlang.org But I don't think it's on the table. So I believe the conclusion several of us have reached is, that it's more important to make things that already exist work as intended without ugly corner cases and hacks.
Apr 30 2012
prev sibling parent reply "bearophile" <bearophileHUGS lycos.com> writes:
Jonathan M Davis:

 Honestly, I don't think that you _can_ take much from this 
 thread other than
I don't agree, I see some recurring patterns. People have spent energy and time to write lot of answers in this thread, some good answer bits too, so I expect such work to not let be fully wasted. Asking for opinions, receiving lot of them, and then ignoring them all is not a good way to run a community. And thank you for your answer, I always appreciate your answers, but you aren't Walter, that post was for him (and Andrei) to answer :-) Bye, bearophile
Apr 30 2012
next sibling parent reply "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Monday, April 30, 2012 11:15:17 bearophile wrote:
 Jonathan M Davis:
 Honestly, I don't think that you _can_ take much from this
 thread other than
I don't agree, I see some recurring patterns. People have spent energy and time to write lot of answers in this thread, some good answer bits too, so I expect such work to not let be fully wasted. Asking for opinions, receiving lot of them, and then ignoring them all is not a good way to run a community. And thank you for your answer, I always appreciate your answers, but you aren't Walter, that post was for him (and Andrei) to answer :-)
I never claimed that I _was_ Walter. I was pointing out that there's very little consensus in this thread (almost all of the comments are in conflict with other comments) so that even if it was our intention to go and remove things from the language based on this thread, there is very little, if anything, that has a clear consensus on being removed. The closest would probably be the comma operator, and there wasn't even a complete consensus on _that_. And while I obviously can't say for certain what Walter intended, it was my impression that the point of this thread was more out of curiosity and for "lessons learned" from designing D than to actually make any changes to the language right now (especially when you consider how much Walter hates breaking backwards compatibility). But obviously, he'd have to clarify for us to know for sure. - Jonathan M Davis
Apr 30 2012
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 4/30/2012 10:04 AM, Jonathan M Davis wrote:
 I never claimed that I _was_ Walter. I was pointing out that there's very
 little consensus in this thread (almost all of the comments are in conflict
 with other comments) so that even if it was our intention to go and remove
 things from the language based on this thread, there is very little, if
 anything, that has a clear consensus on being removed. The closest would
 probably be the comma operator, and there wasn't even a complete consensus on
 _that_.
There is less agreement than I thought there would be. This thread also generated far more interest than I anticipated.
 And while I obviously can't say for certain what Walter intended, it was my
 impression that the point of this thread was more out of curiosity and for
 "lessons learned" from designing D than to actually make any changes to the
 language right now (especially when you consider how much Walter hates
 breaking backwards compatibility). But obviously, he'd have to clarify for us
 to know for sure.
The first thing to emphasize is that NONE of this will happen for D2. The emphasis on D2 is fixing implementation and toolchain issues. Breaking existing code is off the table unless we are pretty much forced to in order to fix some other more important issue. So we're talking several years out. The evolution of C++ is interesting. So far, the C++ committee has shown incredible resistance to removing, or even deprecating, some features that pretty much everyone knows were a mistake, all in the interests of maintaining backwards compatibility. Some of C++'s success can be attributed to that, but also some of its endemic failures. Where's the line to draw between breaking existing code and modernizing / removing cruft / removing support for features that promote bad code? Of course, there can't be any fixed rule for that. Hearing peoples' opinions on it on a case by case basis helps a lot. We've had some success in deprecating mistaken features - the bit data type, and typedefs. I'm surprised nobody has mentioned opApply. That was a good idea at the time, but Ranges are a superior solution. I'd like to see new code not use opApply. It's a dead end, though it'll still be supported for a long time.
Apr 30 2012
next sibling parent "Adam D. Ruppe" <destructionator gmail.com> writes:
On Monday, 30 April 2012 at 19:50:36 UTC, Walter Bright wrote:
 I'm surprised nobody has mentioned opApply.
opApply is great. I find myself finding new, kinda crazy things to do with it every so often, like concurrency sugar.
Apr 30 2012
prev sibling next sibling parent reply =?UTF-8?B?QWxleCBSw7hubmUgUGV0ZXJzZW4=?= <xtzgzorex gmail.com> writes:
On 30-04-2012 21:50, Walter Bright wrote:
 On 4/30/2012 10:04 AM, Jonathan M Davis wrote:
 I never claimed that I _was_ Walter. I was pointing out that there's very
 little consensus in this thread (almost all of the comments are in
 conflict
 with other comments) so that even if it was our intention to go and
 remove
 things from the language based on this thread, there is very little, if
 anything, that has a clear consensus on being removed. The closest would
 probably be the comma operator, and there wasn't even a complete
 consensus on
 _that_.
There is less agreement than I thought there would be. This thread also generated far more interest than I anticipated.
 And while I obviously can't say for certain what Walter intended, it
 was my
 impression that the point of this thread was more out of curiosity and
 for
 "lessons learned" from designing D than to actually make any changes
 to the
 language right now (especially when you consider how much Walter hates
 breaking backwards compatibility). But obviously, he'd have to clarify
 for us
 to know for sure.
The first thing to emphasize is that NONE of this will happen for D2. The emphasis on D2 is fixing implementation and toolchain issues. Breaking existing code is off the table unless we are pretty much forced to in order to fix some other more important issue. So we're talking several years out. The evolution of C++ is interesting. So far, the C++ committee has shown incredible resistance to removing, or even deprecating, some features that pretty much everyone knows were a mistake, all in the interests of maintaining backwards compatibility. Some of C++'s success can be attributed to that, but also some of its endemic failures. Where's the line to draw between breaking existing code and modernizing / removing cruft / removing support for features that promote bad code? Of course, there can't be any fixed rule for that. Hearing peoples' opinions on it on a case by case basis helps a lot. We've had some success in deprecating mistaken features - the bit data type, and typedefs. I'm surprised nobody has mentioned opApply. That was a good idea at the time, but Ranges are a superior solution. I'd like to see new code not use opApply. It's a dead end, though it'll still be supported for a long time.
I think what we need is an article on ranges on dlang.org (I can't find one). They seem like a rather foreign concept when you come from other languages, like array slices, and need a proper introduction. -- - Alex
Apr 30 2012
parent reply "SomeDude" <lovelydear mailmetrash.com> writes:
On Monday, 30 April 2012 at 19:58:49 UTC, Alex Rønne Petersen 
wrote:
 On 30-04-2012 21:50, Walter Bright wrote:

 I think what we need is an article on ranges on dlang.org (I 
 can't find one). They seem like a rather foreign concept when 
 you come from other languages, like array slices, and need a 
 proper introduction.
There is one talk by Andrei http://blip.tv/boostcon/boostcon-2009-keynote-2452140 and there is the chapter on Ali's book: http://ddili.org/ders/d.en/ranges.html
Apr 30 2012
parent reply =?UTF-8?B?QWxleCBSw7hubmUgUGV0ZXJzZW4=?= <xtzgzorex gmail.com> writes:
On 30-04-2012 22:25, SomeDude wrote:
 On Monday, 30 April 2012 at 19:58:49 UTC, Alex Rønne Petersen wrote:
 On 30-04-2012 21:50, Walter Bright wrote:

 I think what we need is an article on ranges on dlang.org (I can't
 find one). They seem like a rather foreign concept when you come from
 other languages, like array slices, and need a proper introduction.
There is one talk by Andrei http://blip.tv/boostcon/boostcon-2009-keynote-2452140 and there is the chapter on Ali's book: http://ddili.org/ders/d.en/ranges.html
Right, but we can't expect people who want to learn the language and its conventions to have to go to some external source for information. It has to be on dlang.org. -- - Alex
Apr 30 2012
parent "SomeDude" <lovelydear mailmetrash.com> writes:
On Monday, 30 April 2012 at 20:28:56 UTC, Alex Rønne Petersen 
wrote:
 On 30-04-2012 22:25, SomeDude wrote:
 On Monday, 30 April 2012 at 19:58:49 UTC, Alex Rønne Petersen 
 wrote:
 On 30-04-2012 21:50, Walter Bright wrote:

 I think what we need is an article on ranges on dlang.org (I 
 can't
 find one). They seem like a rather foreign concept when you 
 come from
 other languages, like array slices, and need a proper 
 introduction.
There is one talk by Andrei http://blip.tv/boostcon/boostcon-2009-keynote-2452140 and there is the chapter on Ali's book: http://ddili.org/ders/d.en/ranges.html
Right, but we can't expect people who want to learn the language and its conventions to have to go to some external source for information. It has to be on dlang.org.
I've put these links in the Wiki. They may not be visible enough, though. It still needs a lot of cleanup (although I've done a little bit of it). Baically, the first one is in the tutorials. The second is in "Why switch ?"
Apr 30 2012
prev sibling next sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 04/30/2012 09:50 PM, Walter Bright wrote:
 I'm surprised nobody has mentioned opApply. That was a good idea at the
 time, but Ranges are a superior solution. I'd like to see new code not
 use opApply. It's a dead end, though it'll still be supported for a long
 time.
foreach has been mentioned. I don't think ranges are unequivocally a superior solution. opApply is more powerful for fancy iteration tasks, such as parallel foreach.
Apr 30 2012
parent "SomeDude" <lovelydear mailmetrash.com> writes:
On Monday, 30 April 2012 at 20:04:41 UTC, Timon Gehr wrote:
 On 04/30/2012 09:50 PM, Walter Bright wrote:
 I'm surprised nobody has mentioned opApply. That was a good 
 idea at the
 time, but Ranges are a superior solution. I'd like to see new 
 code not
 use opApply. It's a dead end, though it'll still be supported 
 for a long
 time.
foreach has been mentioned. I don't think ranges are unequivocally a superior solution. opApply is more powerful for fancy iteration tasks, such as parallel foreach.
Yes, I feel they are complementary. Ranges are cool for Python-style or functional-style programming, foreach and opApply reflects more traditional iteration. I'm pretty sure that usage over time will show that they both have their use.
Apr 30 2012
prev sibling next sibling parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Mon, 30 Apr 2012 15:50:00 -0400, Walter Bright  
<newshound2 digitalmars.com> wrote:

 I'm surprised nobody has mentioned opApply. That was a good idea at the  
 time, but Ranges are a superior solution. I'd like to see new code not  
 use opApply. It's a dead end, though it'll still be supported for a long  
 time.
I think we've already covered this -- opApply does things that ranges could never do. I think they can both live in harmony. It's not even close to a dead end. I look at opApply as foreach on a range with a stack-allocated context specifically for iteration. Then of course, you can do stack-based traversal, which is not really possible for ranges. A trivial example: foreach(dchar d; "longstring") {} treating "longstring" as a range, you cannot possibly get the performance opApply has (although, you have to be able to inline both the opApply call and the delegate calls, currently not supported for the above code), as it has to decode each dchar *twice*, once for getting d, and once for popping it off the front. -Steve
Apr 30 2012
parent Walter Bright <newshound2 digitalmars.com> writes:
On 4/30/2012 1:33 PM, Steven Schveighoffer wrote:
 I think we've already covered this -- opApply does things that ranges could
 never do.
deprecating opApply would require addressing this.
Apr 30 2012
prev sibling next sibling parent reply "bearophile" <bearophileHUGS lycos.com> writes:
Walter:

 The first thing to emphasize is that NONE of this will happen 
 for D2. The emphasis on D2 is fixing implementation and 
 toolchain issues. Breaking existing code is off the table 
 unless we are pretty much forced to in order to fix some other 
 more important issue.
But you need to keep into account that D2 is still a not widely used language. So deprecating some things now will cause far less troubles than doing it in D3 some years from now. So I suggest to be a bit more flexible on this.
 We've had some success in deprecating mistaken features - the 
 bit data type, and typedefs.
In the end I agree that deprecating typedef was the right thing. Not because it's useless, quite the contrary, but because it was not well designed, so it's better to remove it to have a chance later to get it more right. Adding if far simpler than removing. But keep in mind that Phobos Typedef is so broken that it's essentially not usable in practical situations (quite more broken even than emplace and rebindable, that have several problems). So we don't have a replacement yet. Bye, bearophile
Apr 30 2012
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 04/30/2012 11:28 PM, bearophile wrote:
 Walter:

 The first thing to emphasize is that NONE of this will happen for D2.
 The emphasis on D2 is fixing implementation and toolchain issues.
 Breaking existing code is off the table unless we are pretty much
 forced to in order to fix some other more important issue.
But you need to keep into account that D2 is still a not widely used language. So deprecating some things now will cause far less troubles than doing it in D3 some years from now.
D2 -> D3 will be full of breaking changes anyway. Otherwise there is no reason to add another major language version.
Apr 30 2012
next sibling parent reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 5/1/12, Timon Gehr <timon.gehr gmx.ch> wrote:
 D2 -> D3 will be full of breaking changes anyway.
Uhmm I hope not, otherwise D3 will be dead in the water.
Apr 30 2012
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 05/01/2012 12:53 AM, Andrej Mitrovic wrote:
 On 5/1/12, Timon Gehr<timon.gehr gmx.ch>  wrote:
 D2 ->  D3 will be full of breaking changes anyway.
Uhmm I hope not,
Then what is the point of D3?
 otherwise D3 will be dead in the water.
Just provide an automatic D2->D3 conversion facility.
Apr 30 2012
next sibling parent reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 5/1/12, Timon Gehr <timon.gehr gmx.ch> wrote:
 On 05/01/2012 12:53 AM, Andrej Mitrovic wrote:
 On 5/1/12, Timon Gehr<timon.gehr gmx.ch>  wrote:
 D2 ->  D3 will be full of breaking changes anyway.
Uhmm I hope not,
Then what is the point of D3?
An incremental improvement with as little code breakage as possible? You can't even properly mix D1 and D2 code in the same library right now without resorting to using mixin() tricks.
Apr 30 2012
parent Timon Gehr <timon.gehr gmx.ch> writes:
On 05/01/2012 01:30 AM, Andrej Mitrovic wrote:
 On 5/1/12, Timon Gehr<timon.gehr gmx.ch>  wrote:
 On 05/01/2012 12:53 AM, Andrej Mitrovic wrote:
 On 5/1/12, Timon Gehr<timon.gehr gmx.ch>   wrote:
 D2 ->   D3 will be full of breaking changes anyway.
Uhmm I hope not,
Then what is the point of D3?
An incremental improvement with as little code breakage as possible?
IMHO that is similar to aiming for some code breakage with as little improvement as possible. Retainment of backwards-compatibility is what makes languages convoluted. Furthermore, the translation from D2->D3 should be possible to be performed automatically.
 You can't  even properly mix D1 and D2 code in the same library right now
 without resorting to using mixin() tricks.
This means you actually can!
Apr 30 2012
prev sibling parent "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Tuesday, May 01, 2012 01:30:11 Andrej Mitrovic wrote:
 On 5/1/12, Timon Gehr <timon.gehr gmx.ch> wrote:
 On 05/01/2012 12:53 AM, Andrej Mitrovic wrote:
 On 5/1/12, Timon Gehr<timon.gehr gmx.ch> wrote:
 D2 -> D3 will be full of breaking changes anyway.
Uhmm I hope not,
Then what is the point of D3?
An incremental improvement with as little code breakage as possible? You can't even properly mix D1 and D2 code in the same library right now without resorting to using mixin() tricks.
But you could do that without creating a D3. Once the implemnetation has stabilized, it should be possible to add new features to D2 as long as they're backwards compatible (e.g. adding user-defined attributes). The only reason to create D3 would be if we wanted to make changes which _weren't_ backwards compatible. - Jonathan M Davis
Apr 30 2012
prev sibling next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
Timon Gehr:

 D2 -> D3 will be full of breaking changes anyway. Otherwise 
 there is no reason to add another major language version.
I remember Walter (and Andrei) stated that D2 is the latest major breaking change in D. So D3 is supposed to be a smooth change (but of course no one knows what will happen). Bye, bearophile
Apr 30 2012
prev sibling parent reply Don Clugston <dac nospam.com> writes:
On 01/05/12 00:33, Timon Gehr wrote:
 On 04/30/2012 11:28 PM, bearophile wrote:
 Walter:

 The first thing to emphasize is that NONE of this will happen for D2.
 The emphasis on D2 is fixing implementation and toolchain issues.
 Breaking existing code is off the table unless we are pretty much
 forced to in order to fix some other more important issue.
But you need to keep into account that D2 is still a not widely used language. So deprecating some things now will cause far less troubles than doing it in D3 some years from now.
D2 -> D3 will be full of breaking changes anyway. Otherwise there is no reason to add another major language version.
What is this D3 thing ???? As far as I can tell, 'D3' was invented by newcomers to the forums.
May 03 2012
parent reply "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Thursday, May 03, 2012 15:30:40 Don Clugston wrote:
 What is this D3 thing ????
 As far as I can tell, 'D3' was invented by newcomers to the forums.
I think that what it comes down to is that there are a variety of people who want features added or changed in D which are either not going to happen anytime soon or will never happen in D2 (especially if they're major breaking changes). So, they figure/hope that we'll have a new revision of the language where we'll be able to make breaking changes and then maybe the changes that they want will make it in then. After all, particularly from the perspective of a newbie, we already had D2 which changed a bunch of stuff from D1, why wouldn't we have D3 later on? And for folks who really want to see changes that aren't going to happen, the idea that we're going to have another major revision of the language which might make the changes that they want sounds really appealing. I think that Walter and Andrei have made it fairly clear when they've said anything on the subject that there is no intention to make any kind of D3 anytime soon and that if we do, it'll be years from now after D2 is mature and well-established, and it actually makes sense to do a new major revision. But I do think that you're right in that the very idea of a D3 was created by folks in the newsgroup. Walter and the other developers have been focusing on stabilizing D2 as _the_ version of the language, not finishing it up so that they can move onto D3. And the misconceptions about D1 that you've pointed out in the past probably just help contribute to the idea that we'll have a D3 at some point. Maybe we will, maybe we won't, but there's no point in worrying about it for years yet. - Jonathan M Davis
May 03 2012
next sibling parent reply "Era Scarecrow" <rtcvb32 yahoo.com> writes:
On Thursday, 3 May 2012 at 20:36:47 UTC, Jonathan M Davis wrote:
 On Thursday, May 03, 2012 15:30:40 Don Clugston wrote:
 What is this D3 thing ????
 As far as I can tell, 'D3' was invented by newcomers to the 
 forums.
I think that what it comes down to is that there are a variety of people who want features added or changed in D which are either not going to happen anytime soon or will never happen in D2 (especially if they're major breaking changes). So, they figure/hope that we'll have a new revision of the language where we'll be able to make breaking changes and then maybe the changes that they want will make it in then. After all, particularly from the perspective of a newbie, we already had D2 which changed a bunch of stuff from D1, why wouldn't we have D3 later on? And for folks who really want to see changes that aren't going to happen, the idea that we're going to have another major revision of the language which might make the changes that they want sounds really appealing. I think that Walter and Andrei have made it fairly clear when they've said anything on the subject that there is no intention to make any kind of D3 anytime soon and that if we do, it'll be years from now after D2 is mature and well-established, and it actually makes sense to do a new major revision. But I do think that you're right in that the very idea of a D3 was created by folks in the newsgroup. Walter and the other developers have been focusing on stabilizing D2 as _the_ version of the language, not finishing it up so that they can move onto D3. And the misconceptions about D1 that you've pointed out in the past probably just help contribute to the idea that we'll have a D3 at some point. Maybe we will, maybe we won't, but there's no point in worrying about it for years yet.
If anything, I would consider D3 an ideal, something to work towards. And no it wouldn't be started or really worked on for at 10-15 years after D's mature and at Andrei's goal of having at least a million users. And as stated before, if there [b]IS[/b] going to be a D3 at any point it should have no problem calling D2 code. Course thinking of D3 now is kinda like thinking of flying cars and how you want a flying car and you won't buy a car today until it can fly... Back (in the 50-60's was it?) they thought we would be having a flying car for every family and had these really badly done animations of what they expected to see. I don't see any flying cars outside of Hollywood. Best if we stick in the present and deal with our problems now.
May 03 2012
parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Thu, May 03, 2012 at 11:32:52PM +0200, Era Scarecrow wrote:
[[...]
  If anything, I would consider D3 an ideal, something to work
 towards. And no it wouldn't be started or really worked on for at
 10-15 years after D's mature and at Andrei's goal of having at least
 a million users. And as stated before, if there [b]IS[/b] going to
 be a D3 at any point it should have no problem calling D2 code.
Do we know (roughly) how many D users are out there right now?
  Course thinking of D3 now is kinda like thinking of flying cars and
 how you want a flying car and you won't buy a car today until it can
 fly...  Back (in the 50-60's was it?) they thought we would be
 having a flying car for every family and had these really badly done
 animations of what they expected to see. I don't see any flying cars
 outside of Hollywood. Best if we stick in the present and deal with
 our problems now.
There aren't any flying cars in Hollywood either. They're either just artist's concepts (*cough*CGI models*cough*), held up by strings, or just superimposed on an animated background. T -- It is not the employer who pays the wages. Employers only handle the money. It is the customer who pays the wages. -- Henry Ford
May 03 2012
parent reply "Era Scarecrow" <rtcvb32 yahoo.com> writes:
On Thursday, 3 May 2012 at 22:29:47 UTC, H. S. Teoh wrote:
 On Thu, May 03, 2012 at 11:32:52PM +0200, Era Scarecrow wrote:
 Do we know (roughly) how many D users are out there right now?
Don't know. Need a poll :) I'm definitely sure we have at least 10 users; beyond that I can only speculate; Maybe 2 to the power of ten or thirteen...
 There aren't any flying cars in Hollywood either. They're 
 either just artist's concepts (*cough*CGI models*cough*), held 
 up by strings, or just superimposed on an animated background.
Exactly! It's on the 'big screen', meaning smoke and gimmicks, the same as magicians. Anyways, focus on the now. D3 may/will come some day, but that's a long ways off. Course if you plan early for certain things that will change it does make going towards it easier with language design, or give you more time to think about faults and fixes.
May 03 2012
parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Fri, May 04, 2012 at 01:12:20AM +0200, Era Scarecrow wrote:
 On Thursday, 3 May 2012 at 22:29:47 UTC, H. S. Teoh wrote:
On Thu, May 03, 2012 at 11:32:52PM +0200, Era Scarecrow wrote:
Do we know (roughly) how many D users are out there right now?
Don't know. Need a poll :) I'm definitely sure we have at least 10 users; beyond that I can only speculate; Maybe 2 to the power of ten or thirteen...
Only 10?? Judging from mailing list membership, I'd say at least 25 or 30, just on the forums alone. I'm assuming that people here aren't subscribed just for kicks, they actually write D code. There are probably more outside the forums (somebody mentioned an entire company of D programmers before, perhaps about 50-100? I don't remember the exact figure). There's got to be more out there, given that Andrei has been giving talks about D for a while. *Somebody* in the audience must be actually listening to what he says. But in any case, I'd say we have a ways to go yet in terms of D adoption. [...]
  Anyways, focus on the now. D3 may/will come some day, but that's a
 long ways off. Course if you plan early for certain things that will
 change it does make going towards it easier with language design, or
 give you more time to think about faults and fixes.
Yep. T -- Those who don't understand Unix are condemned to reinvent it, poorly.
May 03 2012
next sibling parent "Era Scarecrow" <rtcvb32 yahoo.com> writes:
On Thursday, 3 May 2012 at 23:40:32 UTC, H. S. Teoh wrote:
 Only 10?? Judging from mailing list membership, I'd say at 
 least 25 or 30, just on the forums alone. I'm assuming that 
 people here aren't subscribed just for kicks, they actually 
 write D code. There are probably more outside the forums 
 (somebody mentioned an entire company of D programmers before, 
 perhaps about 50-100? I don't remember the exact figure). 
 There's got to be more out there, given that Andrei has been 
 giving talks about D for a while. *Somebody* in the audience 
 must be actually listening to what he says.
I was being sarcastic :P
May 03 2012
prev sibling parent =?ISO-8859-1?Q?Alex_R=F8nne_Petersen?= <xtzgzorex gmail.com> writes:
On 04-05-2012 01:41, H. S. Teoh wrote:
 On Fri, May 04, 2012 at 01:12:20AM +0200, Era Scarecrow wrote:
 On Thursday, 3 May 2012 at 22:29:47 UTC, H. S. Teoh wrote:
 On Thu, May 03, 2012 at 11:32:52PM +0200, Era Scarecrow wrote:
 Do we know (roughly) how many D users are out there right now?
Don't know. Need a poll :) I'm definitely sure we have at least 10 users; beyond that I can only speculate; Maybe 2 to the power of ten or thirteen...
Only 10?? Judging from mailing list membership, I'd say at least 25 or 30, just on the forums alone. I'm assuming that people here aren't subscribed just for kicks, they actually write D code. There are probably more outside the forums (somebody mentioned an entire company of D programmers before, perhaps about 50-100? I don't remember the exact figure). There's got to be more out there, given that Andrei has been giving talks about D for a while. *Somebody* in the audience must be actually listening to what he says. But in any case, I'd say we have a ways to go yet in terms of D adoption.
There are more users than one might think. If you fancy some IRC, you should drop by #d (104 users), #d.gdc (17 users), #ldc (18 users), #d.sdc (5 users) on irc.freenode.net. :) There's also #d on irc.oftc.net (started by Iain).
 [...]
   Anyways, focus on the now. D3 may/will come some day, but that's a
 long ways off. Course if you plan early for certain things that will
 change it does make going towards it easier with language design, or
 give you more time to think about faults and fixes.
Yep. T
-- - Alex
May 03 2012
prev sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2012-05-03 22:36, Jonathan M Davis wrote:
 On Thursday, May 03, 2012 15:30:40 Don Clugston wrote:
 What is this D3 thing ????
 As far as I can tell, 'D3' was invented by newcomers to the forums.
I think that what it comes down to is that there are a variety of people who want features added or changed in D which are either not going to happen anytime soon or will never happen in D2 (especially if they're major breaking changes). So, they figure/hope that we'll have a new revision of the language where we'll be able to make breaking changes and then maybe the changes that they want will make it in then. After all, particularly from the perspective of a newbie, we already had D2 which changed a bunch of stuff from D1, why wouldn't we have D3 later on? And for folks who really want to see changes that aren't going to happen, the idea that we're going to have another major revision of the language which might make the changes that they want sounds really appealing. I think that Walter and Andrei have made it fairly clear when they've said anything on the subject that there is no intention to make any kind of D3 anytime soon and that if we do, it'll be years from now after D2 is mature and well-established, and it actually makes sense to do a new major revision. But I do think that you're right in that the very idea of a D3 was created by folks in the newsgroup. Walter and the other developers have been focusing on stabilizing D2 as _the_ version of the language, not finishing it up so that they can move onto D3. And the misconceptions about D1 that you've pointed out in the past probably just help contribute to the idea that we'll have a D3 at some point. Maybe we will, maybe we won't, but there's no point in worrying about it for years yet. - Jonathan M Davis
People has been talking about D3 for quite a while. Have a look at: http://prowiki.org/wiki4d/wiki.cgi?LanguageDevel Search for "Known to be deferred to D3.0". The features listed there were talked about before D2. -- /Jacob Carlborg
May 04 2012
parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Friday, May 04, 2012 09:38:24 Jacob Carlborg wrote:
 On 2012-05-03 22:36, Jonathan M Davis wrote:
 On Thursday, May 03, 2012 15:30:40 Don Clugston wrote:
 What is this D3 thing ????
 As far as I can tell, 'D3' was invented by newcomers to the forums.
I think that what it comes down to is that there are a variety of people who want features added or changed in D which are either not going to happen anytime soon or will never happen in D2 (especially if they're major breaking changes). So, they figure/hope that we'll have a new revision of the language where we'll be able to make breaking changes and then maybe the changes that they want will make it in then. After all, particularly from the perspective of a newbie, we already had D2 which changed a bunch of stuff from D1, why wouldn't we have D3 later on? And for folks who really want to see changes that aren't going to happen, the idea that we're going to have another major revision of the language which might make the changes that they want sounds really appealing. I think that Walter and Andrei have made it fairly clear when they've said anything on the subject that there is no intention to make any kind of D3 anytime soon and that if we do, it'll be years from now after D2 is mature and well-established, and it actually makes sense to do a new major revision. But I do think that you're right in that the very idea of a D3 was created by folks in the newsgroup. Walter and the other developers have been focusing on stabilizing D2 as _the_ version of the language, not finishing it up so that they can move onto D3. And the misconceptions about D1 that you've pointed out in the past probably just help contribute to the idea that we'll have a D3 at some point. Maybe we will, maybe we won't, but there's no point in worrying about it for years yet. - Jonathan M Davis
People has been talking about D3 for quite a while. Have a look at: http://prowiki.org/wiki4d/wiki.cgi?LanguageDevel Search for "Known to be deferred to D3.0". The features listed there were talked about before D2.
Oh. I know that they've been talking about it for a while, but as far as I can tell, the term has gotten used primarily due to people who don't like the fact that D2 is doing something a particular way or isn't doing something a particular way and who hope that there will be a future version of the language which does it the way that they want. Certainly, it's not something which Walter has pushed at all (the opposite, if anything). - Jonathan M Davis
May 04 2012
prev sibling next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
Walter:

 The evolution of C++ is interesting.
I think the evolution and updating patterns of the language Scale are more interesting for us. Bye, bearophile
Apr 30 2012
prev sibling next sibling parent "foobar" <foo bar.com> writes:
On Monday, 30 April 2012 at 19:50:36 UTC, Walter Bright wrote:
[...]
 I'm surprised nobody has mentioned opApply. That was a good 
 idea at the time, but Ranges are a superior solution. I'd like 
 to see new code not use opApply. It's a dead end, though it'll 
 still be supported for a long time.
Both internal and external iteration have their pros and cons. It doesn't make sense to claim one is superior to the other. Ranges are more appropriate for serial code whereas internal iteration is better suited for concurrent code.
Apr 30 2012
prev sibling parent reply "Kapps" <opantm2+spam gmail.com> writes:
On Monday, 30 April 2012 at 19:50:36 UTC, Walter Bright wrote:
 I'm surprised nobody has mentioned opApply. That was a good 
 idea at the time, but Ranges are a superior solution. I'd like 
 to see new code not use opApply. It's a dead end, though it'll 
 still be supported for a long time.
I practically never use ranges, and instead use opApply for all my code. 1) Ranges force me to use a specific naming convention. My naming convention that I use for my projects is upper camel case. Ranges do not allow this. Technically opApply is still lower camel case, but my code doesn't directly call it. 2) Ranges don't have a way of determining when the iteration ends. Sometimes you want to do something once iteration stops. For example, by far the most common action when executing a database call for me, is to iterate over it and close it. I can then have a helper method that executes the command and closes it when the foreach is done (whether by break or by the function ending). This saves quite a bit of boiler plate code. 3) Ranges can be difficult to implement. You now have to keep track of state instead of simply leaving everything inside a single method call. This can also cause significant problems with multi-threaded code. 4) Ranges take a lot more code, which when all you want is basic iteration, is pointless to have. I'd much rather just see things with opApply being able to have a forward-range magically created for it, much like the reverse. Not sure if this is possible or practical though.
Apr 30 2012
next sibling parent reply "akaz" <nemo utopia.com> writes:
Sorry for my 2nd intervention on this thread. I recently ported 
some (not much) code from C to D. My impression was that D(2) 
tries to be too many things at once. I even considered porting to 
D(1) instead of D(2). What attracted me into the first place to D 
was it promise to be a "better C" (and a better C++), at least 
this is I saw it. However, it seems to have grown too complex to 
me. Yes, I understand that new, modern features should be 
provided by the language, but I do not like to be forced to use 
those.

 From my (limited) background, what I really liked in D:

*the new type[n] and type* declaration syntax
*the templates syntax (that's a biiig plus)
*other things that I do not remember now, but they are plenty of 
them
*the fact that constructors and destructors do not need renaming 
when class name changes (I hated that in C++ and Java), although 
I would have liked more special kewords like "ctor()" and 
"dtor()", instead of "this()" and "~this()", but I can cope with 
that)

What I did NOT like in D (is my impression):

*the confusion between . and -> operators (yes, I know the latter 
does not exist in D, is just for talking first here) for classes 
and structs and why classes are or are not pointers and why 
structs behave differently (or, at least, this is how I perceive 
it) and why not the pointer syntax is not used if they are 
pointers (well, references) and so on (yes, I am a bit dizzy, but 
is not entirely my fault; it's also D's).
*the many   annotations that is not clear if they are compulsory 
or not (and, if not, how to convince me to use them...)
*the writing of the p[0..len] that you need to use when some 
other code (C code) passes you the pointer to data and the length 
(I just do not like it)
*it is also my impression that you cannot declare int[] 
x=<<some_initialization>> as a static array with length filled in 
by compiler at the compile time, since the length is known? 
instead, x is interpreted as a dynamic array (which, also, I do 
not like that same syntax, or very similar, is used for both 
concepts).
*the fact that the calling of a function bears no indication if 
you modify or not the passed variable (I much prefer the C-ish 
style of foo(a,&b); where you *almost* know that b will be 
modified)

Well, these are some. I feel that the right line is somewhere 
between D1 and D2. It is good that advanced, complex features are 
present in D, I just not want to be forced to use those when 
porting "traditional" C code.

I expected to meet D and exclaim: wow! C++ done right! Instead, I 
feel like being forced to learn another, completely new paradigm 
language, like I would start with Lisp or something else.

Remember:
"Within D, there is a much smaller and cleaner language 
struggling to get out".
Apr 30 2012
next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
akaz:

 Well, these are some. I feel that the right line is somewhere 
 between D1 and D2. It is good that advanced, complex features 
 are present in D, I just not want to be forced to use those 
 when porting "traditional" C code.

 I expected to meet D and exclaim: wow! C++ done right! Instead, 
 I feel like being forced to learn another, completely new 
 paradigm language, like I would start with Lisp or something 
 else.
I think D is not C++ done right any more, it's a new language. This was probably necessary if you want D to have a more than minimal chance of success. I have translated a significant amount of C code to D1 and D2, and usually in such simple porting I find bugs in the original C code, like off-by-on errors in arrays, missing returns, missing breaks in switches, dead code paths caused by precedent returns, erroneous re-uses of loop variables used in outer scopes, and so on. So I love such (moderate) bug-discovering qualities of D, and I'd like D to have even more of them. In many cases D doesn't force you to use its advanced features, it allows you to write very C-looking code too (that is usually bad D code). But probably D can't allow this in every case, some things need to change if you want to improve the language a little. So think of those forced uses as a small price to pay to have a better language. Bye, bearophile
Apr 30 2012
prev sibling next sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 05/01/2012 01:20 AM, akaz wrote:
 I expected to meet D and exclaim: wow! C++ done right! Instead, I feel
 like being forced to learn another,
Yes, D is its own thing.
 completely new paradigm language,
 like I would start with Lisp or something else.
OTOH, this seems to be an exaggeration.
 Remember:
 "Within D, there is a much smaller and cleaner language struggling to
 get out".
I don't see the value of that assertion from a pragmatic point of view. What is to be gained? Note that you have discussed mostly syntax. * adding -> does not make the language smaller or cleaner and it complicates generic code for no benefit. * loosening the syntactic distinction between value and reference type variable declarations could be done, (to the neat effect that tail-qualified class references would trivially work) but there shouldn't be any directly built-in support for treating polymorphic class instances as values. * I agree that the property situation needs to be cleaned up. There are only five annotations in total. And what you have said does not apply to the other four. * how p[0..len] can be seen as an issue instead of as great completely escapes my mind. * I agree on supporting deducing length for static arrays. (there is a int[$] arr = [1,2,3]; proposal.) * the syntax for arrays is straightforward and I don't see any potential for improvement. * the foo(a,&b) example is biased because it uses a meaningless function name. From the function name alone it is often *almost* clear that a certain argument will be modified. & & & spam is not 'clean' either.
Apr 30 2012
next sibling parent reply "bearophile" <bearophileHUGS lycos.com> writes:
Timon Gehr:

 * I agree on supporting deducing length for static arrays. 
 (there is a
   int[$] arr = [1,2,3]; proposal.)
Someone in Bugzilla ha just proposed an alternative idea, that despite not looking very nice, is not overall bad (here with a small change): auto arr = [1, 2, 3]f; That trailing f denotes a fixed-side array/string literal. So it's usable for other situations too.
 * the foo(a,&b) example is biased because it uses a meaningless
   function name. From the function name alone it is often 
 *almost*
   clear that a certain argument will be modified. & & & spam is 
 not
   'clean' either.
most cases). D language has chosen a different design, but here bit more clear. Bye, bearophile
Apr 30 2012
next sibling parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Tue, May 01, 2012 at 02:14:42AM +0200, bearophile wrote:
 Timon Gehr:
 
* I agree on supporting deducing length for static arrays. (there
is a
  int[$] arr = [1,2,3]; proposal.)
Someone in Bugzilla ha just proposed an alternative idea, that despite not looking very nice, is not overall bad (here with a small change): auto arr = [1, 2, 3]f; That trailing f denotes a fixed-side array/string literal. So it's usable for other situations too.
[...] I don't like it. An f prefix already means float in another context; overloading it to also mean static array is a bad idea. D already has too much overloaded syntax (like static meaning all sorts of diverse things depending on context). I much prefer the int[$] proposal, because $ already means "length of array" in D, and so would fit right in. T -- We've all heard that a million monkeys banging on a million typewriters will eventually reproduce the entire works of Shakespeare. Now, thanks to the Internet, we know this is not true. -- Robert Wilensk
Apr 30 2012
prev sibling next sibling parent =?UTF-8?B?QWxleCBSw7hubmUgUGV0ZXJzZW4=?= <xtzgzorex gmail.com> writes:
On 01-05-2012 02:14, bearophile wrote:
 Timon Gehr:

 * I agree on supporting deducing length for static arrays. (there is a
 int[$] arr = [1,2,3]; proposal.)
Someone in Bugzilla ha just proposed an alternative idea, that despite not looking very nice, is not overall bad (here with a small change): auto arr = [1, 2, 3]f; That trailing f denotes a fixed-side array/string literal. So it's usable for other situations too.
 * the foo(a,&b) example is biased because it uses a meaningless
 function name. From the function name alone it is often *almost*
 clear that a certain argument will be modified. & & & spam is not
 'clean' either.
some advantages too, it makes the code semantics a bit more clear.
Tell me about it... I've had a few WTF and WAT moments due to D's design here.
 Bye,
 bearophile
-- - Alex
Apr 30 2012
prev sibling parent reply Artur Skawina <art.08.09 gmail.com> writes:
On 05/01/12 02:25, H. S. Teoh wrote:
 On Tue, May 01, 2012 at 02:14:42AM +0200, bearophile wrote:
 Timon Gehr:

 * I agree on supporting deducing length for static arrays. (there
 is a
  int[$] arr = [1,2,3]; proposal.)
Someone in Bugzilla ha just proposed an alternative idea, that despite not looking very nice, is not overall bad (here with a small change): auto arr = [1, 2, 3]f; That trailing f denotes a fixed-side array/string literal. So it's usable for other situations too.
[...] I don't like it. An f prefix already means float in another context; overloading it to also mean static array is a bad idea. D already has too much overloaded syntax (like static meaning all sorts of diverse things depending on context). I much prefer the int[$] proposal, because $ already means "length of array" in D, and so would fit right in.
Since one of the most characteristic D features is overloading "static" whenever possible, this would fit right in: auto arr = static [1, 2, 3]; artur
May 01 2012
parent Jacob Carlborg <doob me.com> writes:
On 2012-05-01 11:50, Artur Skawina wrote:

 Since one of the most characteristic D features is overloading "static"
 whenever possible, this would fit right in:

     auto arr = static [1, 2, 3];

 artur
Meaning this would need to be allowed: static arr = static [1, 2, 3]; That looks a bit confusing. -- /Jacob Carlborg
May 01 2012
prev sibling parent "Era Scarecrow" <rtcvb32 yahoo.com> writes:
On Tuesday, 1 May 2012 at 00:02:37 UTC, Timon Gehr wrote:
 * how p[0..len] can be seen as an issue instead of as great 
 completely escapes my mind.
I can only offer my own experiences. When I first saw D1 and saw ranges used like that, it looked like pure greek and confused the hell out of me. I mean, what is this ..? How does it work? Only after a lightbulb appearing over my head did I realize .. was just another operator, which didn't exist in C or C++. Having the example completely broken down into equiv D code that doesn't use the .. makes it's use and glue to the compiler a bit more obvious and fills in the gaps. I mean, how would you take a foreign symbols of << 1->End >> to be? If you squint, it's just a slightly different syntax for the same thing; depending on how you interpret the languages(s).
Apr 30 2012
prev sibling parent "Simen Kjaeraas" <simen.kjaras gmail.com> writes:
On Tue, 01 May 2012 01:20:53 +0200, akaz <nemo utopia.com> wrote:

 *the confusion between . and -> operators (yes, I know the latter does  
 not exist in D, is just for talking first here) for classes and structs  
 and why classes are or are not pointers and why structs behave  
 differently (or, at least, this is how I perceive it) and why not the  
 pointer syntax is not used if they are pointers (well, references) and  
 so on (yes, I am a bit dizzy, but is not entirely my fault; it's also  
 D's).
Really? This is one of the big pluses to me.
 *the writing of the p[0..len] that you need to use when some other code  
 (C code) passes you the pointer to data and the length (I just do not  
 like it)
While I can agree it's not perfect, I have a hard time seeing a better solution. Somewhere the information has to be combined to create a proper array.
 *it is also my impression that you cannot declare int[]  
 x=<<some_initialization>> as a static array with length filled in by  
 compiler at the compile time, since the length is known? instead, x is  
 interpreted as a dynamic array (which, also, I do not like that same  
 syntax, or very similar, is used for both concepts).
Agreed.
 *the fact that the calling of a function bears no indication if you  
 modify or not the passed variable (I much prefer the C-ish style of  
 foo(a,&b); where you *almost* know that b will be modified)
parameters ref or out. I'd really like that for D too.
Apr 30 2012
prev sibling next sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 05/01/2012 12:54 AM, Kapps wrote:
 On Monday, 30 April 2012 at 19:50:36 UTC, Walter Bright wrote:
 I'm surprised nobody has mentioned opApply. That was a good idea at
 the time, but Ranges are a superior solution. I'd like to see new code
 not use opApply. It's a dead end, though it'll still be supported for
 a long time.
I practically never use ranges, and instead use opApply for all my code. 1) Ranges force me to use a specific naming convention. My naming convention that I use for my projects is upper camel case. Ranges do not allow this.
Yes they do. (If you are willing to have both kinds of symbols around.) mixin template AddAliasesForBuiltInRange(){ alias Front front; alias Empty empty; alias PopFront popFront; } struct R{ ... property Front(){...} property bool Empty(){...} void PopFront(){...} mixin AddAliasesForBuiltInRange; }
 Technically opApply is still lower camel case, but my code
 doesn't directly call it.
The same would hold for the above example.
 2) Ranges don't have a way of determining when the iteration ends.
 Sometimes you want to do something once iteration stops. For example, by
 far the most common action when executing a database call for me, is to
 iterate over it and close it. I can then have a helper method that
 executes the command and closes it when the foreach is done (whether by
 break or by the function ending). This saves quite a bit of boiler plate
 code.
An important point.
 3) Ranges can be difficult to implement. You now have to keep track of
 state instead of simply leaving everything inside a single method call.
 This can also cause significant problems with multi-threaded code.

 4) Ranges take a lot more code, which when all you want is basic
 iteration, is pointless to have
Those two could be mitigated by moving the range concept further into the language.
 I'd much rather just see things with opApply being able to have a
 forward-range magically created for it, much like the reverse. Not sure
 if this is possible or practical though.
Am implementation (that is possible now) could use coroutines (core.thread.Fiber), but that is not very efficient for simple return. (In D the compiler would generate anonymous struct types instead of IEnumerable interface implementations).
Apr 30 2012
prev sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
Kapps:

 1) Ranges force me to use a specific naming convention. My 
 naming convention that I use for my projects is upper camel 
 case. Ranges do not allow this.
Not following the common naming conventions of a language is bad, or quite bad. Most or all modern languages seem to have realized When I see D code written by other people it's very handy to guess some characteristics of the things I'm using assuming it follows the D common naming conventions. This makes reading code simpler, faster, reduces some chances of introducing bugs, and makes is quicker to hack into code written by other people. Bye, bearophile
Apr 30 2012
prev sibling next sibling parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Mon, Apr 30, 2012 at 01:04:01PM -0400, Jonathan M Davis wrote:
[...]
 And while I obviously can't say for certain what Walter intended, it
 was my impression that the point of this thread was more out of
 curiosity and for "lessons learned" from designing D than to actually
 make any changes to the language right now (especially when you
 consider how much Walter hates breaking backwards compatibility). But
 obviously, he'd have to clarify for us to know for sure.
[...] It would be unwise to make major changes to the language at this point. Personally I'd like to see the comma operator removed, but people keep saying it will break existing code, so that's probably not going to happen in D2. D3 perhaps will be able to clean up a lot of this mess. And frankly, most of the responses on this thread (including my own, I'll admit) are more wishlist items than the truly "redundant" features that Walter referred to initially. And I have to say that in spite of little annoyances here and there, D2 is still the closest to my ideal programming language, and that's unlikely to change anytime soon. What we really need to focus on now is to hone the existing features, clean up the bugs, and improve the implementation, rather than continue to introduce new features and breaking changes. Existing features really need to Just Work(tm). We will drive away many potential D users by incomplete/buggy implementation of advertised features. T -- There are three kinds of people in the world: those who can count, and those who can't.
Apr 30 2012
parent reply "Era Scarecrow" <rtcvb32 yahoo.com> writes:
On Monday, 30 April 2012 at 17:13:36 UTC, H. S. Teoh wrote:
 On Mon, Apr 30, 2012 at 01:04:01PM -0400, Jonathan M Davis It 
 would be unwise to make major changes to the language at this 
 point.
 Personally I'd like to see the comma operator removed, but 
 people keep
 saying it will break existing code, so that's probably not 
 going to
 happen in D2. D3 perhaps will be able to clean up a lot of this 
 mess.
Then perhaps the comma operator can be pushed to the 'depreciated' list for a while; If it breaks anything big and important, you can still compile it. After a while we can see if it should be kept or removed. I think that's the best approach all things considered. Personally, I have yet to really use it outside of a for/foreach statement. On the other hand if it breaks something, generally it will become quite clear where in few the few places and require you to fix and update it before moving on.
Apr 30 2012
next sibling parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Mon, Apr 30, 2012 at 08:09:31PM +0200, Era Scarecrow wrote:
 On Monday, 30 April 2012 at 17:13:36 UTC, H. S. Teoh wrote:
It would be unwise to make major changes to the language at this
point.  Personally I'd like to see the comma operator removed, but
people keep saying it will break existing code, so that's probably
not going to happen in D2. D3 perhaps will be able to clean up a lot
of this mess.
Then perhaps the comma operator can be pushed to the 'depreciated' list for a while; If it breaks anything big and important, you can still compile it. After a while we can see if it should be kept or removed. I think that's the best approach all things considered. Personally, I have yet to really use it outside of a for/foreach statement. On the other hand if it breaks something, generally it will become quite clear where in few the few places and require you to fix and update it before moving on.
Actually it's only inside for. A comma in foreach is not a comma operator but a separator (foreach(a,b;c) is not the same as foreach(b;c)). See, that's another case where it only causes confusion. And I've said many times that inside a for, it really should just be special-cased in for syntax. It should not be an operator in general. T -- Right now I'm having amnesia and deja vu at the same time. I think I've forgotten this before.
Apr 30 2012
parent =?ISO-8859-1?Q?Alex_R=F8nne_Petersen?= <xtzgzorex gmail.com> writes:
On 30-04-2012 20:28, H. S. Teoh wrote:
 On Mon, Apr 30, 2012 at 08:09:31PM +0200, Era Scarecrow wrote:
 On Monday, 30 April 2012 at 17:13:36 UTC, H. S. Teoh wrote:
 It would be unwise to make major changes to the language at this
 point.  Personally I'd like to see the comma operator removed, but
 people keep saying it will break existing code, so that's probably
 not going to happen in D2. D3 perhaps will be able to clean up a lot
 of this mess.
Then perhaps the comma operator can be pushed to the 'depreciated' list for a while; If it breaks anything big and important, you can still compile it. After a while we can see if it should be kept or removed. I think that's the best approach all things considered. Personally, I have yet to really use it outside of a for/foreach statement. On the other hand if it breaks something, generally it will become quite clear where in few the few places and require you to fix and update it before moving on.
Actually it's only inside for. A comma in foreach is not a comma operator but a separator (foreach(a,b;c) is not the same as foreach(b;c)). See, that's another case where it only causes confusion. And I've said many times that inside a for, it really should just be special-cased in for syntax. It should not be an operator in general. T
-- - Alex
Apr 30 2012
prev sibling parent "SomeDude" <lovelydear mailmetrash.com> writes:
On Monday, 30 April 2012 at 18:09:32 UTC, Era Scarecrow wrote:
  Then perhaps the comma operator can be pushed to the 
 'depreciated' list for a while; If it breaks anything big and 
 important, you can still compile it. After a while we can see 
 if it should be kept or removed. I think that's the best 
 approach all things considered.

  Personally, I have yet to really use it outside of a 
 for/foreach statement. On the other hand if it breaks 
 something, generally it will become quite clear where in few 
 the few places and require you to fix and update it before 
 moving on.
What we need is a "style guide", ala Scott Meyer, i.e try to find D idioms, how to write good code, what to avoid. Because even though it's harder to write bad code in D than in C++, it's always possible to write code with low performance, or be bitten by some traps. Here is an example: http://forum.dlang.org/post/mailman.9.1335539605.24740.digitalmars-d-learn puremagic.com
Apr 30 2012
prev sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 4/30/12 5:15 AM, bearophile wrote:
 Jonathan M Davis:

 Honestly, I don't think that you _can_ take much from this thread
 other than
I don't agree, I see some recurring patterns. People have spent energy and time to write lot of answers in this thread, some good answer bits too, so I expect such work to not let be fully wasted. Asking for opinions, receiving lot of them, and then ignoring them all is not a good way to run a community.
It's a bit inappropriate to bind Walter to such a social contract upon having asked an informal question. Besides, if we're talking about work of writing posts we should also consider the considerable work of reading certain posts, which are so patronizing as to make reading an exercise in eye rolling.
 And thank you for your answer, I always appreciate your answers, but you
 aren't Walter, that post was for him (and Andrei) to answer :-)
FWIW there is little agreement among answers. Eliminating today's semantics of comma inevitably underlies the hope that it can be retrofitted for something else, which I think is near impossible without changing semantics of working code. Then there's a lot of busywork. Eliminating e.g. "with" is going to leave things pretty much where they are with the note some innocently bystanding programs are going to break. One feature to remove stands out - the struct initialization: struct S { int x, y; } S s = { 1, 2 }; This, was noted, makes the order of members effectively part of the struct's interface, which is subtly dangerous. I think we should remove this feature. Andrei
May 01 2012
next sibling parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
On Wednesday, 2 May 2012 at 03:22:02 UTC, Andrei Alexandrescu 
wrote:
 One feature to remove stands out - the struct initialization:
 S s = { 1, 2 };
I could live without that one, because D has an alternative: auto s = S(1, 2); And I'd be sad if you took that out, as I use it a lot, especially for trivial types: struct Html { string src; } struct Text { string src; } struct Point { int x; int y; } struct Size { int width; int height; } which I like because then we can use the types for overloading, static checks, etc., and it is very very simple to drop in and use. I guess there could be opCalls or constructors, but poo, it works now without that and I like it.
May 01 2012
next sibling parent reply "Jakob Ovrum" <jakobovrum gmail.com> writes:
On Wednesday, 2 May 2012 at 03:38:41 UTC, Adam D. Ruppe wrote:
 On Wednesday, 2 May 2012 at 03:22:02 UTC, Andrei Alexandrescu 
 wrote:
 One feature to remove stands out - the struct initialization:
 S s = { 1, 2 };
I could live without that one, because D has an alternative: auto s = S(1, 2); And I'd be sad if you took that out, as I use it a lot, especially for trivial types: struct Html { string src; } struct Text { string src; } struct Point { int x; int y; } struct Size { int width; int height; } which I like because then we can use the types for overloading, static checks, etc., and it is very very simple to drop in and use. I guess there could be opCalls or constructors, but poo, it works now without that and I like it.
S(...) does not exhibit the same problem as {...} exactly because it has constructors and static opCall. If you change the order of fields in S, you can write a constructor preserving the old behaviour.
May 01 2012
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 5/2/12 12:20 AM, Jakob Ovrum wrote:
 S(...) does not exhibit the same problem as {...} exactly because it has
 constructors and static opCall. If you change the order of fields in S,
 you can write a constructor preserving the old behaviour.
Good observation. So indeed the { ... } case is inferior because there's no reasonable way for the library writer to defend against. Andrei
May 02 2012
prev sibling next sibling parent reply "Maxim Fomin" <maxim maxim-fomin.ru> writes:
On Wednesday, 2 May 2012 at 03:38:41 UTC, Adam D. Ruppe wrote:
 On Wednesday, 2 May 2012 at 03:22:02 UTC, Andrei Alexandrescu 
 wrote:
 One feature to remove stands out - the struct initialization:
 S s = { 1, 2 };
I could live without that one, because D has an alternative: auto s = S(1, 2);
It has the same problem as the first one: members are part of the interface and a new one: struct literals are impossible if opCall is defined (if I am not mistaken).
May 01 2012
parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Wednesday, May 02, 2012 07:17:20 Maxim Fomin wrote:
 On Wednesday, 2 May 2012 at 03:38:41 UTC, Adam D. Ruppe wrote:
 On Wednesday, 2 May 2012 at 03:22:02 UTC, Andrei Alexandrescu
 
 wrote:
 One feature to remove stands out - the struct initialization:
 S s = { 1, 2 };
I could live without that one, because D has an alternative: auto s = S(1, 2);
It has the same problem as the first one: members are part of the interface and a new one: struct literals are impossible if opCall is defined (if I am not mistaken).
Yes, members are part of the interface, but if {1, 2} isn't legal, then their order isn't part of the interface as far as constructing the object is concerned (the memory layout is, so low-level stuff could still be broken by swapping or adding member variables, but the construction doesn't have to stop working like it does with a C struct literal). And defining opCall shouldn't have any effect on S(1, 2). S(1, 2) is clearly calling the constructor. The only reason that you would have a conflict is if you also defined a static opCall which conflicted. If a non-static opCall has _any_ effect on S(1, 2), then it's a bug. - Jonathan M Davis
May 01 2012
prev sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 5/1/12 11:38 PM, Adam D. Ruppe wrote:
 On Wednesday, 2 May 2012 at 03:22:02 UTC, Andrei Alexandrescu wrote:
 One feature to remove stands out - the struct initialization:
 S s = { 1, 2 };
I could live without that one, because D has an alternative: auto s = S(1, 2); And I'd be sad if you took that out, as I use it a lot, especially for trivial types: struct Html { string src; } struct Text { string src; } struct Point { int x; int y; } struct Size { int width; int height; } which I like because then we can use the types for overloading, static checks, etc., and it is very very simple to drop in and use. I guess there could be opCalls or constructors, but poo, it works now without that and I like it.
Well, so probably we shouldn't remove that feature either :o). Andrei
May 02 2012
prev sibling next sibling parent reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 5/2/12, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:
 struct S { int x, y; }
 S s = { 1, 2 };

  I think we should remove
 this feature.
But not this, right: S s = { x : 1, y : 2 }; ?
May 01 2012
parent "SomeDude" <lovelydear mailmetrash.com> writes:
On Wednesday, 2 May 2012 at 05:25:40 UTC, Andrej Mitrovic wrote:
 On 5/2/12, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> 
 wrote:
 struct S { int x, y; }
 S s = { 1, 2 };

  I think we should remove
 this feature.
But not this, right: S s = { x : 1, y : 2 }; ?
Yes, these are named parameters. Andrei's point could be made for just about everything that takes two (or more) consecutive integers, like a function signature, so I think it's a bit moot. Unfortunately, only named parameters can solve this problem, but then comes the problem of accepting both order of parameters and named parameters at the same time...
May 01 2012
prev sibling parent reply "bearophile" <bearophileHUGS lycos.com> writes:
Andrei Alexandrescu:

 It's a bit inappropriate to bind Walter to such a social 
 contract upon having asked an informal question.
Those comments weren't required, but they improve the quality of this community. So it's work and time well spent. Every person attracted to work on D development is a chance to increase significantly the development speed.
 FWIW there is little agreement among answers.
Right, but a thread like this is comparable to the first phase of a Brainstorming process, where ideas are produced freely, where agreement is not required. Later there is a phase of selection, that needs to be based on the quality of the single ideas; because technology/science decisions can't be based (too much) on popularity.
 Eliminating today's semantics of comma inevitably underlies the 
 hope that it can be retrofitted for something else, which I 
 think is near impossible without changing semantics of working 
 code.
Removing/restricting the usage of the comma operator is probably able to avoid some bugs (and increase syntax uniformity in D code written by different programmers), so it has a usefulness even if later they are not used for tuple syntax. How much important such bugs are, is a judgement.
 One feature to remove stands out - the struct initialization:

 struct S { int x, y; }
 S s = { 1, 2 };

 This, was noted, makes the order of members effectively part of 
 the struct's interface, which is subtly dangerous. I think we 
 should remove this feature.
It's a partially redundant feature, and it's able to introduce some long-term rigidity in the code. On the other hand when you have to write many struct literals, nested inside other literals of different structs, repeating the names introduces a bit of extra redundant code. Thank you for the answers, bye, bearophile
May 02 2012
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 5/2/12 7:52 AM, bearophile wrote:
 Andrei Alexandrescu:
 FWIW there is little agreement among answers.
Right, but a thread like this is comparable to the first phase of a Brainstorming process, where ideas are produced freely, where agreement is not required.
Sorry, here I meant "agreement" in the statistical sense, i.e. there's not a lot of clear collection of features we should remove; for most features that some wanted to get rid of, others had gainful uses. Andrei
May 02 2012
prev sibling next sibling parent "Paulo Pinto" <pjmlp progtools.org> writes:
I would say  many of the discussion items are to be fixed in a D version 
"break the
world" to be done when D finally becomes famous, similar to Python 3000 
plans.

Until then the focus should be in fixing the open bugs, deviations to the 
TDPL, and
improving available tools and frameworks.

What is the point of having a perfect systems programming language if no one 
uses it?

--
Paulo


"bearophile"  wrote in message news:tfbtvfccnxluzbuxofot forum.dlang.org...

Walter:

 What's your list?
This thread now has something like 240 answers (and probably few more will come), and despite some variability in the answers, we have seen several recurring patterns too. So what are the conclusions, take-home insights, and the to-do's to make something in practice, from Walter & Andrei? Bye, bearophile
Apr 30 2012
prev sibling next sibling parent reply =?UTF-8?B?QWxleCBSw7hubmUgUGV0ZXJzZW4=?= <xtzgzorex gmail.com> writes:
On 30-04-2012 01:41, bearophile wrote:
 Walter:

 What's your list?
This thread now has something like 240 answers (and probably few more will come), and despite some variability in the answers, we have seen several recurring patterns too. So what are the conclusions, take-home insights, and the to-do's to make something in practice, from Walter & Andrei? Bye, bearophile
I think the one thing there is universal agreement on is that the comma operator has to go. -- - Alex
Apr 30 2012
parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Mon, Apr 30, 2012 at 05:26:15PM +0200, Alex Rønne Petersen wrote:
 On 30-04-2012 01:41, bearophile wrote:
Walter:

What's your list?
This thread now has something like 240 answers (and probably few more will come), and despite some variability in the answers, we have seen several recurring patterns too. So what are the conclusions, take-home insights, and the to-do's to make something in practice, from Walter & Andrei?
[...]
 I think the one thing there is universal agreement on is that the
 comma operator has to go.
[...] +1. Let's rid the comma operator of its miserable existence. T -- Computers aren't intelligent; they only think they are.
Apr 30 2012
prev sibling parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Sun, Apr 29, 2012 at 11:55:43PM -0700, Jonathan M Davis wrote:
[...]
 Honestly, I don't think that you _can_ take much from this thread
 other than the fact that pretty _every_ feature is wanted and used by
 someone, even if other people hate it. Pretty much every feature
 listed as undesirable by someone was listed as desirable by someone
 else.
[...] So far, I've not seen a single response in favor of keeping the comma operator. T -- Give a man a fish, and he eats once. Teach a man to fish, and he will sit forever.
Apr 30 2012
next sibling parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
On Monday, 30 April 2012 at 15:35:19 UTC, H. S. Teoh wrote:
 So far, I've not seen a single response in favor of keeping the 
 comma operator.
I kinda like having it....
Apr 30 2012
parent "Maxim Fomin" <maxim maxim-fomin.ru> writes:
On Monday, 30 April 2012 at 15:38:32 UTC, Adam D. Ruppe wrote:
 On Monday, 30 April 2012 at 15:35:19 UTC, H. S. Teoh wrote:
 So far, I've not seen a single response in favor of keeping 
 the comma operator.
I kinda like having it....
I too and I am afraid that disallowing it would result that something would be broken.
Apr 30 2012
prev sibling next sibling parent reply "Peter Alexander" <peter.alexander.au gmail.com> writes:
On Monday, 30 April 2012 at 15:35:19 UTC, H. S. Teoh wrote:
 So far, I've not seen a single response in favor of keeping the 
 comma
 operator.
Very few want it, but as a practicality, it would be unwise to remove it (would break an awful lot of code).
Apr 30 2012
parent deadalnix <deadalnix gmail.com> writes:
Le 30/04/2012 18:13, Peter Alexander a écrit :
 On Monday, 30 April 2012 at 15:35:19 UTC, H. S. Teoh wrote:
 So far, I've not seen a single response in favor of keeping the comma
 operator.
Very few want it, but as a practicality, it would be unwise to remove it (would break an awful lot of code).
Some have proposed that comma operator could create tuples. If void members in tuples are automagically skipped, this won't break that many code. A first step in that direction would be to deprecate comma expression where expressions before the last one have not type void.
Apr 30 2012
prev sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 04/30/2012 05:36 PM, H. S. Teoh wrote:
 On Sun, Apr 29, 2012 at 11:55:43PM -0700, Jonathan M Davis wrote:
 [...]
 Honestly, I don't think that you _can_ take much from this thread
 other than the fact that pretty _every_ feature is wanted and used by
 someone, even if other people hate it. Pretty much every feature
 listed as undesirable by someone was listed as desirable by someone
 else.
[...] So far, I've not seen a single response in favor of keeping the comma operator. T
I think I use it about every 60 lines of code. Also, I don't think it should be removed for the sake of removing it. If it is removed, the syntax should be reused.
Apr 30 2012
next sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 04/30/2012 08:46 PM, Timon Gehr wrote:
 On 04/30/2012 05:36 PM, H. S. Teoh wrote:
 On Sun, Apr 29, 2012 at 11:55:43PM -0700, Jonathan M Davis wrote:
 [...]
 Honestly, I don't think that you _can_ take much from this thread
 other than the fact that pretty _every_ feature is wanted and used by
 someone, even if other people hate it. Pretty much every feature
 listed as undesirable by someone was listed as desirable by someone
 else.
[...] So far, I've not seen a single response in favor of keeping the comma operator. T
I think I use it about every 60 lines of code.
(outside for)
 Also, I don't think it
 should be removed for the sake of removing it. If it is removed, the
 syntax should be reused.
Apr 30 2012
prev sibling next sibling parent "David Nadlinger" <see klickverbot.at> writes:
On Monday, 30 April 2012 at 18:46:02 UTC, Timon Gehr wrote:
 On 04/30/2012 05:36 PM, H. S. Teoh wrote:
 So far, I've not seen a single response in favor of keeping 
 the comma
 operator.
I think I use it about every 60 lines of code. Also, I don't think it should be removed for the sake of removing it. If it is removed, the syntax should be reused.
Care to show some examples? David
Apr 30 2012
prev sibling next sibling parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Mon, Apr 30, 2012 at 08:46:02PM +0200, Timon Gehr wrote:
 On 04/30/2012 05:36 PM, H. S. Teoh wrote:
[...]
So far, I've not seen a single response in favor of keeping the comma
operator.
[...]
 I think I use it about every 60 lines of code. Also, I don't think it
 should be removed for the sake of removing it. If it is removed, the
 syntax should be reused.
We already have a reuse waiting in the line up, for a looong time. Native tuple syntax. T -- Doubtless it is a good thing to have an open mind, but a truly open mind should be open at both ends, like the food-pipe, with the capacity for excretion as well as absorption. -- Northrop Frye
Apr 30 2012
prev sibling parent reply "bearophile" <bearophileHUGS lycos.com> writes:
Timon Gehr:

 I think I use it about every 60 lines of code. Also, I don't 
 think it should be removed for the sake of removing it. If it 
 is removed, the syntax should be reused.
Commas do cause some bugs, so maybe they are worth restricting (further) even if their syntax doesn't get reused. Bye, bearophile
Apr 30 2012
parent reply deadalnix <deadalnix gmail.com> writes:
Le 30/04/2012 22:44, bearophile a écrit :
 Timon Gehr:

 I think I use it about every 60 lines of code. Also, I don't think it
 should be removed for the sake of removing it. If it is removed, the
 syntax should be reused.
Commas do cause some bugs, so maybe they are worth restricting (further) even if their syntax doesn't get reused. Bye, bearophile
+1 Looking for a , instead of a ; is really painful. It doesn't occur often, but when it does, you remember it for quite a long time.
Apr 30 2012
parent "David Nadlinger" <see klickverbot.at> writes:
On Monday, 30 April 2012 at 22:04:16 UTC, deadalnix wrote:
 Looking for a , instead of a ; is really painful. It doesn't 
 occur often, but when it does, you remember it for quite a long 
 time.
Also consider that at least on many European keyboard layouts, ',' and ';' share the same key… David
Apr 30 2012
prev sibling next sibling parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On Sunday, April 29, 2012 19:37:50 H. S. Teoh wrote:
 On Sun, Apr 29, 2012 at 08:42:23PM +0200, Andrej Mitrovic wrote:
 On 4/29/12, Jacob Carlborg <doob me.com> wrote:
 In principle I agree with you. But in practice this doesn't always
 work.  Take this for example: Prints "0" and "1" as expected. If we
 now change "point" to a property like this: It will now print "0"
 and "0". This is a silently breaking change. Sure you can change
 "point" to return by reference..
This is a great point and an issue I've ran into and talked about before. The compiler really ought to try and convert a call like this: foo.property++; foo.property+=10; into e.g.: foo.property = foo.property.opAdd(1); foo.property = foo.property.opAdd(10); It would make for some really nice APIs if this feature was available.
[...] To me, the compiler needs to be fixed so that anytime the return value of a property is used as an lvalue, it should always try to call the setter function, or some kind of setter function, instead of the getter (unless there's no setter, in which case it's OK to call the getter). I chalk this up to a compiler issue, not a language issue.
Well, it's both really. If the language spec was exact enough, it would say _exactly_ what the correct behavior is here, in which case, either the compiler is currently doing the right thing or it's not, depending on the spec. But the spec isn't that exact, so in some respects, the compiler _is_ the spec. Certainly, the way that this behaves in the language right now is a matter of how the compiler behaves. Ideally though, there would be zero difference between using a property and a public member variable save for taking its address (which should probably just be illegal for property functions). I've been tempted to add an enhancement request for putting property on public member variables to make it so that anything which would would break code if it were switched to a property function wouldn't be legal (such as taking its address). Unfortunately, right now that would include stuff like ++. - Jonathan M Davis
Apr 29 2012
parent reply Jacob Carlborg <doob me.com> writes:
On 2012-04-30 04:41, Jonathan M Davis wrote:

 Ideally though, there would be zero difference between using a property and a
 public member variable save for taking its address (which should probably just
 be illegal for  property functions). I've been tempted to add an enhancement
 request for putting  property on public member variables to make it so that
 anything which would would break code if it were switched to a property
 function wouldn't be legal (such as taking its address). Unfortunately, right
 now that would include stuff like ++.

 - Jonathan M Davis
I would rather have property on instance variables be a syntax sugar for implementing property functions. Basically virtual instance variables. -- /Jacob Carlborg
Apr 30 2012
parent reply =?UTF-8?B?QWxleCBSw7hubmUgUGV0ZXJzZW4=?= <xtzgzorex gmail.com> writes:
On 30-04-2012 09:58, Jacob Carlborg wrote:
 On 2012-04-30 04:41, Jonathan M Davis wrote:

 Ideally though, there would be zero difference between using a
 property and a
 public member variable save for taking its address (which should
 probably just
 be illegal for  property functions). I've been tempted to add an
 enhancement
 request for putting  property on public member variables to make it so
 that
 anything which would would break code if it were switched to a property
 function wouldn't be legal (such as taking its address).
 Unfortunately, right
 now that would include stuff like ++.

 - Jonathan M Davis
I would rather have property on instance variables be a syntax sugar for implementing property functions. Basically virtual instance variables.
Then there better be a way to mark them final too. ;) -- - Alex
Apr 30 2012
parent reply Jacob Carlborg <doob me.com> writes:
On 2012-04-30 17:27, Alex Rønne Petersen wrote:
 On 30-04-2012 09:58, Jacob Carlborg wrote:
 I would rather have  property on instance variables be a syntax sugar
 for implementing property functions. Basically virtual instance
 variables.
Then there better be a way to mark them final too. ;)
Then what's the point of having a method? Just use a public instance variable. -- /Jacob Carlborg
Apr 30 2012
parent reply =?UTF-8?B?QWxleCBSw7hubmUgUGV0ZXJzZW4=?= <xtzgzorex gmail.com> writes:
On 30-04-2012 21:43, Jacob Carlborg wrote:
 On 2012-04-30 17:27, Alex Rønne Petersen wrote:
 On 30-04-2012 09:58, Jacob Carlborg wrote:
 I would rather have  property on instance variables be a syntax sugar
 for implementing property functions. Basically virtual instance
 variables.
Then there better be a way to mark them final too. ;)
Then what's the point of having a method? Just use a public instance variable.
Encapsulation. I want contracts in my properties. -- - Alex
Apr 30 2012
parent Jacob Carlborg <doob me.com> writes:
On 2012-04-30 21:56, Alex Rønne Petersen wrote:
 On 30-04-2012 21:43, Jacob Carlborg wrote:
 On 2012-04-30 17:27, Alex Rønne Petersen wrote:
 On 30-04-2012 09:58, Jacob Carlborg wrote:
 I would rather have  property on instance variables be a syntax sugar
 for implementing property functions. Basically virtual instance
 variables.
Then there better be a way to mark them final too. ;)
Then what's the point of having a method? Just use a public instance variable.
Encapsulation. I want contracts in my properties.
Aha, didn't thin of that. Sure, why not. -- /Jacob Carlborg
May 01 2012
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Monday, April 30, 2012 07:46:48 Andrej Mitrovic wrote:
 On 4/30/12, Jonathan M Davis <jmdavisProg gmx.com> wrote:
 On Sunday, April 29, 2012 21:56:08 H. S. Teoh wrote:
 I wonder if dmd (or rdmd) should have a mode where it *only* compiles
 unittest code (i.e., no main() -- the resulting exe just runs unittests
 and nothing else).
For RDMD you can do: version(unittest) { } else void main() { // regular code here } And then you can invoke rdmd with --unittest and --main to insert an empty main function when unittesting. Personally I put in a stub main so I don't depend on rdmd features like --main: version(unittest) { void main(string[] args) { } } // stub main else void main() { // regular code here }
Yes, but that still compiles everything. It just gives you a convenient way to have a unit test executable separate from your normal executable. - Jonathan M Davis
Apr 29 2012
prev sibling next sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 4/28/2012 11:47 AM, Walter Bright wrote:
 Andrei and I had a fun discussion last night about this question. The idea was
 which features in D are redundant and/or do not add significant value?

 A couple already agreed upon ones are typedef and the cfloat, cdouble and creal
 types.

 What's your list?
This certainly seems to have become the biggest thread ever!
Apr 30 2012
next sibling parent Ary Manzana <ary esperanto.org.ar> writes:
On 5/1/12 2:24 AM, Walter Bright wrote:
 On 4/28/2012 11:47 AM, Walter Bright wrote:
 Andrei and I had a fun discussion last night about this question. The
 idea was
 which features in D are redundant and/or do not add significant value?

 A couple already agreed upon ones are typedef and the cfloat, cdouble
 and creal
 types.

 What's your list?
This certainly seems to have become the biggest thread ever!
Apr 30 2012
prev sibling next sibling parent "Eyyub" <eyyub.pangearaion gmail.com> writes:
On Monday, 30 April 2012 at 19:24:50 UTC, Walter Bright wrote:
 On 4/28/2012 11:47 AM, Walter Bright wrote:
 Andrei and I had a fun discussion last night about this 
 question. The idea was
 which features in D are redundant and/or do not add 
 significant value?

 A couple already agreed upon ones are typedef and the cfloat, 
 cdouble and creal
 types.

 What's your list?
This certainly seems to have become the biggest thread ever!
Yes, this is a very interesting discussion, even for a n00b like me ! (and even if i didn't understand everything)
Apr 30 2012
prev sibling parent reply "SomeDude" <lovelydear mailmetrash.com> writes:
On Monday, 30 April 2012 at 19:24:50 UTC, Walter Bright wrote:
 This certainly seems to have become the biggest thread ever!
What did you expect, really ? That people would say "nothing, the language is perfect" ? :D When I saw your question, I immediately thought "damn, Walter is starting a troll thread for fun, it's gonna be a huge waste of time". :D But then I changed my mind, because what I saw, - and that's what I expected actually -, is that almost everybody had a different list from other people. Which is in fact good, because that means that everybody uses his own subset of the language for his own use, and although there is a common ground, the union of all subsets seems to pretty much fill the "design space" of the language. In the end, very few "features" seem to be universally disdained (the comma operator seems to come regularly, though, but even that one has supporters). Which means to me that in terms of overall design, the language is not in a bad shape at all. So the design phase seems almost complete. The real effort now must be to finish the implementation, and build a full productive ecosystem. And I suppose we are still far from that goal.
Apr 30 2012
parent reply deadalnix <deadalnix gmail.com> writes:
Le 30/04/2012 22:52, SomeDude a écrit :
 In the end, very few "features" seem to be universally disdained (the
 comma operator seems to come regularly, though, but even that one has
 supporters). Which means to me that in terms of overall design, the
 language is not in a bad shape at all.
I wouldn't say supporter, but some people think it doesn't worth the cost of breaking code. BTW, you'll find lazy too.
Apr 30 2012
parent Timon Gehr <timon.gehr gmx.ch> writes:
On 05/01/2012 12:12 AM, deadalnix wrote:
 Le 30/04/2012 22:52, SomeDude a écrit :
 In the end, very few "features" seem to be universally disdained (the
 comma operator seems to come regularly, though, but even that one has
 supporters). Which means to me that in terms of overall design, the
 language is not in a bad shape at all.
I wouldn't say supporter, but some people think it doesn't worth the cost of breaking code. BTW, you'll find lazy too.
call by name is useful.
Apr 30 2012
prev sibling parent reply Don Clugston <dac nospam.com> writes:
On 28/04/12 20:47, Walter Bright wrote:
 Andrei and I had a fun discussion last night about this question. The
 idea was which features in D are redundant and/or do not add significant
 value?

 A couple already agreed upon ones are typedef and the cfloat, cdouble
 and creal types.

 What's your list?
Other ones which were agreed to a long time ago were: * NCEG operators * built-in .sort and .reverse ============================= About the NCEG operators -- the reason they're redundant is that you practically always want to treat NaN separately. I've tried _very_ hard to come up with uses for them, but without success. The thing I've used the most is: x !<>= x which is a kind of built-in isNaN(x), but that can also be rewritten as: x != x Initially I though you'd do things like real func(real x) { // x must be non-NaN and in the range -x.infinity .. N if (x !< N) return real.nan; but even that isn't convincing, because if x is NaN you should be returning x, so that you preserve NaN payloads. I think I have used these guys more than anyone else, but I still haven't found a single use case that stands up to scrutiny.
May 03 2012
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 5/3/12 9:55 AM, Don Clugston wrote:
 On 28/04/12 20:47, Walter Bright wrote:
 Andrei and I had a fun discussion last night about this question. The
 idea was which features in D are redundant and/or do not add significant
 value?

 A couple already agreed upon ones are typedef and the cfloat, cdouble
 and creal types.

 What's your list?
Other ones which were agreed to a long time ago were: * NCEG operators * built-in .sort and .reverse
Good ones. In fact I even discounted them from this discussion because I'd already considered them gone. Walter agreed that I don't mention them in TDPL, with the intent to have them peter out. One good step right now would be to remove NCEG operators from the online documentation. Later on, we'll consider them an accept-invalid bug :o). Andrei
May 03 2012
parent reply Don Clugston <dac nospam.com> writes:
On 03/05/12 16:13, Andrei Alexandrescu wrote:
 On 5/3/12 9:55 AM, Don Clugston wrote:
 On 28/04/12 20:47, Walter Bright wrote:
 Andrei and I had a fun discussion last night about this question. The
 idea was which features in D are redundant and/or do not add significant
 value?

 A couple already agreed upon ones are typedef and the cfloat, cdouble
 and creal types.

 What's your list?
Other ones which were agreed to a long time ago were: * NCEG operators * built-in .sort and .reverse
Good ones. In fact I even discounted them from this discussion because I'd already considered them gone. Walter agreed that I don't mention them in TDPL, with the intent to have them peter out. One good step right now would be to remove NCEG operators from the online documentation. Later on, we'll consider them an accept-invalid bug :o).
Well, they are also used in druntime, in core.stdc.math BTW I *hate* that module, I don't know why it exists. Even worse, it seems to be growing -- people are adding more things to it. Practically everything in there has a better implementation in std.math.
May 03 2012
next sibling parent reply =?ISO-8859-1?Q?Alex_R=F8nne_Petersen?= <xtzgzorex gmail.com> writes:
On 03-05-2012 17:13, Don Clugston wrote:
 On 03/05/12 16:13, Andrei Alexandrescu wrote:
 On 5/3/12 9:55 AM, Don Clugston wrote:
 On 28/04/12 20:47, Walter Bright wrote:
 Andrei and I had a fun discussion last night about this question. The
 idea was which features in D are redundant and/or do not add
 significant
 value?

 A couple already agreed upon ones are typedef and the cfloat, cdouble
 and creal types.

 What's your list?
Other ones which were agreed to a long time ago were: * NCEG operators * built-in .sort and .reverse
Good ones. In fact I even discounted them from this discussion because I'd already considered them gone. Walter agreed that I don't mention them in TDPL, with the intent to have them peter out. One good step right now would be to remove NCEG operators from the online documentation. Later on, we'll consider them an accept-invalid bug :o).
Well, they are also used in druntime, in core.stdc.math BTW I *hate* that module, I don't know why it exists. Even worse, it seems to be growing -- people are adding more things to it. Practically everything in there has a better implementation in std.math.
But not quite everything yet. When I tried to pure/nothrow/ safe-ify std.math[special], I eventually stumbled upon code that used core.stdc.math. It would definitely be nice if we could completely kill any dependency on that module, so we can actually make proper use of pure/nothrow/ safe, etc. -- - Alex
May 03 2012
parent Sean Kelly <sean invisibleduck.org> writes:
On May 3, 2012, at 9:58 AM, Alex R=F8nne Petersen wrote:

 On 03-05-2012 17:13, Don Clugston wrote:
=20
=20
 Well, they are also used in druntime, in core.stdc.math
=20
 BTW I *hate* that module, I don't know why it exists. Even worse, it
 seems to be growing -- people are adding more things to it.
 Practically everything in there has a better implementation in =
std.math.
=20
 But not quite everything yet. When I tried to pure/nothrow/ safe-ify =
std.math[special], I eventually stumbled upon code that used = core.stdc.math.
=20
 It would definitely be nice if we could completely kill any dependency =
on that module, so we can actually make proper use of = pure/nothrow/ safe, etc. I've always thought use of core.stdc as an indicator for things that = should be added to Phobos. Really, core.stdc should only be used by = apps ported from C to D, not by apps written from scratch in D.=
May 03 2012
prev sibling next sibling parent reply Sean Kelly <sean invisibleduck.org> writes:
On May 3, 2012, at 8:13 AM, Don Clugston wrote:

 On 03/05/12 16:13, Andrei Alexandrescu wrote:
=20
=20
 Good ones. In fact I even discounted them from this discussion =
because
 I'd already considered them gone. Walter agreed that I don't mention
 them in TDPL, with the intent to have them peter out.
=20
 One good step right now would be to remove NCEG operators from the
 online documentation. Later on, we'll consider them an accept-invalid
 bug :o).
=20 Well, they are also used in druntime, in core.stdc.math =20 BTW I *hate* that module, I don't know why it exists. Even worse, it =
seems to be growing -- people are adding more things to it.
 Practically everything in there has a better implementation in =
std.math. core.stdc.math corresponds to C99's math.h and is there as a part of the = standard C interface. It should only contain the required C99 = prototypes, and in some cases functions if the C implementation is a = macro. If there is anything nonstandard in there, I'm not aware of it.=
May 03 2012
parent reply Don <nospam nospam.com> writes:
On 03.05.2012 21:08, Sean Kelly wrote:
 On May 3, 2012, at 8:13 AM, Don Clugston wrote:

 On 03/05/12 16:13, Andrei Alexandrescu wrote:
 Good ones. In fact I even discounted them from this discussion because
 I'd already considered them gone. Walter agreed that I don't mention
 them in TDPL, with the intent to have them peter out.

 One good step right now would be to remove NCEG operators from the
 online documentation. Later on, we'll consider them an accept-invalid
 bug :o).
Well, they are also used in druntime, in core.stdc.math BTW I *hate* that module, I don't know why it exists. Even worse, it seems to be growing -- people are adding more things to it. Practically everything in there has a better implementation in std.math.
core.stdc.math corresponds to C99's math.h and is there as a part of the standard C interface. It should only contain the required C99 prototypes, and in some cases functions if the C implementation is a macro. If there is anything nonstandard in there, I'm not aware of it.
Yes, but why do we have it? We're not C. Some of the std C functions aren't implemented correctly (especially the FreeBSD long double functions, which are completely wrong). And that shouldn't be D's problem. Even when they are, they're not pure nothrow, and sometimes they have really silly names (I'm looking at you, tgamma() ) Quite absurdly, the DMC gamma function is a port from the D version. Why include it twice??
May 03 2012
next sibling parent reply Sean Kelly <sean invisibleduck.org> writes:
On May 3, 2012, at 1:11 PM, Don wrote:

 On 03.05.2012 21:08, Sean Kelly wrote:
 On May 3, 2012, at 8:13 AM, Don Clugston wrote:
=20
 On 03/05/12 16:13, Andrei Alexandrescu wrote:
=20
=20
 Good ones. In fact I even discounted them from this discussion =
because
 I'd already considered them gone. Walter agreed that I don't =
mention
 them in TDPL, with the intent to have them peter out.
=20
 One good step right now would be to remove NCEG operators from the
 online documentation. Later on, we'll consider them an =
accept-invalid
 bug :o).
=20 Well, they are also used in druntime, in core.stdc.math =20 BTW I *hate* that module, I don't know why it exists. Even worse, it =
seems to be growing -- people are adding more things to it.
 Practically everything in there has a better implementation in =
std.math.
=20
 core.stdc.math corresponds to C99's math.h and is there as a part of =
the standard C interface. It should only contain the required C99 = prototypes, and in some cases functions if the C implementation is a = macro. If there is anything nonstandard in there, I'm not aware of it.
=20
 Yes, but why do we have it? We're not C.
Mostly because it was handy to fall back on the C API before Phobos was = so well fleshed-out. Today, I think it mostly exists to ease porting of = C apps.=
May 03 2012
parent reply deadalnix <deadalnix gmail.com> writes:
Le 03/05/2012 22:43, Sean Kelly a écrit :
 On May 3, 2012, at 1:11 PM, Don wrote:

 On 03.05.2012 21:08, Sean Kelly wrote:
 On May 3, 2012, at 8:13 AM, Don Clugston wrote:

 On 03/05/12 16:13, Andrei Alexandrescu wrote:
 Good ones. In fact I even discounted them from this discussion because
 I'd already considered them gone. Walter agreed that I don't mention
 them in TDPL, with the intent to have them peter out.

 One good step right now would be to remove NCEG operators from the
 online documentation. Later on, we'll consider them an accept-invalid
 bug :o).
Well, they are also used in druntime, in core.stdc.math BTW I *hate* that module, I don't know why it exists. Even worse, it seems to be growing -- people are adding more things to it. Practically everything in there has a better implementation in std.math.
core.stdc.math corresponds to C99's math.h and is there as a part of the standard C interface. It should only contain the required C99 prototypes, and in some cases functions if the C implementation is a macro. If there is anything nonstandard in there, I'm not aware of it.
Yes, but why do we have it? We're not C.
Mostly because it was handy to fall back on the C API before Phobos was so well fleshed-out. Today, I think it mostly exists to ease porting of C apps.
So they probably belongs to deimos.
May 03 2012
parent reply Sean Kelly <sean invisibleduck.org> writes:
On May 3, 2012, at 2:16 PM, deadalnix <deadalnix gmail.com> wrote:

 Le 03/05/2012 22:43, Sean Kelly a =C3=A9crit :
 On May 3, 2012, at 1:11 PM, Don wrote:
=20
 On 03.05.2012 21:08, Sean Kelly wrote:
 On May 3, 2012, at 8:13 AM, Don Clugston wrote:
=20
 On 03/05/12 16:13, Andrei Alexandrescu wrote:
=20
=20
 Good ones. In fact I even discounted them from this discussion becaus=
e
 I'd already considered them gone. Walter agreed that I don't mention
 them in TDPL, with the intent to have them peter out.
=20
 One good step right now would be to remove NCEG operators from the
 online documentation. Later on, we'll consider them an accept-invalid=
 bug :o).
=20 Well, they are also used in druntime, in core.stdc.math =20 BTW I *hate* that module, I don't know why it exists. Even worse, it s=
eems to be growing -- people are adding more things to it.
 Practically everything in there has a better implementation in std.mat=
h.
=20
 core.stdc.math corresponds to C99's math.h and is there as a part of th=
e standard C interface. It should only contain the required C99 prototypes,= and in some cases functions if the C implementation is a macro. If there i= s anything nonstandard in there, I'm not aware of it.
=20
 Yes, but why do we have it? We're not C.
=20 Mostly because it was handy to fall back on the C API before Phobos was s=
o well fleshed-out. Today, I think it mostly exists to ease porting of C ap= ps.
=20
 So they probably belongs to deimos.
Except that they're used by druntime, both explicitly and publicly imported b= y core.sys.posix.=20=
May 03 2012
parent reply deadalnix <deadalnix gmail.com> writes:
Le 04/05/2012 02:03, Sean Kelly a écrit :
 On May 3, 2012, at 2:16 PM, deadalnix<deadalnix gmail.com>  wrote:

 Le 03/05/2012 22:43, Sean Kelly a écrit :
 On May 3, 2012, at 1:11 PM, Don wrote:

 On 03.05.2012 21:08, Sean Kelly wrote:
 On May 3, 2012, at 8:13 AM, Don Clugston wrote:

 On 03/05/12 16:13, Andrei Alexandrescu wrote:
 Good ones. In fact I even discounted them from this discussion because
 I'd already considered them gone. Walter agreed that I don't mention
 them in TDPL, with the intent to have them peter out.

 One good step right now would be to remove NCEG operators from the
 online documentation. Later on, we'll consider them an accept-invalid
 bug :o).
Well, they are also used in druntime, in core.stdc.math BTW I *hate* that module, I don't know why it exists. Even worse, it seems to be growing -- people are adding more things to it. Practically everything in there has a better implementation in std.math.
core.stdc.math corresponds to C99's math.h and is there as a part of the standard C interface. It should only contain the required C99 prototypes, and in some cases functions if the C implementation is a macro. If there is anything nonstandard in there, I'm not aware of it.
Yes, but why do we have it? We're not C.
Mostly because it was handy to fall back on the C API before Phobos was so well fleshed-out. Today, I think it mostly exists to ease porting of C apps.
So they probably belongs to deimos.
Except that they're used by druntime, both explicitly and publicly imported by core.sys.posix.
I may scare people here, but as Deimos is only declaration, I see no problem to use a deimos header in druntime.
May 06 2012
parent Walter Bright <newshound2 digitalmars.com> writes:
On 5/6/2012 8:09 AM, deadalnix wrote:
 I may scare people here, but as Deimos is only declaration, I see no problem to
 use a deimos header in druntime.
I do, because it adds another dependency on something not in the main download.
May 06 2012
prev sibling parent "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Thursday, May 03, 2012 13:43:11 Sean Kelly wrote:
 On May 3, 2012, at 1:11 PM, Don wrote:
 On 03.05.2012 21:08, Sean Kelly wrote:
 On May 3, 2012, at 8:13 AM, Don Clugston wrote:
 On 03/05/12 16:13, Andrei Alexandrescu wrote:
 Good ones. In fact I even discounted them from this discussion because
 I'd already considered them gone. Walter agreed that I don't mention
 them in TDPL, with the intent to have them peter out.
 
 One good step right now would be to remove NCEG operators from the
 online documentation. Later on, we'll consider them an accept-invalid
 bug :o).
Well, they are also used in druntime, in core.stdc.math BTW I *hate* that module, I don't know why it exists. Even worse, it seems to be growing -- people are adding more things to it. Practically everything in there has a better implementation in std.math.>>
core.stdc.math corresponds to C99's math.h and is there as a part of the standard C interface. It should only contain the required C99 prototypes, and in some cases functions if the C implementation is a macro. If there is anything nonstandard in there, I'm not aware of it.>
Yes, but why do we have it? We're not C.
Mostly because it was handy to fall back on the C API before Phobos was so well fleshed-out. Today, I think it mostly exists to ease porting of C apps.
In principle, having prototypes for the entire standard C library in druntime seems like a good idea to me. In practice though, it could cause problems due to people using the C functions rather than the D functions for some things (e.g. the math functions). If we properly documented them all though, we could then put comments about the correct D function to use to replace each C function which has a D replacement, and then it could actually help people move away from the C functions. - Jonathan M Davis
May 03 2012
prev sibling next sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 5/3/2012 8:13 AM, Don Clugston wrote:
 Well, they are also used in druntime, in core.stdc.math
 BTW I *hate* that module, I don't know why it exists. Even worse, it seems to
be
 growing -- people are adding more things to it.
It's there simply because all the Standard C headers should be represented. It should not get anything that is not in Standard C. Ditto for all the other stuff in core.stdc. It's there to make converting C code to D code easier.
 Practically everything in there has a better implementation in std.math.
Yup. But also note that the only "implementations" in there are things that are done as macros in C's math.h, meaning they're trivial.
May 03 2012
next sibling parent reply "foobar" <foo bar.com> writes:
On Thursday, 3 May 2012 at 22:57:02 UTC, Walter Bright wrote:
 On 5/3/2012 8:13 AM, Don Clugston wrote:
 Well, they are also used in druntime, in core.stdc.math
 BTW I *hate* that module, I don't know why it exists. Even 
 worse, it seems to be
 growing -- people are adding more things to it.
It's there simply because all the Standard C headers should be represented. It should not get anything that is not in Standard C. Ditto for all the other stuff in core.stdc. It's there to make converting C code to D code easier.
This argument comes up every once in a while even though AFAIK it is *not* a goal of D and never has been! D does not and *should not* strive to be source compatible with C. We already have C++ for that and it is a horrible idea. D can link with C which allows to use pre-existing C code. we should *not* encourage converting C code to D code at all. Either just link the C code or use D idiomatic code. IMO C headers should be moved to Deimos, and should be clearly documented that their intended purpose is to _link_ D code with the C runtime.
May 06 2012
parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On Sunday, May 06, 2012 21:18:38 foobar wrote:
 On Thursday, 3 May 2012 at 22:57:02 UTC, Walter Bright wrote:
 On 5/3/2012 8:13 AM, Don Clugston wrote:
 Well, they are also used in druntime, in core.stdc.math
 BTW I *hate* that module, I don't know why it exists. Even
 worse, it seems to be
 growing -- people are adding more things to it.
It's there simply because all the Standard C headers should be represented. It should not get anything that is not in Standard C. Ditto for all the other stuff in core.stdc. It's there to make converting C code to D code easier.
This argument comes up every once in a while even though AFAIK it is *not* a goal of D and never has been! D does not and *should not* strive to be source compatible with C. We already have C++ for that and it is a horrible idea. D can link with C which allows to use pre-existing C code. we should *not* encourage converting C code to D code at all. Either just link the C code or use D idiomatic code.
Then you misunderstand. One of the tenets that D holds to is that any C/C++ code either compiles as valid D code with identical semantics, or it doesn't compile as D code (there are a few minor exceptions - such as static arrays being passed by value - but not many). This means that we can break compatibility with C/C++ and do our own thing for a lot of stuff but that we can't just redefine what stuff does such that it would silently break code when it's ported from C/C++ to D. That approach is _very_ different from C++'s approach where valid C code pretty much _always_ compiles identically in C++ (the fact that C++ added keywords being the only exception that I can think of at the moment), but that doesn't mean that we don't care about code portability from C/C++ to D. There's a huge difference between designing a language such that porting code to it from another language isn't error-prone and making the new language source compatibile. D does the former. C++ does the latter. Being able to port code from C/C++ to D without having to worry about silent breakage _is_ one of D's goals. - Jonathan M Davis
May 06 2012
next sibling parent reply =?UTF-8?B?QWxleCBSw7hubmUgUGV0ZXJzZW4=?= <xtzgzorex gmail.com> writes:
On 07-05-2012 00:06, Jonathan M Davis wrote:
 On Sunday, May 06, 2012 21:18:38 foobar wrote:
 On Thursday, 3 May 2012 at 22:57:02 UTC, Walter Bright wrote:
 On 5/3/2012 8:13 AM, Don Clugston wrote:
 Well, they are also used in druntime, in core.stdc.math
 BTW I *hate* that module, I don't know why it exists. Even
 worse, it seems to be
 growing -- people are adding more things to it.
It's there simply because all the Standard C headers should be represented. It should not get anything that is not in Standard C. Ditto for all the other stuff in core.stdc. It's there to make converting C code to D code easier.
This argument comes up every once in a while even though AFAIK it is *not* a goal of D and never has been! D does not and *should not* strive to be source compatible with C. We already have C++ for that and it is a horrible idea. D can link with C which allows to use pre-existing C code. we should *not* encourage converting C code to D code at all. Either just link the C code or use D idiomatic code.
Then you misunderstand. One of the tenets that D holds to is that any C/C++ code either compiles as valid D code with identical semantics, or it doesn't compile as D code (there are a few minor exceptions - such as static arrays being passed by value - but not many). This means that we can break compatibility with C/C++ and do our own thing for a lot of stuff but that we can't just redefine what stuff does such that it would silently break code when it's ported from C/C++ to D.
So basically, language design advances on our front have to be hindered by some kind of compatibility that has *very* questionable usefulness. I have never copy/pasted C/C++ code into D. Ever. Even when making bindings, I type declarations out manually to be completely sure I get them right. This is like when C++ tried to be source compatible with C. In practice, nearly no one just took a C source base and compiled it as C++ and called it a day, because of two reasons: 1) C++ wasn't actually source compatible enough so that this would just be a tiny build system change, 2) there would be zero gain in doing it. I haven't ever copy/pasted C code into C++ either, now that I think about it. I don't think you're going to see people port their large C source bases to D just for the sake of doing it. I think, rather, you'll see them write bindings because that's the more pragmatic and time-efficient approach. BTW, if we're so focused on C/C++ source compatibility, what about the unfortunate D1 folks? We seem to largely not care about source compatibility for their code at all. Seems like our priorities are quite skewed.
 That approach is _very_ different from C++'s approach where valid C code pretty
 much _always_ compiles identically in C++ (the fact that C++ added keywords
 being the only exception that I can think of at the moment), but that doesn't
 mean that we don't care about code portability from C/C++ to D. There's a huge
 difference between designing a language such that porting code to it from
 another language isn't error-prone and making the new language source
 compatibile. D does the former. C++ does the latter.
http://en.wikipedia.org/wiki/Compatibility_of_C_and_C%2B%2B We probably have many of the incompatibilities mentioned there too.
 Being able to port code from C/C++ to D without having to worry about silent
 breakage _is_ one of D's goals.

 - Jonathan M Davis
-- - Alex
May 06 2012
next sibling parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On Monday, May 07, 2012 07:48:05 Alex R=C3=B8nne Petersen wrote:
 On 07-05-2012 00:06, Jonathan M Davis wrote:
 On Sunday, May 06, 2012 21:18:38 foobar wrote:
 On Thursday, 3 May 2012 at 22:57:02 UTC, Walter Bright wrote:
 On 5/3/2012 8:13 AM, Don Clugston wrote:
 Well, they are also used in druntime, in core.stdc.math
 BTW I *hate* that module, I don't know why it exists. Even
 worse, it seems to be
 growing -- people are adding more things to it.
=20 It's there simply because all the Standard C headers should be represented. It should not get anything that is not in Standard C. Ditto for all the other stuff in core.stdc. =20 It's there to make converting C code to D code easier.
=20 This argument comes up every once in a while even though AFAIK it is *not* a goal of D and never has been! D does not and *should not* strive to be source compatible with C. We already have C++ for that and it is a horrible idea. D can link with C which allows to use pre-existing C code. we should *not* encourage converting C code to D code at all. Either just link the C code or use D idiomatic code.
=20 Then you misunderstand. One of the tenets that D holds to is that a=
ny
 C/C++
 code either compiles as valid D code with identical semantics, or i=
t
 doesn't compile as D code (there are a few minor exceptions - such =
as
 static arrays being passed by value - but not many). This means tha=
t we
 can break compatibility with C/C++ and do our own thing for a lot o=
f
 stuff but that we can't just redefine what stuff does such that it =
would
 silently break code when it's ported from C/C++ to D.
=20 So basically, language design advances on our front have to be hinder=
ed
 by some kind of compatibility that has *very* questionable usefulness=
. I
 have never copy/pasted C/C++ code into D. Ever. Even when making
 bindings, I type declarations out manually to be completely sure I ge=
t
 them right.
=20
 This is like when C++ tried to be source compatible with C. In practi=
ce,
 nearly no one just took a C source base and compiled it as C++ and
 called it a day, because of two reasons: 1) C++ wasn't actually sourc=
e
 compatible enough so that this would just be a tiny build system chan=
ge,
 2) there would be zero gain in doing it. I haven't ever copy/pasted C=
 code into C++ either, now that I think about it.
=20
 I don't think you're going to see people port their large C source ba=
ses
 to D just for the sake of doing it. I think, rather, you'll see them
 write bindings because that's the more pragmatic and time-efficient
 approach.
We only require source compatibility so far as C/C++ code which compile= s as D=20 code needs to have the same semantics as it does in C/C++. This actuall= y=20 causes very few restrictions, because D's syntax differs enough that co= mpiling=20 C/C++ as D code breaks _very_ quickly. But by having that level of=20 compatability, we make it so that porting code from C/C++ (which people= _will_=20 do, even if the majority of D programmers don't) doesn't break silently= . The only place that I'm aware of where this policy has caused some prob= lems is=20 arithmetic and integral promotions. There a few cases where it would be= nice=20 to change the semantics for that, but for the most part, the C/C++ sema= ntics=20 are fine, and I'm sure that Walter considers whatever loss we get there= to be=20 worth the gain in making it so that C/C++ code ports to D without break= ing=20 silently. I really don't think that this level of compatibility with C/C++ has co= st us=20 much. As similar as D's syntax is, it differs in so many small ways, th= at C/C++=20 code quickly fails to compile as D code, and so the small level of=20 compatibility that we insist on doesn't affect much.
 BTW, if we're so focused on C/C++ source compatibility, what about th=
e
 unfortunate D1 folks? We seem to largely not care about source
 compatibility for their code at all. Seems like our priorities are qu=
ite
 skewed.
D was frozen as D1 when it was so that the folks using D for real work = could=20 continue to do so while major breakages continued to occur as the langu= age was=20 expanded and refined (in particular, const was going to be added, which= was=20 going to break a _lot_). It was _never_ intended that D2 be source comp= atible=20 with D1 or that D1 even stick around long term. It was merely a stable = branch=20 which was left around in order to let people continue to use the langua= ge for=20 real work while the main branch continued to be developed. In the long = run, D1=20 will be pretty much dead, while we'll still have to worry about people = porting=20 C/C++ code to D for pretty much forever. - Jonathan M Davis
May 06 2012
parent reply Jacob Carlborg <doob me.com> writes:
On 2012-05-07 08:03, Jonathan M Davis wrote:

 The only place that I'm aware of where this policy has caused some problems is
 arithmetic and integral promotions. There a few cases where it would be nice
 to change the semantics for that, but for the most part, the C/C++ semantics
 are fine, and I'm sure that Walter considers whatever loss we get there to be
 worth the gain in making it so that C/C++ code ports to D without breaking
 silently.
I had some problems with floats being default initialized to NaN. -- /Jacob Carlborg
May 07 2012
next sibling parent =?UTF-8?B?QWxleCBSw7hubmUgUGV0ZXJzZW4=?= <xtzgzorex gmail.com> writes:
On 07-05-2012 09:10, Jacob Carlborg wrote:
 On 2012-05-07 08:03, Jonathan M Davis wrote:

 The only place that I'm aware of where this policy has caused some
 problems is
 arithmetic and integral promotions. There a few cases where it would
 be nice
 to change the semantics for that, but for the most part, the C/C++
 semantics
 are fine, and I'm sure that Walter considers whatever loss we get
 there to be
 worth the gain in making it so that C/C++ code ports to D without
 breaking
 silently.
I had some problems with floats being default initialized to NaN.
I still think floats being initialized to NaN is an atrocity... -- - Alex
May 07 2012
prev sibling parent reply Andrew Wiley <wiley.andrew.j gmail.com> writes:
On Mon, May 7, 2012 at 2:10 AM, Jacob Carlborg <doob me.com> wrote:

 On 2012-05-07 08:03, Jonathan M Davis wrote:

  The only place that I'm aware of where this policy has caused some
 problems is
 arithmetic and integral promotions. There a few cases where it would be
 nice
 to change the semantics for that, but for the most part, the C/C++
 semantics
 are fine, and I'm sure that Walter considers whatever loss we get there
 to be
 worth the gain in making it so that C/C++ code ports to D without breaking
 silently.
I had some problems with floats being default initialized to NaN.
That's still correct behavior for C, actually. Using an uninitialized variable in C results in undefined behavior, so D still complies with C requirements when it initializes floats to NaN. I'm guessing there's more to it than that, though, because code that uses uninitialized floats was probably wrong to begin with.
May 07 2012
parent Jeff Nowakowski <jeff dilacero.org> writes:
On 05/07/2012 03:22 AM, Andrew Wiley wrote:
 I had some problems with floats being default initialized to NaN.
That's still correct behavior for C, actually. Using an uninitialized variable in C results in undefined behavior, so D still complies with C requirements when it initializes floats to NaN.
For variables with static storage, C initializes them by default to zero. It's in the spec.
May 07 2012
prev sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2012-05-07 07:48, Alex Rønne Petersen wrote:

 So basically, language design advances on our front have to be hindered
 by some kind of compatibility that has *very* questionable usefulness. I
 have never copy/pasted C/C++ code into D. Ever. Even when making
 bindings, I type declarations out manually to be completely sure I get
 them right.
I've created bindings for libclang, I did that by copy-pasting the C code and then some quick search-and-replace. Although this is the only library I manged to create bindings for this easy. -- /Jacob Carlborg
May 07 2012
parent reply =?UTF-8?B?QWxleCBSw7hubmUgUGV0ZXJzZW4=?= <xtzgzorex gmail.com> writes:
On 07-05-2012 09:07, Jacob Carlborg wrote:
 On 2012-05-07 07:48, Alex Rønne Petersen wrote:

 So basically, language design advances on our front have to be hindered
 by some kind of compatibility that has *very* questionable usefulness. I
 have never copy/pasted C/C++ code into D. Ever. Even when making
 bindings, I type declarations out manually to be completely sure I get
 them right.
I've created bindings for libclang, I did that by copy-pasting the C code and then some quick search-and-replace. Although this is the only library I manged to create bindings for this easy.
But declarations are very different from actual statements and expressions (I assume you mean declarations?). -- - Alex
May 07 2012
parent Jacob Carlborg <doob me.com> writes:
On 2012-05-07 09:09, Alex Rønne Petersen wrote:

 But declarations are very different from actual statements and
 expressions (I assume you mean declarations?).
That's true. Yes, declarations. -- /Jacob Carlborg
May 07 2012
prev sibling parent reply "foobar" <foo bar.com> writes:
On Sunday, 6 May 2012 at 22:06:32 UTC, Jonathan M Davis wrote:
 This argument comes up every once in a while even though AFAIK 
 it
 is *not* a goal of D and never has been!
 D does not and *should not* strive to be source compatible with
 C. We already have C++ for that and it is a horrible idea.
 D can link with C which allows to use pre-existing C code. we
 should *not* encourage converting C code to D code at all. 
 Either
 just link the C code or use D idiomatic code.
Then you misunderstand. One of the tenets that D holds to is that any C/C++ code either compiles as valid D code with identical semantics, or it doesn't compile as D code (there are a few minor exceptions - such as static arrays being passed by value - but not many). This means that we can break compatibility with C/C++ and do our own thing for a lot of stuff but that we can't just redefine what stuff does such that it would silently break code when it's ported from C/C++ to D. That approach is _very_ different from C++'s approach where valid C code pretty much _always_ compiles identically in C++ (the fact that C++ added keywords being the only exception that I can think of at the moment), but that doesn't mean that we don't care about code portability from C/C++ to D. There's a huge difference between designing a language such that porting code to it from another language isn't error-prone and making the new language source compatibile. D does the former. C++ does the latter. Being able to port code from C/C++ to D without having to worry about silent breakage _is_ one of D's goals. - Jonathan M Davis
I have a three main problems with the above: a. C++ is *not* fully source compatible with C, especially the latest C99 conflicts with C++ IIRC. b. D isn't either - there are already semantics changes compared to C, as you said so yourself, e.g. static arrays, default initialization of static floats, etc. c. If this is currently a goal of D it really shouldn't be - it prevents us from fixing design bugs we inherited from C such as implicit numeric coercions. As others said, the only thing that sort-of makes sense is to copy/paste *declarations* and even those are different enough in D that they deserve at least a look over to make sure they are correct. We shouldn't promote this "goal" at all especially given that it isn't even guarantied to be 100% correct in all cases. Really what we should be promoting is the fact that D is _link_ compatible with C and allows you to use existing C code _without_ porting it to D.
May 08 2012
next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 5/8/12, foobar <foo bar.com> wrote:
 a. C++ is *not* fully source compatible with C, especially the
 latest C99 conflicts with C++ IIRC.
Yeah there's a nice list in the C++ standard, Annex C.1 (C++ and ISO C). PDF: www-d0.fnal.gov/~dladams/cxx_standard.pdf
May 08 2012
prev sibling next sibling parent reply "bearophile" <bearophileHUGS lycos.com> writes:
foobar:

 As others said, the only thing that sort-of makes sense is to 
 copy/paste *declarations* and even those are different enough 
 in D that they deserve at least a look over to make sure they 
 are correct.

 We shouldn't promote this "goal" at all especially given that 
 it isn't even guarantied to be 100% correct in all cases.
 Really what we should be promoting is the fact that D is _link_ 
 compatible with C and allows you to use existing C code 
 _without_ porting it to D.
For various reasons I have translated many times routines, functions and other small and medium amounts of C code to D. And in many cases I have used the C std lib functions to circumvent bugs or limitations or performance problems of Phobos. In both cases I have found the C functions quite useful, so moving them into not built-in stuff is bad for me. The risk of using C functions by mistake is low enough. Bye, bearophile
May 08 2012
next sibling parent "Chris Cain" <clcain uncg.edu> writes:
On Tuesday, 8 May 2012 at 13:57:30 UTC, bearophile wrote:
 in many cases I have used the C std lib functions to circumvent
 bugs or limitations or performance problems of Phobos. In both
I tend to agree with the performance aspect. I just got done with a very challenging class where we solved programming contest style problems ... we got bonus points for the fastest solution (or solutions that could solve extended versions of the problems). It was extremely useful for me to be able to use the C versions of functions. Especially I/O because it made it significantly faster to do some things. That said, some of the things I was doing I would never advocate for being easy/possible with D's I/O.
May 08 2012
prev sibling parent reply "foobar" <foo bar.com> writes:
On Tuesday, 8 May 2012 at 13:57:30 UTC, bearophile wrote:
 foobar:

 As others said, the only thing that sort-of makes sense is to 
 copy/paste *declarations* and even those are different enough 
 in D that they deserve at least a look over to make sure they 
 are correct.

 We shouldn't promote this "goal" at all especially given that 
 it isn't even guarantied to be 100% correct in all cases.
 Really what we should be promoting is the fact that D is 
 _link_ compatible with C and allows you to use existing C code 
 _without_ porting it to D.
For various reasons I have translated many times routines, functions and other small and medium amounts of C code to D. And in many cases I have used the C std lib functions to circumvent bugs or limitations or performance problems of Phobos. In both cases I have found the C functions quite useful, so moving them into not built-in stuff is bad for me. The risk of using C functions by mistake is low enough. Bye, bearophile
That does not contradict what I said. No one stops you from _translating_ C/C++ code (or any other language for that matter) to D. You shouldn't however rely on _copy/pasting_ C code and expect it to magically just work with 100% certainty. I also did not say that using C headers should be forbidden, merely that it should obey the code organization - the current scheme which was defined by Walter is to put such headers in Deimos. I wouldn't mind if Deimos would come bundled with the D tool-chain or be easily accessible via a package manager, Just that code should be kept organized according to our own defined scheme. Besides, what if I find it useful to use e.g. FORTRAN code, should the relevant functions also be in the stdlib?
May 08 2012
parent reply "Lars T. Kyllingstad" <public kyllingen.net> writes:
On Tuesday, 8 May 2012 at 14:48:27 UTC, foobar wrote:
 [...], what if I find it useful to use e.g. FORTRAN code, 
 should the relevant functions also be in the stdlib?
No, FORTRAN has absolutely nothing to do with D. C, on the other hand, does. Both druntime and Phobos depend heavily on the C stdlib. The GC uses malloc/free, std.stdio.File is a wrapper around FILE*, etc. -Lars
May 08 2012
parent reply "foobar" <foo bar.com> writes:
On Tuesday, 8 May 2012 at 14:59:43 UTC, Lars T. Kyllingstad wrote:
 On Tuesday, 8 May 2012 at 14:48:27 UTC, foobar wrote:
 [...], what if I find it useful to use e.g. FORTRAN code, 
 should the relevant functions also be in the stdlib?
No, FORTRAN has absolutely nothing to do with D. C, on the other hand, does. Both druntime and Phobos depend heavily on the C stdlib. The GC uses malloc/free, std.stdio.File is a wrapper around FILE*, etc. -Lars
Irrelevant. For all I care druntime could be implemented in Klingon. That doesn't mean its API needs to include Klingon as well. That's called "encapsulation".
May 08 2012
next sibling parent reply "Lars T. Kyllingstad" <public kyllingen.net> writes:
On Tuesday, 8 May 2012 at 16:35:05 UTC, foobar wrote:
 On Tuesday, 8 May 2012 at 14:59:43 UTC, Lars T. Kyllingstad 
 wrote:
 On Tuesday, 8 May 2012 at 14:48:27 UTC, foobar wrote:
 [...], what if I find it useful to use e.g. FORTRAN code, 
 should the relevant functions also be in the stdlib?
No, FORTRAN has absolutely nothing to do with D. C, on the other hand, does. Both druntime and Phobos depend heavily on the C stdlib. The GC uses malloc/free, std.stdio.File is a wrapper around FILE*, etc. -Lars
Irrelevant. For all I care druntime could be implemented in Klingon. That doesn't mean its API needs to include Klingon as well. That's called "encapsulation".
Um... so you don't mind the C/POSIX declarations being there, you just want them to be private so you aren't tempted to use them in your own code? -Lars
May 08 2012
parent reply "foobar" <foo bar.com> writes:
On Tuesday, 8 May 2012 at 17:03:10 UTC, Lars T. Kyllingstad wrote:
 On Tuesday, 8 May 2012 at 16:35:05 UTC, foobar wrote:
 On Tuesday, 8 May 2012 at 14:59:43 UTC, Lars T. Kyllingstad 
 wrote:
 On Tuesday, 8 May 2012 at 14:48:27 UTC, foobar wrote:
 [...], what if I find it useful to use e.g. FORTRAN code, 
 should the relevant functions also be in the stdlib?
No, FORTRAN has absolutely nothing to do with D. C, on the other hand, does. Both druntime and Phobos depend heavily on the C stdlib. The GC uses malloc/free, std.stdio.File is a wrapper around FILE*, etc. -Lars
Irrelevant. For all I care druntime could be implemented in Klingon. That doesn't mean its API needs to include Klingon as well. That's called "encapsulation".
Um... so you don't mind the C/POSIX declarations being there, you just want them to be private so you aren't tempted to use them in your own code? -Lars
Yes, pretty much. They are an implementation detail of druntime/phobos. Other vendors may choose to implement the tool-chain with another language in mind and as long as the API remains the same I shouldn't need to care e.g. how the GC allocation is implemented (Perhaps it's done with FORTRAN's memory allocation routines). If I ,the user, want to interface with C I need to use the "official" C headers in Deimos. This is after all the official location for that.
May 08 2012
next sibling parent "foobar" <foo bar.com> writes:
On Tuesday, 8 May 2012 at 17:24:24 UTC, foobar wrote:
 On Tuesday, 8 May 2012 at 17:03:10 UTC, Lars T. Kyllingstad 
 wrote:
 On Tuesday, 8 May 2012 at 16:35:05 UTC, foobar wrote:
 On Tuesday, 8 May 2012 at 14:59:43 UTC, Lars T. Kyllingstad 
 wrote:
 On Tuesday, 8 May 2012 at 14:48:27 UTC, foobar wrote:
 [...], what if I find it useful to use e.g. FORTRAN code, 
 should the relevant functions also be in the stdlib?
No, FORTRAN has absolutely nothing to do with D. C, on the other hand, does. Both druntime and Phobos depend heavily on the C stdlib. The GC uses malloc/free, std.stdio.File is a wrapper around FILE*, etc. -Lars
Irrelevant. For all I care druntime could be implemented in Klingon. That doesn't mean its API needs to include Klingon as well. That's called "encapsulation".
Um... so you don't mind the C/POSIX declarations being there, you just want them to be private so you aren't tempted to use them in your own code? -Lars
Yes, pretty much. They are an implementation detail of druntime/phobos. Other vendors may choose to implement the tool-chain with another language in mind and as long as the API remains the same I shouldn't need to care e.g. how the GC allocation is implemented (Perhaps it's done with FORTRAN's memory allocation routines). If I ,the user, want to interface with C I need to use the "official" C headers in Deimos. This is after all the official location for that.
BTW, it makes sense even if druntime is implemented with C/POSIX - it decouples the user-facing headers from those used by the runtime. the runtime could depend on an older stable version than the one exposed to the users. I assume druntime/phobos uses some windows APIs in their implementations. Now consider the new winRT API for windows. It should be a matter of updating the headers in a separate repository so that it would be exposed to end-users without waiting on a druntime update to utilize those APIs.
May 08 2012
prev sibling parent Sean Kelly <sean invisibleduck.org> writes:
On May 8, 2012, at 10:24 AM, foobar wrote:

 On Tuesday, 8 May 2012 at 17:03:10 UTC, Lars T. Kyllingstad wrote:
 On Tuesday, 8 May 2012 at 16:35:05 UTC, foobar wrote:
 On Tuesday, 8 May 2012 at 14:59:43 UTC, Lars T. Kyllingstad wrote:
 On Tuesday, 8 May 2012 at 14:48:27 UTC, foobar wrote:
 [...], what if I find it useful to use e.g. FORTRAN code, should =
the relevant functions also be in the stdlib?
=20
 No, FORTRAN has absolutely nothing to do with D.  C, on the other =
hand, does. Both druntime and Phobos depend heavily on the C stdlib. = The GC uses malloc/free, std.stdio.File is a wrapper around FILE*, etc.
=20
 -Lars
=20 Irrelevant. For all I care druntime could be implemented in Klingon. =
That doesn't mean its API needs to include Klingon as well. That's = called "encapsulation".
=20
 Um... so you don't mind the C/POSIX declarations being there, you =
just want them to be private so you aren't tempted to use them in your = own code?
=20
 Yes, pretty much.
 They are an implementation detail of druntime/phobos.
=20
 Other vendors may choose to implement the tool-chain with another =
language in mind and as long as the API remains the same I shouldn't = need to care e.g. how the GC allocation is implemented (Perhaps it's = done with FORTRAN's memory allocation routines).
=20
 If I ,the user, want to interface with C I need to use the "official" =
C headers in Deimos. This is after all the official location for that. I think this is two separate issues. The GC implementation is very much = hidden already. The only point of exposure for standard C headers is in = core.*, and frankly, I think the only ones actually used are = core.sys.windows and core.sys.posix (posix admittedly being a superset = of standard C, as stated before).=
May 08 2012
prev sibling next sibling parent reply Sean Kelly <sean invisibleduck.org> writes:
On May 8, 2012, at 9:35 AM, foobar wrote:

 On Tuesday, 8 May 2012 at 14:59:43 UTC, Lars T. Kyllingstad wrote:
 On Tuesday, 8 May 2012 at 14:48:27 UTC, foobar wrote:
 [...], what if I find it useful to use e.g. FORTRAN code, should the =
relevant functions also be in the stdlib?
=20
 No, FORTRAN has absolutely nothing to do with D.  C, on the other =
hand, does. Both druntime and Phobos depend heavily on the C stdlib. = The GC uses malloc/free, std.stdio.File is a wrapper around FILE*, etc.
=20
 Irrelevant. For all I care druntime could be implemented in Klingon. =
That doesn't mean its API needs to include Klingon as well. That's = called "encapsulation". This is difficult to do with the module system. You'd have to = hand-craft .di files with the stdc headers left out to avoid bundling = them in the distro. They could go into core.internal I suppose though.=
May 08 2012
parent "foobar" <foo bar.com> writes:
On Tuesday, 8 May 2012 at 21:17:21 UTC, Sean Kelly wrote:
 On May 8, 2012, at 9:35 AM, foobar wrote:

 On Tuesday, 8 May 2012 at 14:59:43 UTC, Lars T. Kyllingstad 
 wrote:
 On Tuesday, 8 May 2012 at 14:48:27 UTC, foobar wrote:
 [...], what if I find it useful to use e.g. FORTRAN code, 
 should the relevant functions also be in the stdlib?
No, FORTRAN has absolutely nothing to do with D. C, on the other hand, does. Both druntime and Phobos depend heavily on the C stdlib. The GC uses malloc/free, std.stdio.File is a wrapper around FILE*, etc.
Irrelevant. For all I care druntime could be implemented in Klingon. That doesn't mean its API needs to include Klingon as well. That's called "encapsulation".
This is difficult to do with the module system. You'd have to hand-craft .di files with the stdc headers left out to avoid bundling them in the distro. They could go into core.internal I suppose though.
Having an internal package is a good idea. Don did the same for the Math code. More over, the general issue with the module system should be fixed. There was a recent discussion about Andrei's DIP, precisely about addressing this problem.
May 08 2012
prev sibling next sibling parent reply "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Tuesday, May 08, 2012 14:17:14 Sean Kelly wrote:
 On May 8, 2012, at 9:35 AM, foobar wrote:
 On Tuesday, 8 May 2012 at 14:59:43 UTC, Lars T. Kyllingstad wrote:
 On Tuesday, 8 May 2012 at 14:48:27 UTC, foobar wrote:
 [...], what if I find it useful to use e.g. FORTRAN code, should the
 relevant functions also be in the stdlib?>> 
No, FORTRAN has absolutely nothing to do with D. C, on the other hand, does. Both druntime and Phobos depend heavily on the C stdlib. The GC uses malloc/free, std.stdio.File is a wrapper around FILE*, etc.>
Irrelevant. For all I care druntime could be implemented in Klingon. That doesn't mean its API needs to include Klingon as well. That's called "encapsulation".
This is difficult to do with the module system. You'd have to hand-craft .di files with the stdc headers left out to avoid bundling them in the distro. They could go into core.internal I suppose though.
We've previously discussed having _all_ of the C system call functions from the various OSes that we support being in druntime, and I very much think that that's the right way to go. Phobos and druntime then have whatever they need as for as standard C and system call functions go, and anyone who needs any which aren't wrapped by Phobos in some manner has them available to them. Anyone that doesn't want to use any of those C function directly, doesn't have to, but I don't see any reason to hide them just because someone doesn't want to use them in their code. If the problem is that certain C functions end up getting used a lot when they should have D wrappers of some kind which better encapsulate their functionality, then maybe we add the appropriate wrappers to Phobos. But that's a completely different issue. Hiding the C functions doesn't help us any. It makes sense to make truly internal stuff internal, but the standard C function declarations and OS system functions are _not_ internal to druntime. They're _very_ much external. druntime is just providing them because they're functionality which is core to the system that any D program is running on. - Jonathan M Davis
May 08 2012
parent =?UTF-8?B?QWxleCBSw7hubmUgUGV0ZXJzZW4=?= <xtzgzorex gmail.com> writes:
On 08-05-2012 23:31, Jonathan M Davis wrote:
 On Tuesday, May 08, 2012 14:17:14 Sean Kelly wrote:
 On May 8, 2012, at 9:35 AM, foobar wrote:
 On Tuesday, 8 May 2012 at 14:59:43 UTC, Lars T. Kyllingstad wrote:
 On Tuesday, 8 May 2012 at 14:48:27 UTC, foobar wrote:
 [...], what if I find it useful to use e.g. FORTRAN code, should the
 relevant functions also be in the stdlib?>>
No, FORTRAN has absolutely nothing to do with D. C, on the other hand, does. Both druntime and Phobos depend heavily on the C stdlib. The GC uses malloc/free, std.stdio.File is a wrapper around FILE*, etc.>
Irrelevant. For all I care druntime could be implemented in Klingon. That doesn't mean its API needs to include Klingon as well. That's called "encapsulation".
This is difficult to do with the module system. You'd have to hand-craft .di files with the stdc headers left out to avoid bundling them in the distro. They could go into core.internal I suppose though.
We've previously discussed having _all_ of the C system call functions from the various OSes that we support being in druntime, and I very much think that that's the right way to go. Phobos and druntime then have whatever they need as for as standard C and system call functions go, and anyone who needs any which aren't wrapped by Phobos in some manner has them available to them. Anyone that doesn't want to use any of those C function directly, doesn't have to, but I don't see any reason to hide them just because someone doesn't want to use them in their code.
+1. We have better things to fix.
 If the problem is that certain C functions end up getting used a lot when they
 should have D wrappers of some kind which better encapsulate their
 functionality, then maybe we add the appropriate wrappers to Phobos. But
 that's a completely different issue. Hiding the C functions doesn't help us
 any.
I do think we could benefit from hiding the (deprecated) std.c.* modules on dlang.org (I posted about this a while back).
 It makes sense to make truly internal stuff internal, but the standard C
 function declarations and OS system functions are _not_ internal to druntime.
 They're _very_ much external. druntime is just providing them because they're
 functionality which is core to the system that any D program is running on.

 - Jonathan M Davis
-- - Alex
May 08 2012
prev sibling parent reply Sean Kelly <sean invisibleduck.org> writes:
On May 8, 2012, at 2:31 PM, Jonathan M Davis wrote:
=20
 We've previously discussed having _all_ of the C system call functions =
from=20
 the various OSes that we support being in druntime, and I very much =
think that=20
 that's the right way to go. Phobos and druntime then have whatever =
they need=20
 as for as standard C and system call functions go, and anyone who =
needs any=20
 which aren't wrapped by Phobos in some manner has them available to =
them.=20
 Anyone that doesn't want to use any of those C function directly, =
doesn't have=20
 to, but I don't see any reason to hide them just because someone =
doesn't want=20
 to use them in their code.
=20
 If the problem is that certain C functions end up getting used a lot =
when they=20
 should have D wrappers of some kind which better encapsulate their=20
 functionality, then maybe we add the appropriate wrappers to Phobos. =
But=20
 that's a completely different issue. Hiding the C functions doesn't =
help us=20
 any.
I personally use "import core.stdc" as an indicator that there may be = some feature missing from Phobos. It's easily greppable, and easy to = avoid using the routines. In fact, I think "import core" anything = should be an exceptional case in a typical D application. Everything = exposed in Druntime is for what I'd consider power users. Unsafe = threads, runtime and GC hooks, platform API calls, etc. It's all there = because the higher-level stuff needs it, but is really not intended for = general use.
 It makes sense to make truly internal stuff internal, but the standard =
C
 function declarations and OS system functions are _not_ internal to =
druntime.
 They're _very_ much external. druntime is just providing them because =
they're
 functionality which is core to the system that any D program is =
running on. Once upon a time, there was a D runtime library (unrelated to Druntime) = that has no C library dependence at all. It was an interesting idea, = but I don't know that there's any system that D targets which doesn't = support C.=
May 08 2012
parent reply =?ISO-8859-1?Q?Alex_R=F8nne_Petersen?= <xtzgzorex gmail.com> writes:
On 08-05-2012 23:48, Sean Kelly wrote:
 On May 8, 2012, at 2:31 PM, Jonathan M Davis wrote:
 We've previously discussed having _all_ of the C system call functions from
 the various OSes that we support being in druntime, and I very much think that
 that's the right way to go. Phobos and druntime then have whatever they need
 as for as standard C and system call functions go, and anyone who needs any
 which aren't wrapped by Phobos in some manner has them available to them.
 Anyone that doesn't want to use any of those C function directly, doesn't have
 to, but I don't see any reason to hide them just because someone doesn't want
 to use them in their code.

 If the problem is that certain C functions end up getting used a lot when they
 should have D wrappers of some kind which better encapsulate their
 functionality, then maybe we add the appropriate wrappers to Phobos. But
 that's a completely different issue. Hiding the C functions doesn't help us
 any.
I personally use "import core.stdc" as an indicator that there may be some feature missing from Phobos. It's easily greppable, and easy to avoid using the routines. In fact, I think "import core" anything should be an exceptional case in a typical D application. Everything exposed in Druntime is for what I'd consider power users. Unsafe threads, runtime and GC hooks, platform API calls, etc. It's all there because the higher-level stuff needs it, but is really not intended for general use.
I just hope none of it goes away. I make extensive use of many core.* modules.
 It makes sense to make truly internal stuff internal, but the standard C
 function declarations and OS system functions are _not_ internal to druntime.
 They're _very_ much external. druntime is just providing them because they're
 functionality which is core to the system that any D program is running on.
Once upon a time, there was a D runtime library (unrelated to Druntime) that has no C library dependence at all. It was an interesting idea, but I don't know that there's any system that D targets which doesn't support C.
*Is* there any system that doesn't support C? ;) -- - Alex
May 09 2012
next sibling parent "foobar" <foo bar.com> writes:
On Wednesday, 9 May 2012 at 08:16:35 UTC, Alex Rønne Petersen 
wrote:
 I personally use "import core.stdc" as an indicator that there 
 may be some feature missing from Phobos.  It's easily 
 greppable, and easy to avoid using the routines.  In fact, I 
 think "import core" anything should be an exceptional case in 
 a typical D application.  Everything exposed in Druntime is 
 for what I'd consider power users.  Unsafe threads, runtime 
 and GC hooks, platform API calls, etc.  It's all there because 
 the higher-level stuff needs it, but is really not intended 
 for general use.
I just hope none of it goes away. I make extensive use of many core.* modules.
Could you please provide more details about your use-cases? As Sean said, it might indicate missing functionality in Phobos. Keep in mind we were specifically discussing the C APIs which are an external dependency. No one suggests removing the low-level druntime APIs such as GC hooks.
 Once upon a time, there was a D runtime library (unrelated to 
 Druntime) that has no C library dependence at all.  It was an 
 interesting idea, but I don't know that there's any system 
 that D targets which doesn't support C.
*Is* there any system that doesn't support C? ;)
It isn't only a question of whether the system supports C or not. There are many considerations when choosing your tool-chain. For instance, the reference implementation of some languages is implemented in ML for its correctness properties. EcmaScript for instance uses ML for the language/runtime. In the JS case, it doesn't necessarily mean your browser will run ML, it just means the highly optimized vendor implementation has an official correct version to compare to. In the D world, we have a few projects that aim to implement a D compiler using D. Why would such a compiler/runtime need to provide C APIs if it's completely written in D?
May 09 2012
prev sibling parent Don Clugston <dac nospam.com> writes:
On 09/05/12 10:16, Alex Rønne Petersen wrote:
 On 08-05-2012 23:48, Sean Kelly wrote:
 On May 8, 2012, at 2:31 PM, Jonathan M Davis wrote:
 We've previously discussed having _all_ of the C system call
 functions from
 the various OSes that we support being in druntime, and I very much
 think that
 that's the right way to go. Phobos and druntime then have whatever
 they need
 as for as standard C and system call functions go, and anyone who
 needs any
 which aren't wrapped by Phobos in some manner has them available to
 them.
 Anyone that doesn't want to use any of those C function directly,
 doesn't have
 to, but I don't see any reason to hide them just because someone
 doesn't want
 to use them in their code.

 If the problem is that certain C functions end up getting used a lot
 when they
 should have D wrappers of some kind which better encapsulate their
 functionality, then maybe we add the appropriate wrappers to Phobos. But
 that's a completely different issue. Hiding the C functions doesn't
 help us
 any.
I personally use "import core.stdc" as an indicator that there may be some feature missing from Phobos. It's easily greppable, and easy to avoid using the routines. In fact, I think "import core" anything should be an exceptional case in a typical D application. Everything exposed in Druntime is for what I'd consider power users. Unsafe threads, runtime and GC hooks, platform API calls, etc. It's all there because the higher-level stuff needs it, but is really not intended for general use.
I just hope none of it goes away. I make extensive use of many core.* modules.
 It makes sense to make truly internal stuff internal, but the standard C
 function declarations and OS system functions are _not_ internal to
 druntime.
 They're _very_ much external. druntime is just providing them because
 they're
 functionality which is core to the system that any D program is
 running on.
Once upon a time, there was a D runtime library (unrelated to Druntime) that has no C library dependence at all. It was an interesting idea, but I don't know that there's any system that D targets which doesn't support C.
*Is* there any system that doesn't support C? ;)
There are plenty of systems that don't support C99 perfectly.
May 09 2012
prev sibling parent reply deadalnix <deadalnix gmail.com> writes:
Le 08/05/2012 13:59, foobar a écrit :
 On Sunday, 6 May 2012 at 22:06:32 UTC, Jonathan M Davis wrote:
 This argument comes up every once in a while even though AFAIK it
 is *not* a goal of D and never has been!
 D does not and *should not* strive to be source compatible with
 C. We already have C++ for that and it is a horrible idea.
 D can link with C which allows to use pre-existing C code. we
 should *not* encourage converting C code to D code at all. Either
 just link the C code or use D idiomatic code.
Then you misunderstand. One of the tenets that D holds to is that any C/C++ code either compiles as valid D code with identical semantics, or it doesn't compile as D code (there are a few minor exceptions - such as static arrays being passed by value - but not many). This means that we can break compatibility with C/C++ and do our own thing for a lot of stuff but that we can't just redefine what stuff does such that it would silently break code when it's ported from C/C++ to D. That approach is _very_ different from C++'s approach where valid C code pretty much _always_ compiles identically in C++ (the fact that C++ added keywords being the only exception that I can think of at the moment), but that doesn't mean that we don't care about code portability from C/C++ to D. There's a huge difference between designing a language such that porting code to it from another language isn't error-prone and making the new language source compatibile. D does the former. C++ does the latter. Being able to port code from C/C++ to D without having to worry about silent breakage _is_ one of D's goals. - Jonathan M Davis
I have a three main problems with the above: a. C++ is *not* fully source compatible with C, especially the latest C99 conflicts with C++ IIRC. b. D isn't either - there are already semantics changes compared to C, as you said so yourself, e.g. static arrays, default initialization of static floats, etc. c. If this is currently a goal of D it really shouldn't be - it prevents us from fixing design bugs we inherited from C such as implicit numeric coercions. As others said, the only thing that sort-of makes sense is to copy/paste *declarations* and even those are different enough in D that they deserve at least a look over to make sure they are correct. We shouldn't promote this "goal" at all especially given that it isn't even guarantied to be 100% correct in all cases. Really what we should be promoting is the fact that D is _link_ compatible with C and allows you to use existing C code _without_ porting it to D.
I think that goal is misunderstood. It is aimed at human being, not compiler. If one read D code that look like C, it should be able to understand it easily. I is not supped to compile with 100% exact semantic.
May 08 2012
parent reply "foobar" <foo bar.com> writes:
On Tuesday, 8 May 2012 at 19:00:01 UTC, deadalnix wrote:
 I think that goal is misunderstood. It is aimed at human being, 
 not compiler.

 If one read D code that look like C, it should be able to 
 understand it easily. I is not supped to compile with 100% 
 exact semantic.
Unfortunately that is not the case. The stated argument is that compiling C code with a D compiler should either compile exactly the same or produce a compilation error. As discussed, this is _already_ incorrect for some cases, is completely unnecessary since you can link with pre-compiled C code (via a C compiler) _without_ any overhead and this forces us to carry legacy C design flaws. If you talking about ease of understanding "C-like" D, that's already a given because D belongs to the C-family of languages. For that matter, JavaScript also belongs to the same family and is easily understood (if you write C-like code). yet no one expects to be able to copy/paste C code into a JS script and have it working as/is.
May 08 2012
next sibling parent reply Sean Cavanaugh <WorksOnMyMachine gmail.com> writes:
On 5/8/2012 3:36 PM, foobar wrote:
 On Tuesday, 8 May 2012 at 19:00:01 UTC, deadalnix wrote:
 I think that goal is misunderstood. It is aimed at human being, not
 compiler.

 If one read D code that look like C, it should be able to understand
 it easily. I is not supped to compile with 100% exact semantic.
Unfortunately that is not the case. The stated argument is that compiling C code with a D compiler should either compile exactly the same or produce a compilation error.
Thousands of my C/C++ floating point constants are broken by the CTFE change since as 'integer'-like float constants 31.f and won't compile anymore, since its trying to do f(31) to them for me now . . .
May 08 2012
next sibling parent Jens Mueller <jens.k.mueller gmx.de> writes:
Sean Cavanaugh wrote:
 On 5/8/2012 3:36 PM, foobar wrote:
On Tuesday, 8 May 2012 at 19:00:01 UTC, deadalnix wrote:
I think that goal is misunderstood. It is aimed at human being, not
compiler.

If one read D code that look like C, it should be able to understand
it easily. I is not supped to compile with 100% exact semantic.
Unfortunately that is not the case. The stated argument is that compiling C code with a D compiler should either compile exactly the same or produce a compilation error.
Thousands of my C/C++ floating point constants are broken by the CTFE change since as 'integer'-like float constants 31.f and won't compile anymore, since its trying to do f(31) to them for me now . . .
I wholeheartedly agree that breaking changes are frustrating. But especially this one was needed. What we should provide is a clear path to fix the code. In your case, search and replace using a regular expression like s/(\d+).f/\1.0f/g is the way to fix your code in less than 5 minutes I hope. Jens
May 09 2012
prev sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2012-05-09 02:56, Sean Cavanaugh wrote:

 Thousands of my C/C++ floating point constants are broken by the CTFE
 change since as 'integer'-like float constants 31.f and won't compile
 anymore, since its trying to do f(31) to them for me now . . .
I don't see any point in supporting 31.f as a floating point syntax. -- /Jacob Carlborg
May 09 2012
parent =?UTF-8?B?QWxleCBSw7hubmUgUGV0ZXJzZW4=?= <xtzgzorex gmail.com> writes:
On 09-05-2012 10:27, Jacob Carlborg wrote:
 On 2012-05-09 02:56, Sean Cavanaugh wrote:

 Thousands of my C/C++ floating point constants are broken by the CTFE
 change since as 'integer'-like float constants 31.f and won't compile
 anymore, since its trying to do f(31) to them for me now . . .
I don't see any point in supporting 31.f as a floating point syntax.
+1. -- - Alex
May 11 2012
prev sibling next sibling parent Sean Cavanaugh <WorksOnMyMachine gmail.com> writes:
On 5/8/2012 7:56 PM, Sean Cavanaugh wrote:
 On 5/8/2012 3:36 PM, foobar wrote:
 On Tuesday, 8 May 2012 at 19:00:01 UTC, deadalnix wrote:
 I think that goal is misunderstood. It is aimed at human being, not
 compiler.

 If one read D code that look like C, it should be able to understand
 it easily. I is not supped to compile with 100% exact semantic.
Unfortunately that is not the case. The stated argument is that compiling C code with a D compiler should either compile exactly the same or produce a compilation error.
Thousands of my C/C++ floating point constants are broken by the CTFE change since as 'integer'-like float constants 31.f and won't compile anymore, since its trying to do f(31) to them for me now . . .
s/CTFE/UFCS
May 08 2012
prev sibling parent Sean Cavanaugh <WorksOnMyMachine gmail.com> writes:
On 5/8/2012 7:56 PM, Sean Cavanaugh wrote:
 On 5/8/2012 3:36 PM, foobar wrote:
 On Tuesday, 8 May 2012 at 19:00:01 UTC, deadalnix wrote:
 I think that goal is misunderstood. It is aimed at human being, not
 compiler.

 If one read D code that look like C, it should be able to understand
 it easily. I is not supped to compile with 100% exact semantic.
Unfortunately that is not the case. The stated argument is that compiling C code with a D compiler should either compile exactly the same or produce a compilation error.
Thousands of my C/C++ floating point constants are broken by the CTFE change since as 'integer'-like float constants 31.f and won't compile anymore, since its trying to do f(31) to them for me now . . .
s/CTFE/UFCS
May 08 2012
prev sibling parent "Lars T. Kyllingstad" <public kyllingen.net> writes:
On Thursday, 3 May 2012 at 22:57:02 UTC, Walter Bright wrote:
 On 5/3/2012 8:13 AM, Don Clugston wrote:
 Well, they are also used in druntime, in core.stdc.math
 BTW I *hate* that module, I don't know why it exists. Even 
 worse, it seems to be
 growing -- people are adding more things to it.
It's there simply because all the Standard C headers should be represented. It should not get anything that is not in Standard C. Ditto for all the other stuff in core.stdc. It's there to make converting C code to D code easier.
I agree that this is a good enough reason in itself. On top of that, the ANSI C stdlib is a subset of the POSIX API, which is *very* useful to have in druntime. Phobos (and druntime itself, of course), uses it for everything platform-specific. -Lars
May 08 2012
prev sibling parent reply Iain Buclaw <ibuclaw ubuntu.com> writes:
On 3 May 2012 16:13, Don Clugston <dac nospam.com> wrote:
 On 03/05/12 16:13, Andrei Alexandrescu wrote:
 On 5/3/12 9:55 AM, Don Clugston wrote:
 On 28/04/12 20:47, Walter Bright wrote:
 Andrei and I had a fun discussion last night about this question. The
 idea was which features in D are redundant and/or do not add significant
 value?

 A couple already agreed upon ones are typedef and the cfloat, cdouble
 and creal types.

 What's your list?
Other ones which were agreed to a long time ago were: * NCEG operators * built-in .sort and .reverse
Good ones. In fact I even discounted them from this discussion because I'd already considered them gone. Walter agreed that I don't mention them in TDPL, with the intent to have them peter out. One good step right now would be to remove NCEG operators from the online documentation. Later on, we'll consider them an accept-invalid bug :o).
Well, they are also used in druntime, in core.stdc.math BTW I *hate* that module, I don't know why it exists. Even worse, it seems to be growing -- people are adding more things to it. Practically everything in there has a better implementation in std.math.
I used core.stdc.math to map GCC builtins to math lib functions. This allows for a lot of potential const folding that the D frontend does not (currently) handle. -- Iain Buclaw *(p < e ? p++ : p) = (c & 0x0f) + '0';
May 03 2012
parent reply =?ISO-8859-1?Q?Alex_R=F8nne_Petersen?= <xtzgzorex gmail.com> writes:
On 04-05-2012 02:13, Iain Buclaw wrote:
 On 3 May 2012 16:13, Don Clugston<dac nospam.com>  wrote:
 On 03/05/12 16:13, Andrei Alexandrescu wrote:
 On 5/3/12 9:55 AM, Don Clugston wrote:
 On 28/04/12 20:47, Walter Bright wrote:
 Andrei and I had a fun discussion last night about this question. The
 idea was which features in D are redundant and/or do not add significant
 value?

 A couple already agreed upon ones are typedef and the cfloat, cdouble
 and creal types.

 What's your list?
Other ones which were agreed to a long time ago were: * NCEG operators * built-in .sort and .reverse
Good ones. In fact I even discounted them from this discussion because I'd already considered them gone. Walter agreed that I don't mention them in TDPL, with the intent to have them peter out. One good step right now would be to remove NCEG operators from the online documentation. Later on, we'll consider them an accept-invalid bug :o).
Well, they are also used in druntime, in core.stdc.math BTW I *hate* that module, I don't know why it exists. Even worse, it seems to be growing -- people are adding more things to it. Practically everything in there has a better implementation in std.math.
I used core.stdc.math to map GCC builtins to math lib functions. This allows for a lot of potential const folding that the D frontend does not (currently) handle.
Does that play nice with errno? -- - Alex
May 03 2012
parent Iain Buclaw <ibuclaw ubuntu.com> writes:
On 4 May 2012 01:40, Alex R=F8nne Petersen <xtzgzorex gmail.com> wrote:
 On 04-05-2012 02:13, Iain Buclaw wrote:
 On 3 May 2012 16:13, Don Clugston<dac nospam.com> =A0wrote:
 On 03/05/12 16:13, Andrei Alexandrescu wrote:

 On 5/3/12 9:55 AM, Don Clugston wrote:
 On 28/04/12 20:47, Walter Bright wrote:
 Andrei and I had a fun discussion last night about this question. Th=
e
 idea was which features in D are redundant and/or do not add
 significant
 value?

 A couple already agreed upon ones are typedef and the cfloat, cdoubl=
e
 and creal types.

 What's your list?
Other ones which were agreed to a long time ago were: * NCEG operators * built-in .sort and .reverse
Good ones. In fact I even discounted them from this discussion because I'd already considered them gone. Walter agreed that I don't mention them in TDPL, with the intent to have them peter out. One good step right now would be to remove NCEG operators from the online documentation. Later on, we'll consider them an accept-invalid bug :o).
Well, they are also used in druntime, in core.stdc.math BTW I *hate* that module, I don't know why it exists. Even worse, it seems to be growing -- people are adding more things to it. Practically everything in there has a better implementation in std.math=
.
 I used core.stdc.math to map GCC builtins to math lib functions. =A0This
 allows for a lot of potential const folding that the D frontend does
 not (currently) handle.
Does that play nice with errno?
The default is -fno-errno-math for GDC, so errno is not usually set after calling single math instructions. This allows most functions to be used in pure routines. --=20 Iain Buclaw *(p < e ? p++ : p) =3D (c & 0x0f) + '0';
May 04 2012