May 14, 2012
On 14.05.2012 16:37, Steven Schveighoffer wrote:
> On Sun, 13 May 2012 16:52:15 -0400, Dmitry Olshansky
> <dmitry.olsh@gmail.com> wrote:
>
>> On 14.05.2012 0:48, Stewart Gordon wrote:
>>> On 13/05/2012 20:42, Walter Bright wrote:
>>> <snip>
>>>> I'd like to see std.stream dumped. I don't see any reason for it to
>>>> exist that std.stdio
>>>> doesn't do (or should do).
>>>
>>> So std.stdio.File is the replacement for the std.stream stuff?
>>>
>>> How does/will it provide all the different kinds of stream that
>>> std.stream provides, as well as the other kinds of stream that
>>> applications will need?
>>>
>>
>> I think I've seen proper replacement (or rather a draft of it). If
>> only Steven can be bothered to finish it :)
>
> Yes, I know.
>
> I hate starting things and then not finishing them. Especially when I've
> got so much of it completed...
>
> I'm going to make some time to finish this. I need probably a good few
> days (of solid time). Which means, based on my normal schedule, 2-3
> weeks. Most of the difficult parts are complete, I have a working buffer
> implementation, fast unicode translation (meaning UTF-8, UTF-16,
> UTF-16LE, UTF-32, and UTF-32LE), and a path to use RAII for seamless
> integration with std.stdio.File. I even have preliminary agreement from
> Andrei and Walter on a design (no guarantees they accept the final
> product, but I think I can massage it into acceptance).
>

Great!

> The one last puzzle to solve is sharing. File is this half-breed of
> sharing, because it contains a FILE *, which is a shared type, but File
> is not. Then it does some casting to get around the problems.

And  it all went nice and well till I spotted FILE*. Boom.
I mean I half assumed we are going to drop this crutch. Yep, too harsh. So probably leave it as *one* of file backends that features compatibility with C. Because IMHO using C-runtime this way is not buying us anything else other then C compatibility and "welcome to the world of unportable hacks where performance matters".

We need a
> better solution than this, but shared is so difficult to use, I think
> I'm going to have to implement something similar. It has been stipulated
> by Walter and Andrei that fixing this shared situation is a requirement
> for any new replacement. I have some ideas, but I have to play around to
> see if they actually work and make sense.
>
Probably it worths checking how std.stdio does it.

-- 
Dmitry Olshansky
May 14, 2012
On Monday, 14 May 2012 at 06:04:33 UTC, Mehrdad wrote:
> On Monday, 14 May 2012 at 03:19:57 UTC, Jonathan M Davis wrote:
>> I suspect that the folks who are looking for absolutely every CPU cycle and want caching and lazy-loading in their types
>
> It's not a CPU cycle issue.
>
> Caching/lazy-loading can make the difference between a window that freezes, and a window that doesn't.

You can still do this pretty easily.  You just have to cast away const.

You can even make it reusable.

mixin template TrustedToString() {
   const @safe pure nothrow string toString() {
      return unsafeToString();
   }
   final const @trusted pure nothrow string unsafeToString() {
      auto nonConstThis = cast(Unqual!(typeof(this)))this;
      return nonConstThis.trustedToString();
   }
}

class Foo {
 public:
   const @safe pure nothrow string toString() {
      return "Foo";
   }
}

class Bar : Foo {
 public:
   mixin TrustedToString;
   final pure @trusted nothrow string trustedToString() {
      if (cachedString.length == 0) {
         cachedString = "Bar";
      }
      return cachedString;
   }
   string cachedString;
}

unittest {
   auto f = new Foo();
   assert(f.toString() == "Foo");

   auto b = new Bar();
   assert(b.toString() == "Bar");
}
May 14, 2012
On Mon, 14 May 2012 09:20:57 -0400, Dmitry Olshansky <dmitry.olsh@gmail.com> wrote:

> On 14.05.2012 16:37, Steven Schveighoffer wrote:

>> The one last puzzle to solve is sharing. File is this half-breed of
>> sharing, because it contains a FILE *, which is a shared type, but File
>> is not. Then it does some casting to get around the problems.
>
> And  it all went nice and well till I spotted FILE*. Boom.
> I mean I half assumed we are going to drop this crutch. Yep, too harsh. So probably leave it as *one* of file backends that features compatibility with C. Because IMHO using C-runtime this way is not buying us anything else other then C compatibility and "welcome to the world of unportable hacks where performance matters".

I think the compromise agreed upon will be reasonable.  A constructed File will start out as a FILE * entity until you want to do anything more complex than writeln or readf.  At that point, it switches over to D-based backend automatically.  I don't want to be trying to implement advanced buffer-based techniques using FILE *, and I also don't want to restrict phobos' types to only doing things that FILE * can do well.  At the same time, we have this legacy with std.stdio.File that we have to maintain (the comments on my preliminary library were near-unanimous -- it cannot break existing code).

Walter has a very very hard requirement that D's equivalent stdout stdin, and stderr all interoperate with the C calls that use the equivalent C structures.  In other words, it is a hard requirement that writeln and printf interoperate.

Really, printf is the *only* reason to have this backwards compatibility "feature", and I strongly wish we could get rid of it.

That being said, if you *want* to avoid FILE *, it will definitely be possible.

> We need a
>> better solution than this, but shared is so difficult to use, I think
>> I'm going to have to implement something similar. It has been stipulated
>> by Walter and Andrei that fixing this shared situation is a requirement
>> for any new replacement. I have some ideas, but I have to play around to
>> see if they actually work and make sense.
>>
> Probably it worths checking how std.stdio does it.

I have.  I don't know how well it applies to my library.  One thing about using FILE * is that you have full knowledge of the known universe of FILE *.  This means you can control internally the interactions between threads, making sure that you don't have an unshared pointer unless the thing is locked (and this is what std.stdio does).

The problem is when you create an *extendable* system like the one I'm doing.  At that point, you can lock when you cast away shared, but you have no idea whether a method call is going to squirrel away an unshared reference to itself somewhere, so that when you go back to shared (and unlock), there's a leaked thread-local reference somewhere.

It may have to require documentation-based restrictions (i.e. not-compiler-enforced).  I haven't put enough thought into the possible means to do this.  Ideas are welcome!

-Steve
May 14, 2012
On Monday, May 14, 2012 15:27:41 John wrote:
> On Monday, 14 May 2012 at 06:04:33 UTC, Mehrdad wrote:
> > On Monday, 14 May 2012 at 03:19:57 UTC, Jonathan M Davis wrote:
> >> I suspect that the folks who are looking for absolutely every CPU cycle and want caching and lazy-loading in their types
> > 
> > It's not a CPU cycle issue.
> > 
> > Caching/lazy-loading can make the difference between a window that freezes, and a window that doesn't.
> 
> You can still do this pretty easily.  You just have to cast away const.

But that breaks the type system.

http://stackoverflow.com/questions/4219600/logical-const-in-d

Yes, you _can_ do it, but it's not actually guaranteed to work (casting away const and mutating a variable is _undefined_), and if you do it with an object which is actually immutable, then things could go _very_ wrong (e.g. segfault).

- Jonathan M Davis
May 14, 2012
On 05/14/2012 06:10 AM, Chris Cain wrote:
> On Monday, 14 May 2012 at 02:57:57 UTC, Mehrdad wrote:
>> The problem is that it's unavoidable.
>>
>> i.e. you can't say "don't mark it as const if it isn't const",
>> because, practically speaking, it's being forced onto the programmers
>> by the language.
>
> You're really against const in this language, huh?
>

I guess this is not the most important point.
He has been trying to use const like in OO-ish C++.
This just does not work, because D const is detrimental to OO
principles when used that way.
The proposal is about _enforcing_ C++-like usage of const.
May 14, 2012
On Monday, 14 May 2012 at 16:53:24 UTC, Timon Gehr wrote:
> On 05/14/2012 06:10 AM, Chris Cain wrote:
>> On Monday, 14 May 2012 at 02:57:57 UTC, Mehrdad wrote:
>>> The problem is that it's unavoidable.
>>>
>>> i.e. you can't say "don't mark it as const if it isn't const",
>>> because, practically speaking, it's being forced onto the programmers
>>> by the language.
>>
>> You're really against const in this language, huh?
>>
>
> I guess this is not the most important point.
> He has been trying to use const like in OO-ish C++.
> This just does not work, because D const is detrimental to OO
> principles when used that way.
> The proposal is about _enforcing_ C++-like usage of const.

but c++ has the 'mutable' keyword as an easy escape route... which saved me a bunch of times... guess one can emulate it with a library-solution using nested classes? But... what about structs?

class Outer
{
  int i = 6; // mutable

  class Inner {
    int y=0;

    int foo() const
    {
      // ++y; // fail
      return ++i; // look ma, mutable const
    }
  }
  Inner inner;
  this()
  {
    inner = new Inner;
  }
  alias inner this;
}
May 14, 2012
Le 14/05/2012 00:56, Mehrdad a écrit :
> On Sunday, 13 May 2012 at 22:51:05 UTC, Jonathan M Davis wrote:
>> Anything that absolutely requires them will probably have to either
>> have to break the type system or use _other_ functions with the same
>> functionality but without those attributes. In some cases though,
>> providing overloads which aren't const, pure, etc. should work though.
>> If you want it to be otherwise, you're going to have to convince
>> Walter, and I think that it's pretty clear that this is the way that
>> it's going to have to be thanks to how const et al. work.
>
> This is *exactly* the sort of problem I was referring to in my
> const(rant) thread, so to speak.
>
> These const-related issues make D, simply speaking, *HARD TO USE*.
> (Yes, that means even harder then C++ in some cases.)
>
> When people say it's painful to find workarounds to problems in D, I
> hope -- at the very least -- no one will be surprised as to why.

The only reason I'd see a toSting function as non pure or non const is memoize. It can be tackled with lib support in phobos.

What are other uses cases ?
May 14, 2012
On Monday, 14 May 2012 at 18:52:06 UTC, deadalnix wrote:
> The only reason I'd see a toSting function as non pure or non const is memoize. It can be tackled with lib support in phobos.
> What are other uses cases ?

Not necessarily 'memoization' -- you could be instead querying
another object for this information, which may not be const.
(Say, a network connection.)
May 14, 2012
On 14-05-2012 21:04, Mehrdad wrote:
> On Monday, 14 May 2012 at 18:52:06 UTC, deadalnix wrote:
>> The only reason I'd see a toSting function as non pure or non const is
>> memoize. It can be tackled with lib support in phobos.
>> What are other uses cases ?
>
> Not necessarily 'memoization' -- you could be instead querying
> another object for this information, which may not be const.
> (Say, a network connection.)

That's actually a very, very good point.

-- 
- Alex
May 14, 2012
On 5/14/12, Steven Schveighoffer <schveiguy@yahoo.com> wrote:
> Really, printf is the *only* reason to have this backwards compatibility "feature", and I strongly wish we could get rid of it.

printf is also unique in that it works when called in class destructors, which is sometimes needed for debugging (unlike writef which wants to allocate memory and then throws).