Jump to page: 1 2
Thread overview
Reuse of variables referencing const objects
Mar 06, 2009
Sergey Kovrov
Mar 06, 2009
Sergey Kovrov
Mar 06, 2009
bearophile
Mar 06, 2009
Sergey Kovrov
Mar 06, 2009
bearophile
Mar 07, 2009
Sergey Kovrov
Mar 09, 2009
Sergey Kovrov
March 06, 2009
I wonder if it is possible to reuse a variable for a const/invariant reference type? By "reuse" I mean to reference different data. Considering code:

  auto f = new const(Foo)();  // Foo is a class, e.g. reference type
  f = new Foo();  // error: cannot modify const

But here I really meant to assign new data to variable `f`, not to modify old instance.

Of course, I could use mutable pointer to const/invariant data. But this make sense only for value types. In case of reference types this will complicate things (introducing more human errors) and just feels wrong. Consider code:

  const (Foo)* foo = a_condition ? &some_foo : null;
  if (foo !is null && *foo !is null)
      ...;

Reference types was invented to simplify things. And they do, but not in case of const data. Do I miss something, or const support in reference types is not there yet?

-- serg.
March 06, 2009
Other reference types (e.g. arrays) have solution to this: ``immutable(TYPE)[]`` and ``immutable(TYPE[])`.

I think class instances should have something similar in language as well.


-- serg.
March 06, 2009
Sergey Kovrov:

> Other reference types (e.g. arrays)<

Arrays aren't really references, they are a small 2-word long struct, that contains a pointer to the data and a length.

Bye,
bearophile
March 06, 2009
On 3/6/2009 4:42 PM, bearophile wrote:
> Arrays aren't really references, they are a small 2-word long struct,
> that contains a pointer to the data and a length.

I guess there is a data member for allocated buffer size as well...

Objects may be viewed as a structure too. There are context pointer virtual function table and maybe something else implementation-specific.

-- serg.
March 06, 2009
On Fri, 06 Mar 2009 09:39:43 -0500, Sergey Kovrov wrote:

> Other reference types (e.g. arrays) have solution to this:
> ``immutable(TYPE)[]`` and ``immutable(TYPE[])`.
> 
> I think class instances should have something similar in language as well.
> 
> 
> -- serg.

std.typecons.Rebindable

http://www.digitalmars.com/d/2.0/phobos/std_typecons.html#Rebindable

-Steve
March 06, 2009
Sergey Kovrov:
> I guess there is a data member for allocated buffer size as well...

Nope, this isn't vector of C++. It's a long story (caused to allow the slicing). The result is that the append is very slow.


> Objects may be viewed as a structure too. There are context pointer virtual function table and maybe something else implementation-specific.

Objects are managed by a reference (even in a transparent way, when you use scope and the compiler accepts it).

Bye,
bearophile
March 07, 2009
On 3/6/2009 11:29 PM, Steven Schveighoffer wrote:
> std.typecons.Rebindable
>
> http://www.digitalmars.com/d/2.0/phobos/std_typecons.html#Rebindable

Thanks Steve,

this is what I've been looking for, the only thing missing is comparing against null (is null).


-- serg.
March 09, 2009
Sergey Kovrov wrote:
> On 3/6/2009 11:29 PM, Steven Schveighoffer wrote:
>> std.typecons.Rebindable
>>
>> http://www.digitalmars.com/d/2.0/phobos/std_typecons.html#Rebindable
> 
> Thanks Steve,
> 
> this is what I've been looking for, the only thing missing is comparing against null (is null).
> 
> 
> -- serg.

While not strictly intuitive, you could do this:
  auto var = Rebindable!(const Foo)(new Foo);
  assert(var.opDot !is null);

As 'opDot' returns the wrapped object (with const intact).  The downside to that, however, is that it won't work in those cases where Rebindable's template parameter was mutable, as then it simply aliases it.  This shouldn't be a problem in general use, though.  Only in generic code, which could try to check for Rebindable.

-- Christopher Nicholson-Sauls
March 09, 2009
On 3/9/2009 8:50 PM, Chris Nicholson-Sauls wrote:
> While not strictly intuitive, you could do this:
> auto var = Rebindable!(const Foo)(new Foo);
> assert(var.opDot !is null);
>
> As 'opDot' returns the wrapped object (with const intact). The downside
> to that, however, is that it won't work in those cases where
> Rebindable's template parameter was mutable, as then it simply aliases
> it. This shouldn't be a problem in general use, though. Only in generic
> code, which could try to check for Rebindable.

Thanks Chris, this approach indeed works, its a shame I haven't figured this on my own.

I wonder if it's proper usage of opDot.. In general, is it safe for client code to rely on implementation of opDot and call it directly?

And in this particular case we rely on the fact that Rebindable uses opDot to forward calls.

Slightly off-topic... In Python world (and I guess any other dynamic language) it is not valid to make assumptions based on implementation. Only safe way to use "foreign code" (a library, framework) is to follow documentation. That way authors of libraries are free to change their code as long as it comply with documented behavior.


-- serg.
March 10, 2009
Sergey Kovrov wrote:
> On 3/9/2009 8:50 PM, Chris Nicholson-Sauls wrote:
>> While not strictly intuitive, you could do this:
>> auto var = Rebindable!(const Foo)(new Foo);
>> assert(var.opDot !is null);
>>
>> As 'opDot' returns the wrapped object (with const intact). The downside
>> to that, however, is that it won't work in those cases where
>> Rebindable's template parameter was mutable, as then it simply aliases
>> it. This shouldn't be a problem in general use, though. Only in generic
>> code, which could try to check for Rebindable.
> 
> Thanks Chris, this approach indeed works, its a shame I haven't figured this on my own.
> 
> I wonder if it's proper usage of opDot.. In general, is it safe for client code to rely on implementation of opDot and call it directly?

Technically, no, not really.  Then again, it isn't absolutely horrible either.  It would be better if there were some other means of testing for null, which could be overwritten.  The only alternative that comes immediately to mind would be an opCast to T, but then it would supersede any opCast defined on T.  (Then again, in code dealing with Rebindable one could always chain the casts: 'cast(Bar)cast(Foo)var'.  Ugly, but possibly effective.

> And in this particular case we rely on the fact that Rebindable uses opDot to forward calls.

Considering its the only way of doing so in a completely generic manner anyhow, I don't think its a big deal.  It could become annoying, however, for generic code.

> Slightly off-topic... In Python world (and I guess any other dynamic language) it is not valid to make assumptions based on implementation. Only safe way to use "foreign code" (a library, framework) is to follow documentation. That way authors of libraries are free to change their code as long as it comply with documented behavior.
> 
> 
> -- serg.

The sentiment applies in almost any language, but a static typed language does allow for a few more assumptions.  I have a habit of crawling through the sources of libraries I use anyhow, so I'm sure I occasionally do things in "*evil*" undocumented ways.  ;)

Maybe there should be an 'IsNull' template that understands Rebindable's.  That said, I'm not sure what kind of is() invocation would match a struct template...  (pssst, template ninjas...)


-- Chris Nicholson-Sauls
« First   ‹ Prev
1 2