May 16, 2013
On Thu, 16 May 2013 01:40:51 +0200, Andrej Mitrovic <andrej.mitrovich@gmail.com> wrote:

> On 5/16/13, Nick Sabalausky <SeeWebsiteToContactMe@semitwist.com> wrote:
>>> I wasn't around back then. :)
>>>
>>
>> You must be very young, quite a prodigy, really ;)
>
> I'm still learning the alphabet, I'm only at D now!

Now try writing that using only the letters you supposedly know. :p

-- 
Simen
May 16, 2013
deadalnix, el 16 de May a las 05:48 me escribiste:
> On Wednesday, 15 May 2013 at 20:08:23 UTC, Leandro Lucarella wrote:
> >OK, yeah, I thought I read 10 months somewhere and didn't do the
> >math
> >myself. 2.5 months is still high for my taste (and I insist, only
> >if is
> >just a marketing issue and not the lack of power to edit the
> >talks), but
> >more reasonable.
> 
> Completely off topic : your NG client is splitting the discussion, creating a new one on every answer you make.

Thanks for pointing that out, but I think there is a problem with the forum software (I guess you are reading the NG using the web forums?). My client properly set the In-Reply-To: header. I checked manually the e-mail you replied to and have the correct Message-ID: of the post I was replying to in the In-Reply-To: header.

-- 
Leandro Lucarella (AKA luca)                     http://llucax.com.ar/
----------------------------------------------------------------------
GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145  104C 949E BFB6 5F5A 8D05)
----------------------------------------------------------------------
Breathe, breathe in the air.
Don't be afraid to care.
Leave but don't leave me.
Look around and choose your own ground.
May 16, 2013
On Wednesday, 15 May 2013 at 17:32:14 UTC, Jonathan M Davis wrote:
> You probably should actually quote part of the message so that it's easier to
> figure out exactly which message you're replying to it.

It is hard to quote the video :) I was referring to the part starting somewhere here: http://youtu.be/mPr2UspS0fE?t=39m35s

I know that almost all Phobos stuff is either isSomeString+template one or const(char)[] one, but I was curious how this works in context of Ali's presentation.

Negative side of const(char)[] vs immutable(char)[] is that function on its own no longer guarantees thread safety, it relies on the behavior of the caller, which is not that good from the point of view of the type system.
May 16, 2013
On Wed, 15 May 2013 18:32:03 +0100, Jonathan M Davis <jmdavisProg@gmx.com> wrote:
> What's less clear is what to do when a function accepts strings but isn't really operating on them (e.g stuff in std.file or std.net.curl), as they may need immutable(char)[]. In that case, it depends on what's being done with the string. For better or worse though, at this point, I think that it's most common to just accept string for those cases. It's not something that always has a clearcut answer though.

I agree with the first bit, but I think we can make a clear-cut decision on this last..

To me it comes down to a Q of responsibility.

Should a function/method (like those in std.file) require that the argument will not change for the lifetime of the function/method call, or is it reasonable for the function/method to assume the caller will ensure that.

Taking by immutable(char) will guarantee it will not change (ignoring blunt forced cast) whereas const(char) will not, but there is an implicit assumption that it wont change and the caller should guarantee that.

So, who's responsibility is it to ensure the function/method call executes without errors caused by mutable shared data?

I think it's the callers responsibility and think that const(char) is the better choice in cases like this, my reasoning as follows..

1. Callers should already be protecting shared mutable state before using it, this is a common and well understood pattern which cannot be avoided even if we use immutable(char) arguments (caller still needs to ensure shared state is not mutated while they make the immutable copy to pass).

2. In most cases, in most code shared data is less common, especially for calls to functions/methods like those mentioned here.  So, we chose the option which is nicer for the common case, and const(char) is it.

3. const(char) does not require duplication of arguments by caller or callee so is more efficient, one of D's primary goals and a good baseline to build upon.

So, I think in cases where the function/method doesn't need to retain the argument for longer than the lifetime of the call it should accept const(char), otherwise as you mentioned earlier it's better to simply require the caller provide the immutable(char) you require.

This decision has a nice side-effect of implicitly documenting the lifetime/usage of arguments, const(char) means call lifetime, immutable(char) means longer, possibly indefinitely (until termination).

Thoughts?

R

-- 
Using Opera's revolutionary email client: http://www.opera.com/mail/
May 16, 2013
On Thursday, 16 May 2013 at 10:13:28 UTC, Regan Heath wrote:
> ...

I agree that this is a caller responsibility. What leaves me in doubts is how this responsibility is enforced though. With const nothing in type system prevents caller to violate that "contract" and mutate data during function call. Because, well, const does not guarantee that data is not mutated and thus it is a valid action.

Contrary, immutable is absolutely strict requirement from a function that caller must take care of passed argument during the function call or fall into undefined behavior. Explicit usage of "assumeUnique" by caller is clear sign for a type system "yes, I know what I am doing, I am responsible". And no accidents possible.

However, another issue arises then (my first comment), one I guessed "scope" may help with.

May 16, 2013
On Thu, 16 May 2013 11:25:48 +0100, Dicebot <m.strashun@gmail.com> wrote:

> On Thursday, 16 May 2013 at 10:13:28 UTC, Regan Heath wrote:
>> ...
>
> I agree that this is a caller responsibility. What leaves me in doubts is how this responsibility is enforced though. With const nothing in type system prevents caller to violate that "contract" and mutate data during function call. Because, well, const does not guarantee that data is not mutated and thus it is a valid action.

True, it's not enforced.  But, that's because the responsibility lies with the caller, and I think this is a reasonable position to take in these cases (std.file methods which use but do not retain the argument post-call)

> Contrary, immutable is absolutely strict requirement from a function that caller must take care of passed argument during the function call or fall into undefined behavior. Explicit usage of "assumeUnique" by caller is clear sign for a type system "yes, I know what I am doing, I am responsible". And no accidents possible.

Sure, but it's more verbose, and therefore annoying for the general case (where the data is not shared).

And..

The issue here is not common (because shared data is not common) /and/ where shared data is used it should already be protected (because that's the existing pattern).

So that leaves us a very small number of cases which are "broken" and the solution to all of them is to protect the shared data(*) /not/ to call assumeUnique.  The cases where assumeUnique could be used, so could const(char).

Basically I think the assumeUnique idea is only useful where const(char) is useful and const(char) is far nicer.

(*) you cannot even just call idup, because what if the data is in the process of mutating when you do?  You have to protect the shared data with a mutex or similar.

Regan

-- 
Using Opera's revolutionary email client: http://www.opera.com/mail/
May 16, 2013
On Thursday, 16 May 2013 at 10:41:51 UTC, Regan Heath wrote:
> True, it's not enforced.  But, that's because the responsibility lies with the caller, and I think this is a reasonable position to take in these cases (std.file methods which use but do not retain the argument post-call)

You see, if it is not enforced, than no one has any real responsibility. Multi-threading based on convention has been used quite a lot in C/C++ according to my experience it sucks. D developers has done a lot of work in pursuing type system that is aware of multi-threading and can make certain enforcements / provide guarantees. It makes no sense to stop in the midway.

One of D slogans I remember was "Safe by default, efficient when needed". This is exactly one of such cases. Any type contract should be stated explicitly. Everywhere.
May 16, 2013
On Thu, 16 May 2013 12:06:18 +0100, Dicebot <m.strashun@gmail.com> wrote:

> On Thursday, 16 May 2013 at 10:41:51 UTC, Regan Heath wrote:
>> True, it's not enforced.  But, that's because the responsibility lies with the caller, and I think this is a reasonable position to take in these cases (std.file methods which use but do not retain the argument post-call)
>
> You see, if it is not enforced, than no one has any real responsibility. Multi-threading based on convention has been used quite a lot in C/C++ according to my experience it sucks. D developers has done a lot of work in pursuing type system that is aware of multi-threading and can make certain enforcements / provide guarantees. It makes no sense to stop in the midway.

You're missing my main point.

The number of actually "broken" cases are small and the solution is always always always to protect the shared data.  assumeUnique cannot help in these cases, so the caller ends up calling idup.  The caller cannot safely call idup unless the shared data is protected.  So, all roads lead to - protect the shared data.  Given that, const(char) is 100% perfectly safe.

> One of D slogans I remember was "Safe by default, efficient when needed". This is exactly one of such cases. Any type contract should be stated explicitly. Everywhere.

As shown above, just using immutable(char) does not ensure it is safe.  The caller could use assumeUnique mistakenly, or call idup without protecting the shared state, both are subtle bugs and the only solution is - protect the shared data.

Any impression of complete safety from immutable(char) is therefore false.

R

-- 
Using Opera's revolutionary email client: http://www.opera.com/mail/
May 16, 2013
On Thursday, May 16, 2013 11:13:27 Regan Heath wrote:
> So, I think in cases where the function/method doesn't need to retain the argument for longer than the lifetime of the call it should accept const(char), otherwise as you mentioned earlier it's better to simply require the caller provide the immutable(char) you require.

Well, as I said, the decision depends on what you're doing with the string. If
you're just operating on it and not storing it or duping it, then
const(char)[] or inout(char)[] makes the most sense, whereas if you're storing
it or duping it, odds are that immutable(char)[] makes the most sense.

- Jonathan M Davis
May 16, 2013
On Thursday, May 16, 2013 11:13:27 Regan Heath wrote:
> So, who's responsibility is it to ensure the function/method call executes without errors caused by mutable shared data?

I think that for the most part, the question of thread-safety and const that you've been discussing is moot. const by itself is thread-local by definition. Whether you use const or immutable really has no impact on thread safety - not from the perspective of the function being called anyway. The only way that you can end up having to worry about thread-safety in such functions is if the caller casts away shared on a variable and then passes it to the function. And by definition, at that point it's the responsibility of the one doing the cast to make sure that they don't break the type system (since they've circumvented the type system by casting away shared). immutable avoids even that issue, because it's implicitly shared but can be treated by code as being thread- local (since it won't change), but the function accepting the string doesn't care. Worrying about that is completely up to the code that cast away shared.

Without shared, the one area where the function risks the data changing when it was passed as const is when that function has another, mutable handle to the same data, and the data is mutated via that handle. If the function is never mutated the same type as the const parameter (either directly or indirectly), then there's no chance that the const parameter will change.

So, while using immutable reduces the odds of threading issues, I think that it's quite clear that the function itself doesn't have to worry about that. And the type system won't even _let_ it worry about it, because the type system assumes that const without shared is thread-local, and without passing the appropriate mutex to the function, the function wouldn't be able to protect itself from mutation from another thread anyway (in the case where the const parameter was shared underneath the hood with shared cast away).

- Jonathan M Davis