Re: Why is it not possible to write to a file from a const member function ?

2016-03-12 Thread user42 via Digitalmars-d-learn

On Saturday, 12 March 2016 at 15:32:39 UTC, Mike Parker wrote:

On Saturday, 12 March 2016 at 14:02:31 UTC, user42 wrote:


Why is this thing not compiling ?
Or, in other words, how is is possible to log something to a 
file from a const member function ?




Const member functions functions are not allowed to mutate any 
member state at all. This includes the state of any object 
instances that are members. Since the write method of the File 
type is not declared as const, then you can not call it on a 
member of type File from inside a const member function. 
Logging, by its very definition, mutates state.


Move the File instance outside of the class and it works.

import std.stdio;
private File f;
static this() { f = stdout; }

class X
{
  void p(string s) const
  {
 f.writeln!(string)(s);
  }
}

class Y
{
  private string s = "Y";

  override string toString() const
  {
 return s;
  }
}

void main()
{
  auto x = new X;
  auto y = new Y;

  import std.conv: to;
  x.p(to!string(y));
}


Thanks for your reply.
Unfortunately it only solves the problem for this particular 
snippet.


The most interesting part of your reply is this line:
Since the write method of the File type is not declared as 
const,


At a quick glance I suppose it's because of the locking in 
LockingTextWriter.


I think I will probably pass this stuff to a C implementation, or 
override toString non-const, since adding const to it started 
this const avalanche in the first place.


Anyways, thanks for your input and have a nice weekend.


Re: Why is it not possible to write to a file from a const member function ?

2016-03-12 Thread Mike Parker via Digitalmars-d-learn

On Saturday, 12 March 2016 at 14:02:31 UTC, user42 wrote:


Why is this thing not compiling ?
Or, in other words, how is is possible to log something to a 
file from a const member function ?




Const member functions functions are not allowed to mutate any 
member state at all. This includes the state of any object 
instances that are members. Since the write method of the File 
type is not declared as const, then you can not call it on a 
member of type File from inside a const member function. Logging, 
by its very definition, mutates state.


Move the File instance outside of the class and it works.

import std.stdio;
private File f;
static this() { f = stdout; }

class X
{
  void p(string s) const
  {
 f.writeln!(string)(s);
  }
}

class Y
{
  private string s = "Y";

  override string toString() const
  {
 return s;
  }
}

void main()
{
  auto x = new X;
  auto y = new Y;

  import std.conv: to;
  x.p(to!string(y));
}


Why is it not possible to write to a file from a const member function ?

2016-03-12 Thread user42 via Digitalmars-d-learn

Hi

I have the following snippet to illustrate my problem/question:

class X
{
  import std.stdio: write, File, stdout;

  private File* f = 

  void p(string s) const
  {
 f.write(s);
  }
}

class Y
{
  private string s = "Y";

  override string toString() const
  {
 return s;
  }
}

void main()
{
  auto x = new X;
  auto y = new Y;

  import std.conv: to;
  x.p(to!string(y));
}

Why is this thing not compiling ?
Or, in other words, how is is possible to log something to a file 
from a const member function ?


Thanks in advance


Re: const member function

2015-02-23 Thread ketmar via Digitalmars-d-learn
On Mon, 23 Feb 2015 09:12:33 +, rumbu wrote:

 On Saturday, 21 February 2015 at 15:26:28 UTC, ketmar wrote:
 On Sat, 21 Feb 2015 08:27:13 +, rumbu wrote:

 My question was not how I do this, I know already. My question was if
 there is another way to safely call a non-const instance function on a
 const object.

 is there a way to been safely hit by a truck?
 
 I thought if there is some language construct similar to @trusted for
 @safe, applicable to const member functions. You can be safely hit by a
 truck if I tell you that there is no truck around :)

do not make it `const` at all. i see something very strange in making 
something `const` just to find the way to remove constness. just stop 
writing C++ code in D.

signature.asc
Description: PGP signature


Re: const member function

2015-02-23 Thread rumbu via Digitalmars-d-learn

On Saturday, 21 February 2015 at 15:26:28 UTC, ketmar wrote:

On Sat, 21 Feb 2015 08:27:13 +, rumbu wrote:

My question was not how I do this, I know already. My question 
was if
there is another way to safely call a non-const instance 
function on a

const object.


is there a way to been safely hit by a truck?


I thought if there is some language construct similar to @trusted 
for @safe, applicable to const member functions. You can be 
safely hit by a truck if I tell you that there is no truck around 
:)






Re: const member function

2015-02-23 Thread Jonathan M Davis via Digitalmars-d-learn
On Monday, February 23, 2015 09:12:33 rumbu via Digitalmars-d-learn wrote:
 On Saturday, 21 February 2015 at 15:26:28 UTC, ketmar wrote:
  On Sat, 21 Feb 2015 08:27:13 +, rumbu wrote:
 
  My question was not how I do this, I know already. My question
  was if
  there is another way to safely call a non-const instance
  function on a
  const object.
 
  is there a way to been safely hit by a truck?

 I thought if there is some language construct similar to @trusted
 for @safe, applicable to const member functions. You can be
 safely hit by a truck if I tell you that there is no truck around
 :)

No. That wouldn't work at all because of immutable. A const method can be
called on an immutable variable just as well as it can be called on a
const or mutable one.

In addition to that, Walter Bright feels very strongly that const should
provide actual compiler guarantees, and when you have something like C++'s
mutable which gives you a backdoor on const, the compiler can't really
guarantee much of anything.

@trusted has similar problems in that the programmer can screw it up and
mark stuff as @trusted which makes the calling code unsafe, but that would
be an actual bug in the program, whereas C++s mutable isn't a bug. Mutating
const is perfectly acceptle in C++. It just doesn't work unless you tell the
compiler to let you do it anyway, and the behavior is well-defined, whereas
doing anything like casting away const and mutating a variable in D is
undefined behavior, because the compiler is free to rely on const variables
not changing so long as it can guarantee that a mutable reference to the
same data can't have mutated that data.

And yes, on some level, that sucks, because stuff like caching doesn't work
with const, but it does mean that you can rely on const actually being
const, which does provide other benefits. It does take some getting used to
though. Regardless, the fact that we have immutable pretty much forces the
issue - especially when you consider that the compiler can choose to put
immutable variables in read-only-memory if it thinks that makes sense.

- Jonathan M Davis



Re: const member function

2015-02-21 Thread Mike Parker via Digitalmars-d-learn

On 2/21/2015 4:31 PM, rumbu wrote:


My intention is not to have a read-only getter, I want to call SomeProp
on a const object:

class S
{
 private int cache = -1;
 private int SomeExpensiveOp() { return 12345; }

 public @property const(int) SomeProp()
 {
 if (cache = -1)
 cache = SomeExpensiveOp();
 return cache;
 }
}



const is transitive. If an instance of S is const, then all of its 
members are const, too. You cannot modify cache in that case. Assuming 
cache only needs to be initialized once, you can do this instead:


this() { cache = SomeExpensiveOp(); }

public @property const(int) SomeProp() const
{
return cache;
}

Notice the const on the end of SomeProp. That makes the function 
callable on a const instance, but you still cannot modify cache inside 
of it.






Re: const member function

2015-02-21 Thread rumbu via Digitalmars-d-learn

On Saturday, 21 February 2015 at 08:08:25 UTC, Mike Parker wrote:

On 2/21/2015 4:31 PM, rumbu wrote:

you can do this instead:

this() { cache = SomeExpensiveOp(); }

public @property const(int) SomeProp() const
{
return cache;
}

Notice the const on the end of SomeProp. That makes the 
function callable on a const instance, but you still cannot 
modify cache inside of it.


My question was not how I do this, I know already. My question 
was if there is another way to safely call a non-const instance 
function on a const object.


Initializing cache in the constructor will defeat the cache 
mechanism itself an that's I want to avoid.


Re: const member function

2015-02-21 Thread Baz via Digitalmars-d-learn

On Saturday, 21 February 2015 at 07:31:19 UTC, rumbu wrote:

On Saturday, 21 February 2015 at 07:01:12 UTC, Baz wrote:

---
class S
{
   private SomeType cache;

   public const(SomeType) SomeProp() @property
   {
  if (cache is null)
cache = SomeExpensiveOperation();
  return cache;
   }
}
---

the result of the getter will be read-only


My intention is not to have a read-only getter, I want to call 
SomeProp on a const object:


class S
{
private int cache = -1;
private int SomeExpensiveOp() { return 12345; }

public @property const(int) SomeProp()
{
if (cache = -1)
cache = SomeExpensiveOp();
return cache;
}
}

unittest
{
const(S) s = new S();
auto i = s.SomeProp;  //mutable method S.SomeProp is not 
callable using a const object

}


right, i have not carefully read the body of the Q. my bad.



Re: const member function

2015-02-21 Thread Foo via Digitalmars-d-learn

On Saturday, 21 February 2015 at 06:38:18 UTC, rumbu wrote:

Often I'm using the following code pattern:

class S
{
   private SomeType cache;

   public SomeType SomeProp() @property
   {
  if (cache is null)
cache = SomeExpensiveOperation();
  return cache;
   }
}

Is there any way to mark SomeProp() as const? Because I want to 
call somewhere const(S).SomeProp, which for the outside world 
is must be const, returning just a value, even that internaly 
it modifies the internal S structure.


AFAIK it is unsafe and not recommended, but this works for me:


import std.stdio;

class Foo {
void say(string s) const {
writeln(s);
}
}

class Bar {
Foo f;

const(Foo) getFoo() const {
if (!f)
cast() this.f = new Foo();
return f;
}
}

void main() {
Bar b = new Bar();
const Foo f = b.getFoo();
f.say(Hello);
}



Re: const member function

2015-02-21 Thread ketmar via Digitalmars-d-learn
On Sat, 21 Feb 2015 08:27:13 +, rumbu wrote:

 My question was not how I do this, I know already. My question was if
 there is another way to safely call a non-const instance function on a
 const object.

is there a way to been safely hit by a truck?

signature.asc
Description: PGP signature


Re: const member function

2015-02-21 Thread Foo via Digitalmars-d-learn

On Saturday, 21 February 2015 at 15:26:28 UTC, ketmar wrote:

On Sat, 21 Feb 2015 08:27:13 +, rumbu wrote:

My question was not how I do this, I know already. My question 
was if
there is another way to safely call a non-const instance 
function on a

const object.


is there a way to been safely hit by a truck?


In a tank. ;)


Re: const member function

2015-02-21 Thread Jonathan M Davis via Digitalmars-d-learn
On Saturday, February 21, 2015 08:27:13 rumbu via Digitalmars-d-learn wrote:
 On Saturday, 21 February 2015 at 08:08:25 UTC, Mike Parker wrote:
  On 2/21/2015 4:31 PM, rumbu wrote:
 
  you can do this instead:
 
  this() { cache = SomeExpensiveOp(); }
 
  public @property const(int) SomeProp() const
  {
  return cache;
  }
 
  Notice the const on the end of SomeProp. That makes the
  function callable on a const instance, but you still cannot
  modify cache inside of it.

 My question was not how I do this, I know already. My question
 was if there is another way to safely call a non-const instance
 function on a const object.

 Initializing cache in the constructor will defeat the cache
 mechanism itself an that's I want to avoid.

Nope. If you want to use caching, you can't do it with const. D's const is
transitive, and it's not logical const. It's physical const. If _any_
portion of an object were to be mutated by a const function, it would
violate the type system. Unlike C++'s const, D's const provides actual
guarantees about the data not changing, which can be useful for some
optimizations but is outright required because of immutable. For instance,
imagine if your object were immutable and your const function were somehow
able to mutate on of the object's members (e.g. by casting away const). An
immutable object could be in read-only-memory, in which case, that would
segfault. And even if it didn't, it could cause really weird bugs due to the
fact that the compiler is free to assume that an immutable object never
changes and that an object can never be mutated via a const reference. The
fact that immutable objects are implicitly shared would make it even worse,
because then you'd risk thread-related issues to boot.

The reality of the matter is that if you want to do any kind of caching like
this, you either have to do the caching only in mutable functions (in which
case, the const function could take advantage of the cached value if it were
there but would have to calculate it if it hadn't been cached already), or
you can't do caching at all.

Ultimately, for better or worse, D's const is a very different beast from
C++'s const, and you can't approach them the same way.

This SO question discusses the issue:

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

- Jonathan M Davis



Re: const member function

2015-02-20 Thread rumbu via Digitalmars-d-learn

On Saturday, 21 February 2015 at 07:01:12 UTC, Baz wrote:

---
class S
{
private SomeType cache;

public const(SomeType) SomeProp() @property
{
   if (cache is null)
 cache = SomeExpensiveOperation();
   return cache;
}
}
---

the result of the getter will be read-only


My intention is not to have a read-only getter, I want to call 
SomeProp on a const object:


class S
{
private int cache = -1;
private int SomeExpensiveOp() { return 12345; }

public @property const(int) SomeProp()
{
if (cache = -1)
cache = SomeExpensiveOp();
return cache;
}
}

unittest
{
const(S) s = new S();
auto i = s.SomeProp;  //mutable method S.SomeProp is not 
callable using a const object

}


const member function

2015-02-20 Thread rumbu via Digitalmars-d-learn

Often I'm using the following code pattern:

class S
{
   private SomeType cache;

   public SomeType SomeProp() @property
   {
  if (cache is null)
cache = SomeExpensiveOperation();
  return cache;
   }
}

Is there any way to mark SomeProp() as const? Because I want to 
call somewhere const(S).SomeProp, which for the outside world is 
must be const, returning just a value, even that internaly it 
modifies the internal S structure.


Re: const member function

2015-02-20 Thread Baz via Digitalmars-d-learn

---
class S
{
private SomeType cache;

public const(SomeType) SomeProp() @property
{
   if (cache is null)
 cache = SomeExpensiveOperation();
   return cache;
}
}
---

the result of the getter will be read-only