July 11, 2012
On 07/11/2012 07:46 PM, Andrei Alexandrescu wrote:
> On 7/11/12 1:04 PM, Timon Gehr wrote:
>> On 07/11/2012 06:45 PM, Andrei Alexandrescu wrote:
>>> On 7/11/12 12:30 PM, H. S. Teoh wrote:
>>>> It *is* a problem when you're talking about abstractions. If I have
>>>> million node binary trees and I'm testing for equality, I'd like to be
>>>> able to cache the results. But being forced to use const means I can't
>>>> cache anything. And this isn't just about caching; if my tree is
>>>> partially stored in the database, and I have a DB connection object in
>>>> my tree class, then I can't use opEquals because I can't modify the DB
>>>> state (which is impractical if I have to actually use it to make DB
>>>> queries -- the DB engine may have to cache DB pages, etc.). Any
>>>> abstraction of opEquals beyond the bitwise level cannot be implemented.
>>>
>>> How about the static hash/cache?
>>>
>>> Andrei
>>
>> Will break horribly as soon as it is discovered that the methods should
>> be pure as well.
>
> I don't think they should be pure. Do you have reasons to think otherwise?
>
> Andrei

I think they should be pure as much as I think they should be const.

The reasoning is analogous for both.

We have immutable class instances that want to provide the methods => make them const.

We have pure functions that want to provide the methods => make them pure.

This reasoning is not taking into account the whole picture because

We have implementations of those methods that want to use non-const
methods in their implementation. (eg. database connection)

We have implementation of those methods that want to use non-pure
methods in their implementation (eg. database connection, logging)
July 11, 2012
On Wed, Jul 11, 2012 at 01:50:23PM -0400, Andrei Alexandrescu wrote:
> On 7/11/12 1:49 PM, deadalnix wrote:
> >I think they should. Comparing the same object 2 time should definitively have the same result back, otherwise things will go horribly wrong soon enough.
> 
> Yah, but e.g. a comparison may log something.
[...]

I think it's a given that purity is out the window once debugging is involved.

(I assume comparison logging is only for debugging, otherwise you must have a very very strange use for comparison operators.)


T

-- 
"Holy war is an oxymoron." -- Lazarus Long
July 11, 2012
On Wed, Jul 11, 2012 at 01:49:53PM -0400, Andrei Alexandrescu wrote:
> On 7/11/12 1:40 PM, Jakob Ovrum wrote:
> >Some classes don't lend themselves to immutability. Let's take something obvious like a class object representing a dataset in a database. How is an immutable instance of such a class useful?
> 
> This is a good point. It seems we're subjecting all classes to certain limitations for the benefit of a subset of those classes.
[...]

Yes, that's what we've been trying to say for the last, oh, 100 messages? ;-)


T

-- 
Дерево держится корнями, а человек - друзьями.
July 11, 2012
On Wed, Jul 11, 2012 at 08:01:44PM +0200, deadalnix wrote:
> On 11/07/2012 19:49, Andrei Alexandrescu wrote:
> >On 7/11/12 1:40 PM, Jakob Ovrum wrote:
> >>Some classes don't lend themselves to immutability. Let's take something obvious like a class object representing a dataset in a database. How is an immutable instance of such a class useful?
> >
> >This is a good point. It seems we're subjecting all classes to certain limitations for the benefit of a subset of those classes.
> >
> >Andrei
> 
> Did you saw the proposal of feep/tgehr on #d ?
> 
> It basically state that you can overload a const method with a non
> const one if :
>  - You don't mutate any data that belong to the parent.
>  - You are prevented to create any immutable instance of that classe
> or any subclasse.

+1, very good, I like this idea!

It parallels my idea about the base class being const but not the derived class, except that this is a much better implementation (no need for new syntax, fits in with the existing type system). So basically the const in const(BaseClass) applies only to the members inherited from BaseClass, and the derived class's members are allowed to mutate.


T

-- 
"Hi." "'Lo."
July 11, 2012
On 7/11/12 2:01 PM, deadalnix wrote:
> On 11/07/2012 19:49, Andrei Alexandrescu wrote:
>> On 7/11/12 1:40 PM, Jakob Ovrum wrote:
>>> Some classes don't lend themselves to immutability. Let's take something
>>> obvious like a class object representing a dataset in a database. How is
>>> an immutable instance of such a class useful?
>>
>> This is a good point. It seems we're subjecting all classes to certain
>> limitations for the benefit of a subset of those classes.
>>
>> Andrei
>
> Did you saw the proposal of feep/tgehr on #d ?
>
> It basically state that you can overload a const method with a non const
> one if :
> - You don't mutate any data that belong to the parent.
> - You are prevented to create any immutable instance of that classe or
> any subclasse.

Haven't seen that, but on first look it seems promising.

Andrei
July 11, 2012
On 7/11/12 2:03 PM, Timon Gehr wrote:
> I think they should be pure as much as I think they should be const.
>
> The reasoning is analogous for both.
>
> We have immutable class instances that want to provide the methods =>
> make them const.
>
> We have pure functions that want to provide the methods => make them pure.
>
> This reasoning is not taking into account the whole picture because
>
> We have implementations of those methods that want to use non-const
> methods in their implementation. (eg. database connection)
>
> We have implementation of those methods that want to use non-pure
> methods in their implementation (eg. database connection, logging)

The essential difference is there's no "pure" object, so there's no motivation to plant "pure" on its methods.

Andrei
July 11, 2012
On Wednesday, 11 July 2012 at 18:10:04 UTC, H. S. Teoh wrote:
> On Wed, Jul 11, 2012 at 08:01:44PM +0200, deadalnix wrote:
...
>> Did you saw the proposal of feep/tgehr on #d ?
>> 
>> It basically state that you can overload a const method with a non
>> const one if :
>>  - You don't mutate any data that belong to the parent.
>>  - You are prevented to create any immutable instance of that classe
>> or any subclasse.
>
> +1, very good, I like this idea!

It is a trade-off, but relatively nice one, IMO.
July 11, 2012
On 7/11/12 2:05 PM, H. S. Teoh wrote:
> On Wed, Jul 11, 2012 at 01:50:23PM -0400, Andrei Alexandrescu wrote:
>> On 7/11/12 1:49 PM, deadalnix wrote:
>>> I think they should. Comparing the same object 2 time should
>>> definitively have the same result back, otherwise things will go
>>> horribly wrong soon enough.
>>
>> Yah, but e.g. a comparison may log something.
> [...]
>
> I think it's a given that purity is out the window once debugging is
> involved.

Logging is not debugging.

Andrei
July 11, 2012
On 7/11/12 2:07 PM, H. S. Teoh wrote:
> On Wed, Jul 11, 2012 at 01:49:53PM -0400, Andrei Alexandrescu wrote:
>> On 7/11/12 1:40 PM, Jakob Ovrum wrote:
>>> Some classes don't lend themselves to immutability. Let's take
>>> something obvious like a class object representing a dataset in a
>>> database. How is an immutable instance of such a class useful?
>>
>> This is a good point. It seems we're subjecting all classes to
>> certain limitations for the benefit of a subset of those classes.
> [...]
>
> Yes, that's what we've been trying to say for the last, oh, 100
> messages? ;-)

I didn't see that, sorry. What's the closest quote?

Andrei


July 11, 2012
On Wednesday, 11 July 2012 at 02:02:52 UTC, Andrei Alexandrescu wrote:
> On 7/10/12 9:45 PM, Timon Gehr wrote:
>> I do not desire logical const as a language feature. But conservative type systems are not good for everything. The root of the class hierarchy needs to be good for everything. Object is not an adequate root any more.
>
> How about we consider just stiffening that upper lip and implement comparison and hashing without modifying their target?

 I remember offering a suggested structure for cached hashing for const/immutable data (mostly a test/example)... If you follow a similar setup you could get the 'logical const' while following the language rules; Namely the mutable state is separate from the const state. Course it's sorta a wrapper, but that's better than breaking the type system or trying to do something else equally questionable.

It went something like...

struct CachedHash(T) {
 T value;
 uint hash;
 alias value this;
 uint toHash() {
  if (!hash)
   hash = value.toHash();
  return hash;
 }
}