Newbie initial comments on D language - scope

Edward Diener eddielee_no_spam_here at tropicsoft.com
Sun Feb 3 07:15:36 PST 2008


Janice Caron wrote:
> On 03/02/2008, Edward Diener <eddielee_no_spam_here at tropicsoft.com> wrote:
>> But again that does not change the type of 'char'.
> 
> I hope you're not implying that I said it did.
> 
>> In arguing for 'scope' at the type level, as in 'scope class C { ... }'
>> I was arguing that 'scope' applies some attribute to the type of C. The
>> class designer is making a conscious decision in designing his type in
>> order to tell the compiler that all objects of his type need
>> deterministic destruction in a system which normally implements
>> non-deterministic destruction via GC. That says something about the type
>> per se.
> 
> Having actually implemented reference counting in C++, I know how it
> works. For any type T (doesn't matter if it's a class, a struct, or
> just an int), you make two additional types. The first of these just
> adds a reference counter:
> 
>     class Countable(T)
>     {
>         uint refCount;
>         T val;
>     }
> 
> and the second is what is exposed to the end user
> 
>     struct RefCounted(T)
>     {
>         Countable!(T) val;
>         /* and appropriate ref-counting functions */
>         /* and appropriate forwarding functions */
>     }
> 
> It should be clear that there is no way to cast a RefCounted!(T) to a
> T. If you want the following to compile:
> 
>     RefCounted!(C) c = whatever;
>     C d;
>     d = c;
> 
> Then the only way to do that would be to have RefCounted!(C) be
> implicitly castable to C, presumably by having opImplicitCast() return
> c.val.val. This would be disasterous. The moment you allow that,
> suddenly you have uncounted references running around. It would then
> be possible to do the following:
> 
>     C d;
>     {
>         RefCounted!(C) c = new RefCounted!(C)();
>         d = c;
>     }
>     /* Whoops! d now points to a destructed object! */
> 
> Instead, what you'd /really/ want the class designer to do is
> something like this:
> 
>     struct PrivateFileHandle
>     {
>         private this(string filename) { /*...*/ }
>         ~this() { /*...*/ }
>         /* other functions as appropriate */
>     }
>     alias RefCounted!(PrivateFileHandle) FileHandle;
> 
> That way, the caller only has to declare
> 
>     FileHandle fh;
> 
> but gets it ref-counted. (And there is no way for it not to be refcounted).
> 
> If we go the way of "scope C" meaning "RefCounted!(C)" under the hood,
> then whether or not you'll need the word "scope" depends on whether
> you want to refer to the refcounted type or the underlying type.

I am saying that when the type is 'scope class C' the compiler 
automatically wraps every instantiated object of that type as a 
referenced counted object. While I am not uninterested in the details of 
doing that, as you present it above, I am more interested that it be 
done for the correct situations in order to provide RAII in GC. I do not 
think the end user should have to redundantly specify the object as:

scope C c = new C(...);

when C is already a scope class. The compiler can figure out that C is a 
scope class and silently treat c as a scope object.

As for assigning a reference of a scope object to a non-scope object I 
do understand the problems as outlined above. Thanks for the 
explanation. I still think the compiler can figure out in:

class B {...}
scope class C : B {...}

B b = new C(...);

that the b object upon instantiation needs to be wrapped as a scoped 
object without having to write instead:

scope B b = new C(...);

but I do realize now that with

B b;
b = new C(...);

it would be difficult, perhaps impossible, to somehow switch b from a 
non-scoped object to a scoped one since the object has been wrapped or 
not when it was created. So I do now accept that the second form should 
be illegal.

I know others may think it may be nit-picking that I do not think that 
when the dynamic type, upon creation of an object, can be ascertained as 
a scope class the end user should have to specify the 'scope' keyword 
again in the declaration of the object. But I think it is really 
important for RAII to be as transparent as possible from the end user's 
  point of view, while also allowing the end user to create scope 
objects as necessary also when the actual class type of the object 
created is not scope.



More information about the Digitalmars-d mailing list