October 19, 2014
17-Oct-2014 16:42, Marco Leise пишет:
> Am Fri, 17 Oct 2014 00:42:24 +0000
> schrieb "IgorStepanov" <wazar@mail.ru>:
>
> OK, I've run into the same problem and there is no line
> number, just:
>
> Error: immutable method Lib.Sys.File.File.~this is not callable using a mutable object
> Error: mutable method Lib.Sys.File.File.~this is not callable using a immutable object
>
> haha! I should start from scratch.
>

Been there. Which implies that we can't have ref-counted const object (or ref-count has to leave outside of immutable section).

-- 
Dmitry Olshansky
October 20, 2014
Am Sun, 19 Oct 2014 22:33:32 +0400
schrieb Dmitry Olshansky <dmitry.olsh@gmail.com>:

> 17-Oct-2014 16:42, Marco Leise пишет:
> > Am Fri, 17 Oct 2014 00:42:24 +0000
> > schrieb "IgorStepanov" <wazar@mail.ru>:
> >
> > OK, I've run into the same problem and there is no line number, just:
> >
> > Error: immutable method Lib.Sys.File.File.~this is not callable using a mutable object Error: mutable method Lib.Sys.File.File.~this is not callable using a immutable object
> >
> > haha! I should start from scratch.
> >
> 
> Been there. Which implies that we can't have ref-counted const object (or ref-count has to leave outside of immutable section).

Moving the reference count out, means that as soon as you add another immutable layer around the object, it is in the way again. And at that point you turn to "looking it up" instead of pointing directly to the ref count. And then you wonder why it is impossible to use a pointer into an external table, but using a size_t as an array index to an external table is ok. And then you get flash backs of why it is likewise not possible to store mutable elements in an otherwise immutable container.

Wait a second... what is immutable trying to achieve again?

* Avoiding string copies, because we know no one can modify
  them.
  -> Ok, they have no reference count.

* Allowing for pure functions where all parameters are
  immutable.
  -> Reference counting would be an impure action.

* Act as shared at the same time.
  -> This is what I would like to make use of to avoid code
     duplication with shared/unshared methods.

-- 
Marco

October 20, 2014
On Monday, 20 October 2014 at 09:01:15 UTC, Marco Leise wrote:
> Moving the reference count out, means that as soon as you add
> another immutable layer around the object, it is in the way
> again. And at that point you turn to "looking it up" instead

c++ shared_ptr is implemented as a separate object, an extra indirection, but this indirection also makes weak_ptr and ref-counting immutable possible.

In performant code you only use shared_ptr to obtain ownership for a thread and raw pointers after that.
October 21, 2014
On Sunday, October 19, 2014 22:33:32 Dmitry Olshansky via Digitalmars-d wrote:
> 17-Oct-2014 16:42, Marco Leise пишет:
> > Am Fri, 17 Oct 2014 00:42:24 +0000
> > schrieb "IgorStepanov" <wazar@mail.ru>:
> >
> > OK, I've run into the same problem and there is no line number, just:
> >
> > Error: immutable method Lib.Sys.File.File.~this is not callable using a mutable object Error: mutable method Lib.Sys.File.File.~this is not callable using a immutable object
> >
> > haha! I should start from scratch.
>
> Been there. Which implies that we can't have ref-counted const object (or ref-count has to leave outside of immutable section).

Yeah. Ref-counting and const do not mix in D. The ref-counting would violate const unless it's in a wrapper object or in a table somewhere. The wrapper fails as soon as it ends up being const (either directly or because it's inside of another object that's been marked const). And having a table somewhere outside the object or any wrapper makes it so that it doesn't work with pure. There are some serious, practical downsides to transitive, physical const like D has. And I don't think that any of us really know yet where the line is between where const should and shouldn't be used. Too often, the solution is to use it everywhere or to use it nowhere. And some folks violate it and try and make it more like logical const (e.g. as I understand it, vibe.d does ref-counting with const objects by casting away const and then mutating the ref-count, which is definitely a risky thing to be doing and arguably should never be done - but with the strong restrictions of D's const, it's exactly the sort of thing that people are going to be tempted to do).

- Jonathan m Davis


October 21, 2014
On Mon, Oct 20, 2014 at 06:38:11PM -0700, Jonathan M Davis via Digitalmars-d wrote: [...]
> Yeah. Ref-counting and const do not mix in D. The ref-counting would violate const unless it's in a wrapper object or in a table somewhere. The wrapper fails as soon as it ends up being const (either directly or because it's inside of another object that's been marked const). And having a table somewhere outside the object or any wrapper makes it so that it doesn't work with pure. There are some serious, practical downsides to transitive, physical const like D has. And I don't think that any of us really know yet where the line is between where const should and shouldn't be used. Too often, the solution is to use it everywhere or to use it nowhere. And some folks violate it and try and make it more like logical const (e.g. as I understand it, vibe.d does ref-counting with const objects by casting away const and then mutating the ref-count, which is definitely a risky thing to be doing and arguably should never be done - but with the strong restrictions of D's const, it's exactly the sort of thing that people are going to be tempted to do).
[...]

I've run into this before, and I've been thinking about whether it would help for the language somehow to support tail-const of wrapper types, such that:

	/* Note: this is hypothetical syntax */
	tail_const(Wrapper!T) x;

gets translated to:

	Wrapper!(const(T)) x;

While this can already be manually done now, having it as a keyword (or otherwise dedicated syntax) allows things to work transparently, so that generic code never has to worry about what kind of wrapper(s) may be present in a user-passed object.

If used with a reference type, tail_const behaves like Rebindable.

If used with a non-template, non-reference, tail_const just "aliases" itself into plain old const, so it would behave sorta like logical const, except that it's actually checkable: the wrapper template can use the resulting physical const type to hold the wrapped type, thus maintaining D's physical const guarantees, while leaving other parts of the wrapper mutable so that it can implement things like reference counting, caching, etc..

Of course, this idea needs to be fleshed out more before it's actually usable, but it's something that has occurred to me multiple times, and may thus represent a pattern that could solve the logical vs.  physical const dilemma in D.


T

-- 
To err is human; to forgive is not our policy. -- Samuel Adler
October 21, 2014
On Tuesday, 21 October 2014 at 01:50:55 UTC, H. S. Teoh via Digitalmars-d wrote:
> 	/* Note: this is hypothetical syntax */
> 	tail_const(Wrapper!T) x;
>
> gets translated to:
>
> 	Wrapper!(const(T)) x;

Please note that an important reason for using const is multi-threading where you may want to accept multiple readers and one writer. So IMO non-const parts of an object should stay on a different cache lines from the const parts…
October 21, 2014
21-Oct-2014 05:38, Jonathan M Davis via Digitalmars-d пишет:
> On Sunday, October 19, 2014 22:33:32 Dmitry Olshansky via Digitalmars-d wrote:
>> 17-Oct-2014 16:42, Marco Leise пишет:
>>> Am Fri, 17 Oct 2014 00:42:24 +0000
>>> schrieb "IgorStepanov" <wazar@mail.ru>:
>>>
>>> OK, I've run into the same problem and there is no line
>>> number, just:
>>>
>>> Error: immutable method Lib.Sys.File.File.~this is not callable using a
>>> mutable object Error: mutable method Lib.Sys.File.File.~this is not
>>> callable using a immutable object
>>>
>>> haha! I should start from scratch.
>>
>> Been there. Which implies that we can't have ref-counted const object
>> (or ref-count has to leave outside of immutable section).
>
> Yeah. Ref-counting and const do not mix in D. The ref-counting would violate
> const unless it's in a wrapper object or in a table somewhere. The wrapper
> fails as soon as it ends up being const (either directly or because it's
> inside of another object that's been marked const). And having a table
> somewhere outside the object or any wrapper makes it so that it doesn't work
> with pure. There are some serious, practical downsides to transitive, physical
> const like D has.

They pretty much boil down to DO NOT use const everywhere, honestly.

> And I don't think that any of us really know yet where the
> line is between where const should and shouldn't be used. Too often, the
> solution is to use it everywhere or to use it nowhere. And some folks violate
> it and try and make it more like logical const (e.g. as I understand it,
> vibe.d does ref-counting with const objects by casting away const and then
> mutating the ref-count, which is definitely a risky thing to be doing and
> arguably should never be done - but with the strong restrictions of D's const,
> it's exactly the sort of thing that people are going to be tempted to do).
>

Awful.


-- 
Dmitry Olshansky
October 21, 2014
On Tuesday, October 21, 2014 22:26:26 Dmitry Olshansky via Digitalmars-d wrote:
> 21-Oct-2014 05:38, Jonathan M Davis via Digitalmars-d пишет:
> > Yeah. Ref-counting and const do not mix in D. The ref-counting would violate const unless it's in a wrapper object or in a table somewhere. The wrapper fails as soon as it ends up being const (either directly or because it's inside of another object that's been marked const). And having a table somewhere outside the object or any wrapper makes it so that it doesn't work with pure. There are some serious, practical downsides to transitive, physical const like D has.
>
> They pretty much boil down to DO NOT use const everywhere, honestly.

Yeah. Using it everywhere is definitely bad, but the question is then where you _should_ use it. It's quite useful for avoiding code duplication when immutable is involved (though templatizing everything fixes that too), and there are definitely times when the guarantee that something isn't going to mutated is useful (even if it's only for being able reason about the code well). So, abandoning const entirely seems like a bad idea, but you have to be very careful about where you do use it, or you paint yourself into a corner pretty quickly. pure can do the same thing, but it's nowhere near as bad in that respect.

- Jonathan M Davis


1 2 3
Next ›   Last »