July 09, 2012
On 7/9/12 3:52 AM, Jonathan M Davis wrote:
> On Sunday, July 08, 2012 23:37:29 Adam Wilson wrote:
>> First I want to mention two people who really helped make this day happen.
>
> Andrei is the one who was doing most of the work by reviewing and merging most
> of the pull requests which got merged.

Giving me credit for this is like giving credit the cable for electricity. I just let the great work of others flow.

>> Aliases for the 'dur' template. For example, you can now call 3.minutes()
>> and receive a Duration.
>
> As far as I'm concerned, 3.minutes() is a prime example of what's wong UFCS.
> UFCS can be very useful, but oh how I hate that syntax (completely aside from
> the particular function being called, I think that 3.anything() is horrible).
> But obviously not everyone agrees.
>
>> I also hope that these weekly Sunday Pull Audits will continue in the
>> future
>
> I actually hope that it _doesn't_ continue. If Andrei (or anyone else) wants
> to focus on dealing with pull requests on one particular day of the week,
> that's fine with me (it's his time to spend however he wants to), and I think
> that it's great that so much got done, but I think that we'd be better off if
> pull requests generally got dealt with more regularly rather than all at once.

Since this was a first, there's been a lot of pent-up work. Let's try to make one pass through each and every pull request every Sunday, the weekly work should be less than yesterday.


Andrei
July 09, 2012
Great work!!! Thanks guys!
July 09, 2012
On Mon, Jul 09, 2012 at 01:44:24PM +0200, Timon Gehr wrote:
> On 07/09/2012 08:37 AM, Adam Wilson wrote:
> >Object is now const-correct throughout D. This has been a dream for many of you. Today it is a reality.
> 
> PITA. Forced const can severely harm a code base that wants to be flexible -- it leaks implementation details and is infectuous.
[...]

Can you give an explicit example of code that is harmed by const correctness? IME, it rather helps code quality than harm it. Besides, since everything converts to const, it doesn't harm as much code as one might imagine (most code will be unchanged except where it matters -- which IMO is a good thing).

But YMMV.


T

-- 
This sentence is false.
July 09, 2012
Thanks for doing this! I haven't contributed yet, but it was worrisome hearing about various pull requests languishing for long periods. Now maybe I should go learn how to use git...

On Monday, 9 July 2012 at 07:56:40 UTC, Jonathan M Davis wrote:
> As far as I'm concerned, 3.minutes() is a prime example of what's wong UFCS.
> UFCS can be very useful, but oh how I hate that syntax (completely aside from
> the particular function being called, I think that 3.anything() is horrible).
> But obviously not everyone agrees.

Certainly not. C# has had this syntax since 1.0 (albeit not extension methods until v3.0, but IIRC you could always write 3.ToString() or 3.HashCode and, incidentally, int.Parse("3") etc. Ruby has it too (not UFCS per se, but you actually can add methods to any class including integers, IIRC)
July 09, 2012
On 7/9/12 11:13 AM, David Piepgrass wrote:
> Thanks for doing this! I haven't contributed yet, but it was worrisome
> hearing about various pull requests languishing for long periods. Now
> maybe I should go learn how to use git...

You definitely should get to the point where you can contribute to D via github. Once you're there, it's easy and rewarding to fix issues small and large, or to make creative contributions.

Andrei


July 09, 2012
On 07/09/2012 05:00 PM, H. S. Teoh wrote:
> On Mon, Jul 09, 2012 at 01:44:24PM +0200, Timon Gehr wrote:
>> On 07/09/2012 08:37 AM, Adam Wilson wrote:
>>> Object is now const-correct throughout D. This has been a dream for
>>> many of you. Today it is a reality.
>>
>> PITA. Forced const can severely harm a code base that wants to be
>> flexible -- it leaks implementation details and is infectuous.
> [...]
>
> Can you give an explicit example of code that is harmed by const
> correctness?

1.

Most code that gives amortized complexity guarantees, eg:

interface Map(K, V){
    V opIndex(K k) const;
    // ...
}

class SplayTree(K, V) : Map!(K, V) {
    // ???
}

2.

- hash table
- opApply compacts the table if it is occupied too sparsely, in order
  to speed up further iteration.
- toString iterates over all key/value pairs by the means of opApply.

Clearly, toString cannot be const in this setup.

3.

Often, objects can cache derived properties to speed up the code. With
'const-correctness' in place, such an optimization is not transparent
nor doable in a modular way.


> IME, it rather helps code quality than harm it.

I am not talking about code quality. I am talking about code
maintainability, extensibility and performance.

> Besides, since everything converts to const, it doesn't harm as much code as one
> might imagine (most code will be unchanged except where it matters --
> which IMO is a good thing).
>

Methods do not convert to const.


July 09, 2012
On Monday, 9 July 2012 at 16:02:38 UTC, Timon Gehr wrote:
> On 07/09/2012 05:00 PM, H. S. Teoh wrote:
>> On Mon, Jul 09, 2012 at 01:44:24PM +0200, Timon Gehr wrote:
>>> On 07/09/2012 08:37 AM, Adam Wilson wrote:
>>>> Object is now const-correct throughout D. This has been a dream for many of you. Today it is a reality.
>>>
>>> PITA. Forced const can severely harm a code base that wants to be flexible -- it leaks implementation details and is infectuous.
>> [...]
>>
>> Can you give an explicit example of code that is harmed by const
>> correctness?
>
> 1.
>
> Most code that gives amortized complexity guarantees, eg:
>
> interface Map(K, V){
>     V opIndex(K k) const;
>     // ...
> }
>
> class SplayTree(K, V) : Map!(K, V) {
>     // ???
> }
>
> 2.
>
> - hash table
> - opApply compacts the table if it is occupied too sparsely, in order
>   to speed up further iteration.
> - toString iterates over all key/value pairs by the means of opApply.
>
> Clearly, toString cannot be const in this setup.
>
> 3.
>
> Often, objects can cache derived properties to speed up the code. With
> 'const-correctness' in place, such an optimization is not transparent
> nor doable in a modular way.

I guess D does not have 'mutable' (like C++) to override const on methods? Caching anything slow-to-compute is my typical use case, and I know a hashtable design where the getter will move whatever value at finds to the front of a hash collision chain.

Oh, and this is interesting, I implemented a B+tree-like data structure* in C# that supports O(1) cloning. It marks the root as "frozen", making it copy-on-write. In order to clone in O(1), the children are not marked as frozen until later, when someone actually wants to mutate one of the copies. A user can also make the tree immutable in O(1) time and freely make mutable copies of it. This use case is pretty complex, so if I port this to D, I'd probably just cast away const/immutable where necessary. C#, of course, has no const so it was never a concern there.

*it's actually way fancier than that, I should really write a CodeProject article on it.

Of course, the trouble is, you can call any const method on an immutable object, so any const method that mutates needs to be thread safe. Many uses of C++ 'mutable' are thread-safe (e.g. most platforms guarantee atomic pointer-size writes, right? So two threads can cache the same int or two equivalent class instances, and it doesn't matter who wins)... but many other cases are not (e.g. the hashtable).

This is not a solved problem, is it. Ideas?

July 09, 2012
On Monday, July 09, 2012 18:34:14 David Piepgrass wrote:
> I guess D does not have 'mutable' (like C++) to override const on
> methods?

No, const is actually const. You can't modify anything which is const through that reference (or pointer) to that data. Casting away const and mutating something is undefined behavior. This provides much stronger guarantees and better enables compiler optimizations. More importantly, it's required for immutabel, since a const variable could actually be immutable underneath, in which case, depending on how it was constructed (e.g. it was put in ROM), it could result in a segfault if you tried to mutate it after casting away const.

http://stackoverflow.com/questions/4219600/logical-const-in-d

So, const gives you much greater benefits in D than in C++, but it also comes at a much higher cost. And it comes to a bit of a head in Object, because certain function _must_ be const in Object in order to work with const (namely opEquals, opCmp, toHash, and toString), but they _can't_ be const for certain schemes (e.g. caching) to work. The open question is how to fix this (or if it even can be fixed). But the current plan is to make all 4 of those functions be @safe pure const nothrow, and that _will_ make certain schemes effectively infeasible.

- Jonathan M Davis
July 09, 2012
On 7/9/12 12:34 PM, David Piepgrass wrote:
> I guess D does not have 'mutable' (like C++) to override const on
> methods?

It doesn't, which makes life difficult for certain idioms. On the upside, you can assume more than C++ does about immutable data.

> Caching anything slow-to-compute is my typical use case, and I
> know a hashtable design where the getter will move whatever value at
> finds to the front of a hash collision chain.

Yah, that won't be easy to implement. We have a couple of designs in mind for "mutable", but didn't get to it. Regarding advantages, think of this - if an immutable instance of your bring-to-front hashtable were used by multiple threads it would fail because it's "lying" about its being immutable. For now just don't use const for what ain't.

> Oh, and this is interesting, I implemented a B+tree-like data structure*
> in C# that supports O(1) cloning. It marks the root as "frozen", making
> it copy-on-write. In order to clone in O(1), the children are not marked
> as frozen until later, when someone actually wants to mutate one of the
> copies. A user can also make the tree immutable in O(1) time and freely
> make mutable copies of it. This use case is pretty complex, so if I port
> this to D, I'd probably just cast away const/immutable where necessary.
> C#, of course, has no const so it was never a concern there.
>
> *it's actually way fancier than that, I should really write a
> CodeProject article on it.
>
> Of course, the trouble is, you can call any const method on an immutable
> object, so any const method that mutates needs to be thread safe. Many
> uses of C++ 'mutable' are thread-safe (e.g. most platforms guarantee
> atomic pointer-size writes, right? So two threads can cache the same int
> or two equivalent class instances, and it doesn't matter who wins)...
> but many other cases are not (e.g. the hashtable).
>
> This is not a solved problem, is it. Ideas?

One idea we're considering is to plant a pointer to mutable data together with the mutex pointer in classes.


Andrei
July 09, 2012
On 07/09/2012 07:49 PM, Andrei Alexandrescu wrote:
> On 7/9/12 12:34 PM, David Piepgrass wrote:
>> I guess D does not have 'mutable' (like C++) to override const on
>> methods?
>
> It doesn't, which makes life difficult for certain idioms. On the
> upside, you can assume more than C++ does about immutable data.
>
>> Caching anything slow-to-compute is my typical use case, and I
>> know a hashtable design where the getter will move whatever value at
>> finds to the front of a hash collision chain.
>
> Yah, that won't be easy to implement. We have a couple of designs in
> mind for "mutable", but didn't get to it. Regarding advantages, think of
> this - if an immutable instance of your bring-to-front hashtable were
> used by multiple threads it would fail because it's "lying" about its
> being immutable. For now just don't use const for what ain't.
>

This is very inconvenient if the root of the class hierarchy uses it.