Thread overview
Re: Frustrations with const
Mar 08, 2012
H. S. Teoh
Mar 08, 2012
H. S. Teoh
Mar 09, 2012
Timon Gehr
Mar 09, 2012
H. S. Teoh
Mar 09, 2012
Adam D. Ruppe
[OT] mutt settings (Was: Re: Frustrations with const)
Mar 09, 2012
H. S. Teoh
Mar 08, 2012
Timon Gehr
March 08, 2012
On Thu, Mar 08, 2012 at 08:22:05PM +0100, Timon Gehr wrote:
> On 03/08/2012 08:09 PM, H. S. Teoh wrote:
[...]
> >The problem is, how to write this function so that it can be called from *both* a const public method and a non-const public method? Since the method itself doesn't actually modify anything, it *should* in theory be possible to mark it as const:
> >
> >	const Slot *findSlot(Key key) { ... }
> >
> >However, because the const applies to 'this', the compiler insists that referencing anything via 'this', including reading a pointer to a slot, must also be const, so it refuses to let the return type be Slot*; it has to be const(Slot)*.
> >
> >But this is silly, because now the caller isn't allowed to modify the Slot either, so now I need to bloat the code with two identical copies of findSlot, one with const, and one without (since if it wasn't marked const, then a const method couldn't call it).
[...]
> inout(Slot)* findSlot(Key key) inout { ... }

Ahhh. Thanks!

But that still doesn't solve the problem:

	inout(Slot)* findSlot(Key key) inout {
		auto slot = slots[hash(key)];
		while (slot) {
			if (slot.hash == hash(key) && slot.key == key)
				return slot;

			// Error: cannot modify inout(Slot)*
--->			slot = slot.next;
		}
		return null;
	}



T

-- 
Help a man when he is in trouble and he will remember you when he is in trouble again.
March 08, 2012
On Thu, 08 Mar 2012 14:49:12 -0500, H. S. Teoh <hsteoh@quickfur.ath.cx> wrote:

> On Thu, Mar 08, 2012 at 08:22:05PM +0100, Timon Gehr wrote:
>> On 03/08/2012 08:09 PM, H. S. Teoh wrote:
> [...]
>> >The problem is, how to write this function so that it can be called  
>> from
>> >*both* a const public method and a non-const public method? Since the
>> >method itself doesn't actually modify anything, it *should* in theory  
>> be
>> >possible to mark it as const:
>> >
>> >	const Slot *findSlot(Key key) { ... }
>> >
>> >However, because the const applies to 'this', the compiler insists that
>> >referencing anything via 'this', including reading a pointer to a slot,
>> >must also be const, so it refuses to let the return type be Slot*; it
>> >has to be const(Slot)*.
>> >
>> >But this is silly, because now the caller isn't allowed to modify the
>> >Slot either, so now I need to bloat the code with two identical copies
>> >of findSlot, one with const, and one without (since if it wasn't marked
>> >const, then a const method couldn't call it).
> [...]
>> inout(Slot)* findSlot(Key key) inout { ... }
>
> Ahhh. Thanks!
>
> But that still doesn't solve the problem:
>
> 	inout(Slot)* findSlot(Key key) inout {
> 		auto slot = slots[hash(key)];

What is type slot, and how is it constructed?  This snippit isn't enough to provide help.

> 		while (slot) {
> 			if (slot.hash == hash(key) && slot.key == key)
> 				return slot;
>
> 			// Error: cannot modify inout(Slot)*

An exact message is preferrable.

> --->			slot = slot.next;
> 		}
> 		return null;
> 	}

-Steve
March 08, 2012
On 03/08/2012 08:49 PM, H. S. Teoh wrote:
> On Thu, Mar 08, 2012 at 08:22:05PM +0100, Timon Gehr wrote:
>> On 03/08/2012 08:09 PM, H. S. Teoh wrote:
> [...]
>>> The problem is, how to write this function so that it can be called from
>>> *both* a const public method and a non-const public method? Since the
>>> method itself doesn't actually modify anything, it *should* in theory be
>>> possible to mark it as const:
>>>
>>> 	const Slot *findSlot(Key key) { ... }
>>>
>>> However, because the const applies to 'this', the compiler insists that
>>> referencing anything via 'this', including reading a pointer to a slot,
>>> must also be const, so it refuses to let the return type be Slot*; it
>>> has to be const(Slot)*.
>>>
>>> But this is silly, because now the caller isn't allowed to modify the
>>> Slot either, so now I need to bloat the code with two identical copies
>>> of findSlot, one with const, and one without (since if it wasn't marked
>>> const, then a const method couldn't call it).
> [...]
>> inout(Slot)* findSlot(Key key) inout { ... }
>
> Ahhh. Thanks!
>
> But that still doesn't solve the problem:
>
> 	inout(Slot)* findSlot(Key key) inout {
> 		auto slot = slots[hash(key)];

inout(Slot)* slot = slots[hash(key)];

> 		while (slot) {
> 			if (slot.hash == hash(key)&&  slot.key == key)
> 				return slot;
>
> 			// Error: cannot modify inout(Slot)*
> --->			slot = slot.next;
> 		}
> 		return null;
> 	}
>
>
>
> T
>
March 08, 2012
On Thu, Mar 08, 2012 at 02:50:50PM -0500, Steven Schveighoffer wrote:
> On Thu, 08 Mar 2012 14:49:12 -0500, H. S. Teoh <hsteoh@quickfur.ath.cx> wrote:
> 
> >On Thu, Mar 08, 2012 at 08:22:05PM +0100, Timon Gehr wrote:
[...]
> >>inout(Slot)* findSlot(Key key) inout { ... }
> >
> >Ahhh. Thanks!
> >
> >But that still doesn't solve the problem:
> >
> >	inout(Slot)* findSlot(Key key) inout {
> >		auto slot = slots[hash(key)];
> 
> What is type slot, and how is it constructed?  This snippit isn't enough to provide help.
[...]

Slot is a struct, and slots is Slots*[].  But anyway, I found the problem.  I needed to explicitly declare slot as:

	inout(Slot)* slot = ...

because for whatever reason, auto turns it into inout(Slot*) which
cannot be modified.

I think inout is one of those things that really needs more thorough treatment for newbies, because coming from a C/C++ background I had no idea what was wrong. Now that I get it, it makes so much more sense.


T

-- 
Life would be easier if I had the source code. -- YHL
March 08, 2012
On Thu, 08 Mar 2012 15:06:19 -0500, H. S. Teoh <hsteoh@quickfur.ath.cx> wrote:

> On Thu, Mar 08, 2012 at 02:50:50PM -0500, Steven Schveighoffer wrote:
>> On Thu, 08 Mar 2012 14:49:12 -0500, H. S. Teoh
>> <hsteoh@quickfur.ath.cx> wrote:
>>
>> >On Thu, Mar 08, 2012 at 08:22:05PM +0100, Timon Gehr wrote:
> [...]
>> >>inout(Slot)* findSlot(Key key) inout { ... }
>> >
>> >Ahhh. Thanks!
>> >
>> >But that still doesn't solve the problem:
>> >
>> >	inout(Slot)* findSlot(Key key) inout {
>> >		auto slot = slots[hash(key)];
>>
>> What is type slot, and how is it constructed?  This snippit isn't
>> enough to provide help.
> [...]
>
> Slot is a struct, and slots is Slots*[].  But anyway, I found the
> problem.  I needed to explicitly declare slot as:
>
> 	inout(Slot)* slot = ...
>
> because for whatever reason, auto turns it into inout(Slot*) which
> cannot be modified.

I was wondering, because your error message identified it as inout(Slot)*, which should be modifiable...

> I think inout is one of those things that really needs more thorough
> treatment for newbies, because coming from a C/C++ background I had no
> idea what was wrong. Now that I get it, it makes so much more sense.

It's kind of a new concept to D even (since 2.056).  It's not completely fleshed out yet, Timon, Kenji, and Stuart have some great ideas on making it better.

This article might help: http://drdobbs.com/blogs/cpp/231902461

I plan to write a const/inout article at some point.

-Steve
March 09, 2012
On 03/08/2012 09:06 PM, H. S. Teoh wrote:
> On Thu, Mar 08, 2012 at 02:50:50PM -0500, Steven Schveighoffer wrote:
>> On Thu, 08 Mar 2012 14:49:12 -0500, H. S. Teoh
>> <hsteoh@quickfur.ath.cx>  wrote:
>>
>>> On Thu, Mar 08, 2012 at 08:22:05PM +0100, Timon Gehr wrote:
> [...]
>>>> inout(Slot)* findSlot(Key key) inout { ... }
>>>
>>> Ahhh. Thanks!
>>>
>>> But that still doesn't solve the problem:
>>>
>>> 	inout(Slot)* findSlot(Key key) inout {
>>> 		auto slot = slots[hash(key)];
>>
>> What is type slot, and how is it constructed?  This snippit isn't
>> enough to provide help.
> [...]
>
> Slot is a struct, and slots is Slots*[].  But anyway, I found the
> problem.  I needed to explicitly declare slot as:
>
> 	inout(Slot)* slot = ...
>
> because for whatever reason, auto turns it into inout(Slot*) which
> cannot be modified.

Probably it does not. What is the type of the "slots" hashtable?


>
> I think inout is one of those things that really needs more thorough
> treatment for newbies, because coming from a C/C++ background I had no
> idea what was wrong. Now that I get it, it makes so much more sense.
>
>
> T
>

This is a general issue with how auto infers types. It would often be useful to get the head-mutable type out of the type deduction instead of the actual type.
March 09, 2012
On Fri, Mar 09, 2012 at 11:24:46AM +0100, Timon Gehr wrote:
> On 03/08/2012 09:06 PM, H. S. Teoh wrote:
> >On Thu, Mar 08, 2012 at 02:50:50PM -0500, Steven Schveighoffer wrote:
[...]
> >>What is type slot, and how is it constructed?  This snippit isn't enough to provide help.
> >[...]
> >
> >Slot is a struct, and slots is Slots*[].  But anyway, I found the problem.  I needed to explicitly declare slot as:
> >
> >	inout(Slot)* slot = ...
> >
> >because for whatever reason, auto turns it into inout(Slot*) which
> >cannot be modified.
> 
> Probably it does not. What is the type of the "slots" hashtable?

Here are the relevant declarations:

    struct Slot
    {
        Slot   *next;
        hash_t  hash;
        Key     key;
        Value   value;

        this(hash_t h, Key k, Value v)
        {
            hash = h;
            key = k;
            value = v;
        }
    }

    struct Impl
    {
        Slot*[]  slots;
        size_t   nodes;

        // Prevent extra allocations for very small AA's.
        Slot*[4] binit;
    }


[...]
> >I think inout is one of those things that really needs more thorough treatment for newbies, because coming from a C/C++ background I had no idea what was wrong. Now that I get it, it makes so much more sense.
[...]
> This is a general issue with how auto infers types. It would often be useful to get the head-mutable type out of the type deduction instead of the actual type.

Yeah, that would be very useful.


T

-- 
Tech-savvy: euphemism for nerdy.
March 09, 2012
On Friday, 9 March 2012 at 15:30:50 UTC, H. S. Teoh wrote:
> Yeah, that would be very useful.

I think it was actually decided to do that... they
made the change for templates already.


PS: you might want to take a look at your mutt settings.
Your replies seem to have a truncated References header
which messes up threading in many clients.
March 09, 2012
On Fri, Mar 09, 2012 at 04:39:13PM +0100, Adam D. Ruppe wrote: [...]
> PS: you might want to take a look at your mutt settings.  Your replies seem to have a truncated References header which messes up threading in many clients.

Oh really? I don't think I changed any settings related to that. AFAICT it does generate the right references header. How do I fix it?

P.S. I do have mutt set on mailing list mode when replying to this list, though, and I usually reply using 'L'. Does that make a difference?


T

-- 
Computerese Irregular Verb Conjugation: I have preferences.  You have biases.  He/She has prejudices. -- Gene Wirchenko