[M3devel] Implementing the "Singleton pattern" in Modula-3
Tony Hosking
hosking at cs.purdue.edu
Tue Apr 7 04:07:19 CEST 2009
On 7 Apr 2009, at 11:18, Mika Nystrom wrote:
> Well I think the problem is with this "is known to be an object
> type"...
But if the opaque type T is T<:REFANY and the only revelation is
branded and private to a module (not exported by its interfaces) then
no-one can determine that it is an object type without forging the
BRAND.
> You may in fact want to override the methods of the singleton, but
> ensure that only one ever gets instantiated.
>
> It's a minor problem, but it does sometimes bother me that it is
> difficult to prevent clients from NEWing pretty much anything they
> like.
>
> By the way, the "Modula-3 Type System" paper also talks about a
> nifty way to do narrowing very quickly (page 10, last paragraph).
> I remember this is occasionally problematic. (RTType.IsSubtype
> isn't great.) They speak of keeping an array of supertypes
> for each type, and recording the "depth" (distance from REFANY)
> of every type in, I guess, RT0.TypeDefn. This seems moderately
> space-efficient (better than a 2D array of all the typecodes),
> and very fast.
>
> Mika
>
> Tony Hosking writes:
>> I would exploit opaque types and branding. If T is opaque then you
>> cannot instantiate T except in scopes where T's concrete type has
>> been
>> revealed or is known to be an object type. Thus, you could define an
>> interface:
>>
>> GENERIC INTERFACE Singleton(Rep);
>> TYPE T <: REFANY;
>> VAR t: T;
>> END Singleton.
>>
>> GENERIC MODULE Singleton(Rep);
>> REVEAL T = BRANDED REF Rep.T;
>> BEGIN
>> t := NEW(T);
>> END Singleton.
>>
>> where Rep defines the type T. You could do similar for object types.
>>
>>
>> On 7 Apr 2009, at 06:31, Mika Nystrom wrote:
>>
>>>
>>> Tony, Jay, you two seem to be most knowledgeable about this.
>>>
>>> Let's say I wanted to implement the "singleton pattern" in
>>> Modula-3. At present there seems to be no way of doing this.
>>>
>>> What about changing RTAllocator.callback as follows (or adding
>>> another callback):
>>>
>>> VAR callback : PROCEDURE(r : REFANY) : REFANY := NIL;
>>>
>>> (* If non-NIL, the allocator calls "callback(r)" just before
>>> returning
>>> a new traced reference "r" and instead returns the result of
>>> callback(r).
>>> See "RTAllocStats" for an example client. It is a checked runtime
>>> error
>>> for the typecode of r to differ from the typecode of the return
>>> value of
>>> callback(r). *)
>>>
>>> Mika
>>>
>>>
>>>
More information about the M3devel
mailing list