View mode: basic / threaded / horizontal-split · Log in · Help
July 09, 2012
Re: Inherited const when you need to mutate
On Mon, Jul 09, 2012 at 08:07:22PM +0200, Timon Gehr wrote:
> 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.
[...]

I'm wondering if it makes any sense to have _also_ have non-const
versions of things like toString, for objects that want to implement
caching. So in contexts where const is not important, you can have
caching, network access, whatever you want, but for core language stuff
that needs to assume const, everything will still work (just a little
slower).

I'm thinking of the case where some objects might be kept in ROM, say,
in which case you can't cache within the class, even if you wanted to.
But for other instances of the class that are outside ROM, you can be
free to use the non-const, caching, network-accessing version of
toString to your heart's content.

After all, we have inout for a reason; here's a case where we need to do
the opposite of inout (have both a const and non-const version of a
method).

Or am I just spouting nonsense again? ;-)


T

-- 
Help a man when he is in trouble and he will remember you when he is in trouble again.
July 09, 2012
Re: Inherited const when you need to mutate
On Monday, July 09, 2012 11:53:05 H. S. Teoh wrote:
> I'm wondering if it makes any sense to have _also_ have non-const
> versions of things like toString, for objects that want to implement
> caching. So in contexts where const is not important, you can have
> caching, network access, whatever you want, but for core language stuff
> that needs to assume const, everything will still work (just a little
> slower).

That works as long as the const version still works. As soon as you _need_ to 
mutate in order to do opEquals, opCmp, toString, or toHash (as can happen with 
lazy loading schemes), it doesn't work. Basic caching should work with that 
though.

- Jonathan M Davis
July 09, 2012
Re: Congratulations to the D Team!
On Monday, July 09, 2012 10:01:25 Andrei Alexandrescu wrote:
> 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.

It's a team effort, but the processing of pull requests has been a definite 
bottleneck. I'd say that for Phobos, 90+% of the time it's either you or me 
who merges them, so if either of us is slow about it and/or another Phobos dev 
is needed to review a particular request, then pull requests tend to languish. 
It's even worse for druntime, since a lot of the time, Sean needs to get 
involved (particularly since some of us feel a bit unqualified reviewing and 
merging some of the critical stuff in druntime), and he seems to be very, very 
busy (though with Martin Nowak recently added as a committer for druntime, the 
situation may improve). So, the fact that you took the time to review and 
merge so many pull requests had a big impact.

- Jonathan M Davis
July 09, 2012
Re: Congratulations to the D Team!
On Mon, 09 Jul 2012 12:24:12 -0700, Jonathan M Davis <jmdavisProg@gmx.com>  
wrote:

> On Monday, July 09, 2012 10:01:25 Andrei Alexandrescu wrote:
>> 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.
>
> It's a team effort, but the processing of pull requests has been a  
> definite
> bottleneck. I'd say that for Phobos, 90+% of the time it's either you or  
> me
> who merges them, so if either of us is slow about it and/or another  
> Phobos dev
> is needed to review a particular request, then pull requests tend to  
> languish.
> It's even worse for druntime, since a lot of the time, Sean needs to get
> involved (particularly since some of us feel a bit unqualified reviewing  
> and
> merging some of the critical stuff in druntime), and he seems to be  
> very, very
> busy (though with Martin Nowak recently added as a committer for  
> druntime, the
> situation may improve). So, the fact that you took the time to review and
> merge so many pull requests had a big impact.
>
> - Jonathan M Davis

When I mentioned this post on IRC he specifically requested to be left out  
of it. So I did. However, I personally feel that his willingness to get in  
there and swing his +50 Hammer of Merging did in fact have a big impact on  
the successes of yesterday.

-- 
Adam Wilson
IRC: LightBender
Project Coordinator
The Horizon Project
http://www.thehorizonproject.org/
July 09, 2012
Re: Congratulations to the D Team!
On Monday, July 09, 2012 12:28:32 Adam Wilson wrote:
> When I mentioned this post on IRC he specifically requested to be left out
> of it. So I did. However, I personally feel that his willingness to get in
> there and swing his +50 Hammer of Merging did in fact have a big impact on
> the successes of yesterday.

Ah. Okay. It just seemed really odd to me that you were singling people out 
and didn't say anything about him.

I've never used the D IRC channel, so I have no clue what goes on in there. I 
lose enough time just dealing with the newsgroup.

- Jonathan M Davis
July 09, 2012
Re: Congratulations to the D Team!
On Monday, 9 July 2012 at 14:59:31 UTC, 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? 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 is like the third time I bring up this example around this 
topic, but forcing const harms wrappers of state-machine style 
interfaces, which many C libraries use.

Here's LuaObject.opEquals from LuaD:

	/**
	 * Compare this object to another with Lua's equality semantics.
	 * Also returns false if the two objects are in different Lua 
states.
	 */
	bool opEquals(T : LuaObject)(ref T o) @trusted
	{
		if(o.state != this.state)
			return false;

		push();
		o.push();
		scope(success) lua_pop(state, 2);

		return lua_equal(state, -1, -2);
	}

This works because LuaObject is currently a struct, but that's an 
irrelevant detail, it could just as well be a class in a 
different scenario.

This opEquals is only logically constant, not bitwise constant, 
hence it must not be const; similar to the caching scenario. Just 
trying to demonstrate that the issue is bigger than just caching 
- it's any logically constant comparison function.
July 10, 2012
Re: Congratulations to the D Team!
On 10 July 2012 01:02, Timon Gehr <timon.gehr@gmx.ch> wrote:
> 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.

Although I don't know what D's goals with const are, in C++,
const-correctness is often considered from the perspective of outside
the interface. A const member function guarantees that, from the point
of view of an entity using the object, its state will not change. This
does not guarantee that data stored in the object is not changing.
This allows for things like storing cached values. Unfortunately,
implementing this is more difficult than it might sound, e.g. in cases
such as  #2 above, particularly if you also want the compiler checking
that the const keyword can allow (which you should).

See here for more information:
http://www.parashift.com/c++-faq-lite/mutable-data-members.html

Geoff
July 10, 2012
Re: Congratulations to the D Team!
On 07/10/2012 01:57 AM, Geoffrey Biggs wrote:
> On 10 July 2012 01:02, Timon Gehr<timon.gehr@gmx.ch>  wrote:
>> ...
>> 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.
>>
>> ...
>> I am not talking about code quality. I am talking about code
>> maintainability, extensibility and performance.
>
> Although I don't know what D's goals with const are, in C++,
> const-correctness is often considered from the perspective of outside
> the interface. A const member function guarantees that, from the point
> of view of an entity using the object, its state will not change. This
> does not guarantee that data stored in the object is not changing.
> This allows for things like storing cached values. Unfortunately,
> implementing this is more difficult than it might sound, e.g. in cases
> such as  #2 above, particularly if you also want the compiler checking
> that the const keyword can allow (which you should).
>
> See here for more information:
> http://www.parashift.com/c++-faq-lite/mutable-data-members.html
>
> Geoff

Exactly! I don't think that the term 'const correctness' actually
has a meaning in D. It is a C++ term.
July 10, 2012
Re: Inherited const when you need to mutate
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++.

Bye,
bearophile
July 10, 2012
Re: Inherited const when you need to mutate
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++.

 Depends on what you are trying to do I suppose. The only 
mutation I would use is a new object (and cast away const to do a 
bulk copy which is otherwise annoying to do). If something is 
const(ant), it means you don't intend to change it. Perhaps this 
is a bad example:

 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. If the functions are 
const(ant) that you need to use, make non-const(ant) versions (or 
ensure the original(s) are unmodified) and/or disable the 
original ones (if you can/need, I think?).

 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.

 I hope I'm not rambling too much.
1 2 3 4 5 6 7
Top | Discussion index | About this forum | D home