www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - C#5 desiderata

reply bearophile <bearophileHUGS lycos.com> writes:
You can remember when I have shown this link, about desired features for C#4:
http://stackoverflow.com/questions/138367/
Instead of many of those features, C# devs have chosen to add only very few
ones, but rather basic ones, like the dynamic attribute, that change some how
C# programs can be written.


Recently a similar question has appeared about C#5 (probably some answers are
repeated from the precedent thread):
http://stackoverflow.com/questions/2875533/
Some of those things are meaningful only in the context of C#4.

Note: what follows below is not my list of desiderata for D2/D3, it's just a
summarized version of that that stackoverflow thread about C#5 desiderata.

-------------------

Return tuples:

public (int, string, double) Foo() {
    return (42, "foo", 4.2);
    return {"Hello World", 42, 4.2};
}


// elsewhere: item1 is a string, item2 is an int, item3 is a double. 
var (item1, item2, item3) = Foo();
var {item1, item2, item3} = Foo();

var myTuple = (42, "foo", 4.2);
var myTuple = {42, "foo", 4.2};
===
Tuple<int, string, double> myTuple = Tuple.Create(42, "foo", 4.2);

-------------------

in for arrays:

if (x in (1, 2, 3)) {}

-------------------

Automatic Flag Enums (automatically enumerate in powers of two).

-------------------

Null Safe Member Operator:

Instead of doing:

var obj = Foo();
Bar value = null;
if (obj.Bar != null && obj.Bar.Something != null)
    value = obj.Bar.Something.DoSomething();

You can do this with Groovy's null safe member operator:

var obj = Foo();
var value = obj?.Bar?.Something?.DoSomething();

-------------------

Nested Iterators:

public override IEnumerable<int> Foo() {
  yield return 1;
  yield return 2;
  yield return base.Foo();
  // yield foreach base.Foo();
}

Instead of:

public override IEnumerable<int> Foo() {
  yield return 1;
  yield return 2;
  foreach(var i in base.Foo()) yield i;
}

As explained here too:
http://research.microsoft.com/en-us/projects/specsharp/iterators.pdf

-------------------

Weak delegates, to make it easy to implement weak events. A modifier like ~
could mark a normal delegate weak:

public event EventHandler StrongEvent;
public event EventHandler~ WeakEvent; // Shortcut for WeakDelegate<EventHandler>

-------------------

Arrays indexed by enums, delphi style:

enum Weekdays { Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday }
private int[Weekdays] dayFun = new [] { 0, 0, 1, 1, 3, 10, 8 };

// later..
mondayFun = dayFun[Weekdays.Monday];

-------------------

Exception grouping to avoid duplicating the same handling logic

try
{
}
catch (ArgumentOutOfRangeException)
catch (ArgumentNullException)
{
   // Catch a ArgumentOutOfRangeException or a ArgumentNullException
}

(I think this syntax can be improved, just using the comma).

-------------------

 memoize

Or something similar user-defined. It is really useful, to avoid coding true
dynamic programming algorithms.

-------------------

"as" operator for objects (This is already present in C#4).

Bye,
bearophile
May 28 2010
next sibling parent reply "Simen kjaeraas" <simen.kjaras gmail.com> writes:
bearophile <bearophileHUGS lycos.com> wrote:

 Return tuples:

Absolutely. While it's possible today, some more sugar wouldn't hurt.
 in for arrays:

Yes.
 Automatic Flag Enums (automatically enumerate in powers of two).

Neat. Worthy an keyword, I think. " flag enum foo {...}"
 Null Safe Member Operator:
 var value = obj?.Bar?.Something?.DoSomething();

I feel this is a tad too sweet. On the one hand I like it, on the other I feel it will lead to bugs at a later point, by hiding null pointers and not teaching programmers to deal with them. "Add a ? to all object accesses. It is magical and removes bugs."
 Weak delegates, to make it easy to implement weak events.

From what I read about this, it seems nice, but also possible to implement with current metaprogramming capabilities. Given an event system, what are the advantages to language support for this?
 Arrays indexed by enums, delphi style:

This seems to work for me in D2. But you probably meant an array that has exactly the same number of elements as has the enum. I can imagine this being a problem with enums having completely random values (which they may). That might be even more of an argument for flag, as mentioned above. If non- flag enums may not expose internal details such as equivalent values, while flags may (to allow for composite flag shortcuts), you could easily allow this for non- flag enums. Also, manifest constants should have a different name than 'enum', as they have nothing to do with enums.
 Exception grouping to avoid duplicating the same handling logic

Very nice.
  memoize

 Or something similar user-defined. It is really useful, to avoid coding  
 true dynamic programming algorithms.

This again is to sweet for me. What does memoize do? Does it store the last 5 results? All results? The last result only? Does it depend on the phase of the moon, time of day and what socks I'm wearing?
 "as" operator for objects (This is already present in C#4).

So "a as b" rather than "cast(b)(a)" or "to!(b)(a)"? Or is there some other magic at work that I don't see? -- Simen
May 28 2010
parent reply bearophile <bearophileHUGS lycos.com> writes:
Simen kjaeraas:

I think you have missed one important point: that was not my list of things I'd
like in D2/D3. It contains some cute things, but it's first of all a summary of
the linked stackoverflow thread. My personal list of desiderata for D3 is
different.


 Absolutely. While it's possible today, some more sugar wouldn't hurt.

I think Walter said this can't be implemented :) The items alignment of function arguments used by D tuples is not fitting to return a struct. I have not understood the details of this thing, and in the end I don't care if returning a struct can decrease performance a bit...
 in for arrays:

Yes.

I think Walter doesn't like this because he thinks "in" has to always look for keys, and keys of an array are its indexes. I don't agree with Walter here, but I don't think he will change his mind soon.
 Neat. Worthy an  keyword, I think. " flag enum foo {...}"

It's cute. But Don hates attributes :-) Recently I have created a thread about this, and some one has written a good enough implementation in normal D code, that can be "good enough".
 I feel this is a tad too sweet. On the one hand I like it, on the
 other I feel it will lead to bugs at a later point, by hiding null
 pointers and not teaching programmers to deal with them.
 "Add a ? to all object accesses. It is magical and removes bugs."

I agree. It can be handy but it can lead to bugs too, so I don't know what to think about it.
 Given an event system, what are the advantages to language
 support for this?

I don't know.
 Exception grouping to avoid duplicating the same handling logic

Very nice.

I have proposed something similar time ago. Python uses a tuple of possible exceptions, I was not expecting D to allow only one of them. Some form of this can be added to D2.
  memoize

 Or something similar user-defined. It is really useful, to avoid coding  
 true dynamic programming algorithms.

This again is to sweet for me. What does memoize do? Does it store the last 5 results? All results? The last result only? Does it depend on the phase of the moon, time of day and what socks I'm wearing?

That's why I have said user-defined (in Python too it's user defined), so you can define and use the one you prefer. But currently D properties are not flexible enough to allow programmers to define them.
 So "a as b" rather than "cast(b)(a)" or "to!(b)(a)"? Or is there
 some other magic at work that I don't see?

I think there is no magic, it's just syntax sugar. Bye, bearophile
May 28 2010
next sibling parent bearophile <bearophileHUGS lycos.com> writes:
Simen kjaeraas:
 Yeah. So, either we need thunks for this, or tuples need to carry
 alignment information.

If we accept a little less performance there must be a way to solve this problem. Multiple return values are certainly very handy. Bye, bearophile
May 28 2010
prev sibling next sibling parent Marianne Gagnon <auria.mg gmail.com> writes:
 I think Walter said this can't be implemented :)
 The items alignment of function arguments used by D tuples is not fitting to
return a struct. I have not understood the details of this thing, and in the
end I don't care if returning a struct can decrease performance a bit...
 

well, it could just be sugar ;) e.g. : (int, int) doFoo(int x, int y) could perhaps automagically be re-written by the compiler as int doFoo(int x, int y, out int z)
May 28 2010
prev sibling parent reply Don <nospam nospam.com> writes:
Simen kjaeraas wrote:
 bearophile <bearophileHUGS lycos.com> wrote:
 
 Simen kjaeraas:

 I think you have missed one important point: that was not my list of 
 things I'd like in D2/D3. It contains some cute things, but it's first 
 of all a summary of the linked stackoverflow thread. My personal list 
 of desiderata for D3 is different.

You are right indeed. I misread that first sentence to its exact opposite. :p
 I think Walter said this can't be implemented :)

I think Walter just doesn't want to implement it. :p
 The items alignment of function arguments used by D tuples is not 
 fitting to return a struct.

Yeah. So, either we need thunks for this, or tuples need to carry alignment information.
 Neat. Worthy an  keyword, I think. " flag enum foo {...}"

It's cute. But Don hates attributes :-) Recently I have created a thread about this, and some one has written a good enough implementation in normal D code, that can be "good enough".

Screw Don. :p

<g>. I just think that shouldn't be an excuse to be careless -- anything with an in front is still part of the language. That's all.
May 29 2010
next sibling parent reply Don <nospam nospam.com> writes:
Simen kjaeraas wrote:
 Leandro Lucarella <llucax gmail.com> wrote:
 
 <g>. I just think that   shouldn't be an excuse to be careless --
 anything with an   in front is still part of the language. That's
 all.

It shouldn't, that's (was?) the point of . If the point of was to create a namespace for keywords, it sucks...

With compiler- or language-given keywords, there is no difference from other keywords, except they don't eat valid identifiers. With a user-configurable system, it's still part of a language, but that language is specific to the component in which the keywords are being used, and thus does not pollute the namespace of keywords for other projects.

Except that they do eat identifiers for user-definable attributes...
May 30 2010
parent reply Ary Borenszweig <ary esperanto.org.ar> writes:
On 05/30/2010 08:49 AM, Don wrote:
 Simen kjaeraas wrote:
 Leandro Lucarella <llucax gmail.com> wrote:

 <g>. I just think that   shouldn't be an excuse to be careless --
 anything with an   in front is still part of the language. That's
 all.

It shouldn't, that's (was?) the point of . If the point of was to create a namespace for keywords, it sucks...

With compiler- or language-given keywords, there is no difference from other keywords, except they don't eat valid identifiers. With a user-configurable system, it's still part of a language, but that language is specific to the component in which the keywords are being used, and thus does not pollute the namespace of keywords for other projects.

Except that they do eat identifiers for user-definable attributes...

Well, that's because in other languages (Java, C#), attributes are first class citizens and they have a namespace too. So it's like saying "Oh, you can't have a class named Object in D because Object is already a class", which is not true because you can disambiguate with a namespace. The same is true for attributes in Java and C#... but not for D. :-( http://java.sun.com/javase/7/docs/api/java/lang/Deprecated.html In Java, I can create my own Deprecated annotation without problem.
May 30 2010
parent bearophile <bearophileHUGS lycos.com> writes:
Ary Borenszweig:
 Well, that's because in other languages (Java, C#), attributes are first 
 class citizens and they have a namespace too. So it's like saying "Oh, 
 you can't have a class named Object in D because Object is already a 
 class", which is not true because you can disambiguate with a namespace. 
 The same is true for attributes in Java and C#... but not for D. :-(

Can this be changed in D? Bye, bearophile
May 30 2010
prev sibling parent Ary Borenszweig <ary esperanto.org.ar> writes:
On 05/30/2010 04:09 AM, Simen kjaeraas wrote:
 Don <nospam nospam.com> wrote:

 <g>. I just think that   shouldn't be an excuse to be careless --
 anything with an   in front is still part of the language. That's all.

I know, and I agree. It irritates me whenever people say foo is not a keyword. By that logic, we might as well say any word starting with a 'w' is not a keyword. Would get rid of that pesky 'while'.

Please read my reply to Don. If implemented properly, foo is *not* a keyword.
May 30 2010
prev sibling next sibling parent Adam Ruppe <destructionator gmail.com> writes:
On 5/28/10, bearophile <bearophileHUGS lycos.com> wrote:
 in for arrays:
 if (x in (1, 2, 3)) {}

If the uniform function call syntax starts up, you could (maybe) do something like this: import std.algorithm; import std.array; bool among(T)(T v, T[] arr...) { return ! (arr.find(v).empty); } if( x . among ( 1, 2, 3 ) ) { } This doesn't work right now because you can't do property syntax on ints, but this might work in the near future. It does work if you're looking for an array: "hello" . among ( "world", "hello", "whatever" ); // compiles and runs correctly right now I picked "among" here since it does what it means and isn't a reserved word like "in" right now. The name doesn't really matter though.
May 28 2010
prev sibling next sibling parent "Robert Jacques" <sandford jhu.edu> writes:
On Fri, 28 May 2010 19:52:46 -0400, bearophile <bearophileHUGS lycos.com>  
wrote:
 Simen kjaeraas:
 Neat. Worthy an  keyword, I think. " flag enum foo {...}"

It's cute. But Don hates attributes :-) Recently I have created a thread about this, and some one has written a good enough implementation in normal D code, that can be "good enough".

Also, don't forget CTFE makes this simple to roll your own: enum foo { bar = 1 << 0, bar2 = 1<<1, ... }
May 28 2010
prev sibling next sibling parent "Simen kjaeraas" <simen.kjaras gmail.com> writes:
bearophile <bearophileHUGS lycos.com> wrote:

 Simen kjaeraas:

 I think you have missed one important point: that was not my list of  
 things I'd like in D2/D3. It contains some cute things, but it's first  
 of all a summary of the linked stackoverflow thread. My personal list of  
 desiderata for D3 is different.

You are right indeed. I misread that first sentence to its exact opposite. :p
 I think Walter said this can't be implemented :)

I think Walter just doesn't want to implement it. :p
 The items alignment of function arguments used by D tuples is not  
 fitting to return a struct.

Yeah. So, either we need thunks for this, or tuples need to carry alignment information.
 Neat. Worthy an  keyword, I think. " flag enum foo {...}"

It's cute. But Don hates attributes :-) Recently I have created a thread about this, and some one has written a good enough implementation in normal D code, that can be "good enough".

Screw Don. :p In all seriousness though, the implementation in that thread is good enough for me, and with the language change Andrei mentioned in the same thread, I would be a happy panda. -- Simen
May 28 2010
prev sibling next sibling parent Marianne Gagnon <auria.mg gmail.com> writes:
If there's one thing I need to agree with there, it's definitely having more
than one return value.

C/C++ have it really awful by passing pointers, and then you need to document
it's an "out parameter" (I know this has become very common to most of us, me
included, but when I first saw this - years and years ago - I was like "WTF,
parameters are defined as values going in" - I think that looking at the first
reaction of beginners can sometimes point you very directly at what doesn't
make sense but that experienced programmers don't notice because they're used
to it).

D makes this a bit cleaner by having a "out" keyword; but still I feel that
placing the first out value at the start of the function, then the second among
the parameters with some special keyword is still grouping unrelated things,
and splitting related ones.

So, in short, +1 ;) But I know this won't happen for D2. Guess I had to say it
anyway :)
May 28 2010
prev sibling next sibling parent Leandro Lucarella <llucax gmail.com> writes:
Don, el 29 de mayo a las 17:59 me escribiste:
It's cute. But Don hates attributes :-) Recently I have created
a thread about this, and some one has written a good enough
implementation in normal D code, that can be "good enough".

Screw Don. :p

<g>. I just think that shouldn't be an excuse to be careless -- anything with an in front is still part of the language. That's all.

It shouldn't, that's (was?) the point of . If the point of was to create a namespace for keywords, it sucks... -- Leandro Lucarella (AKA luca) http://llucax.com.ar/ ---------------------------------------------------------------------- GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145 104C 949E BFB6 5F5A 8D05) ---------------------------------------------------------------------- Bald men with no jobs and no money who live with their parents don't approach strange women. -- George Constanza
May 29 2010
prev sibling next sibling parent "Simen kjaeraas" <simen.kjaras gmail.com> writes:
Don <nospam nospam.com> wrote:

 <g>. I just think that   shouldn't be an excuse to be careless --  
 anything with an   in front is still part of the language. That's all.

I know, and I agree. It irritates me whenever people say foo is not a keyword. By that logic, we might as well say any word starting with a 'w' is not a keyword. Would get rid of that pesky 'while'. -- Simen
May 30 2010
prev sibling parent "Simen kjaeraas" <simen.kjaras gmail.com> writes:
Leandro Lucarella <llucax gmail.com> wrote:

 <g>. I just think that   shouldn't be an excuse to be careless --
 anything with an   in front is still part of the language. That's
 all.

It shouldn't, that's (was?) the point of . If the point of was to create a namespace for keywords, it sucks...

With compiler- or language-given keywords, there is no difference from other keywords, except they don't eat valid identifiers. With a user-configurable system, it's still part of a language, but that language is specific to the component in which the keywords are being used, and thus does not pollute the namespace of keywords for other projects. -- Simen
May 30 2010