Singleton in the absence of static state (and the presence of nested classes)

17 views
Skip to first unread message

Milan Zimmermann

unread,
Nov 14, 2023, 2:17:35 AM11/14/23
to newspeak...@googlegroups.com
(There is a brief question at the end, all stuffing before is context, sorry) 

For a while I have been wondering how to create a singleton class in Newspeak, because the usual trick of storing the singleton instance in a static state cannot be used in Newspeak (yes, for example in Java only works within the same classloader etc, but anyway)

I realize that one way of achieving the goal practically in Newspeak, is to put a slot with the instance on the top class, something like

     |modulesSingletonInstance = AnyClass new| (* new or declared primary factory *)

Assuming a developer coding in that module knows and accepts some rigor, any code in the module can address the 'modulesSingletonInstance' because it is in lexical scope, and things should work as needed. But ignorance allows developer to use in code deep inside the module, something like

    secondInstance:: AnyClass new.

I thought the way to make an appropriate singleton would be to make the singleton a nested class in the module and:
  - make the primary factory private
  - provide a public class method getInstance
  - still use a slot on the top level class (similar to the  |modulesSingletonInstance| above) to store the instance (what would be a static instance in other languages).

 I thought it could be something like this (this is overengineered, this is pasted from my test)

-----------------------------
Newspeak3
'Root'
class AAModuleUsingSingletonQUESTION = (
|
    (* Holder of the singleton instance for this module. *)
    private modulesSingletonInstance <AASingleton>
|
) (
private class AASingleton new = () (
) : (
public getInstance ^<AASingleton> = (
   modulesSingletonInstance = nil
   ifTrue: [
     modulesSingletonInstance: AASingleton new.
   ].
   ^ modulesSingletonInstance.
   )
)
class NestedUsingSingleton = (
|
public nestedClassSlotWithSingletonInstance = AASingleton getInstance.
|
) (
) : (
)
public client1OfSingleton ^ <AASingleton> = (
    |gotInstance|
    gotInstance:: AASingleton getInstance.
    ^ gotInstance.
)
public client2OfSingleton ^ <AASingleton> = (
    |gotInstance|
    gotInstance:: AASingleton getInstance.
    ^ gotInstance.
)
public client3OfSingletonUsedInNested ^ <AASingleton> = (
^ NestedUsingSingleton new nestedClassSlotWithSingletonInstance.
)
public client4OfSingletonBreakingSingleton ^ <AASingleton> = (
(* BREAKING SINGLETON *)
    modulesSingletonInstance = AASingleton new.
)
) : (
-----------------------------

But I did NOT realize, the PRIVATE primary factory 

    'private class AASingleton new = ()'

does NOT prevent being called from the outer class 'AAModuleUsingSingletonQUESTION', as 'AASingleton' is a member of 'AAModuleUsingSingletonQUESTION', hence accessible, as in the 'client4OfSingletonBreakingSingleton', breaking the singleton property.

Hmm, long context introduction again.

==> My question is, how would a singleton be done right in Newspeak, or are there examples to point to? (I did not yet experiment with importing AASingleton instead of nesting it, maybe I could work around the accessibility rules)

Thanks,
Milan

PS: I promised myself not to overload and only ask 2 short questions a week max. This already exceeded the length, although not the max :)

Gilad Bracha

unread,
Nov 14, 2023, 11:26:32 PM11/14/23
to newspeak...@googlegroups.com
Hi Milan,

Sorry for the late reply. I have been distracted from my Newspeak work recently, for reasons I suspect you understand only too well.

As a practical matter, your solution is fine - after all, within the boundaries of the outer class, you would not to try and instantiate the singleton class. However, I imagine you are worried about human error and want a more bullet proof solution.  I think you can have the singleton class factory test this count and throw an exception if an instance already exists. Now you can still undermine this by manipulating the slot  modulesSingletonInstance, but now you must be downright malicious (or a certifiable idiot) to do so. See an adaptation of your code below

Newspeak3
'Root'
class AAModuleUsingSingletonQUESTION = (
|
    (* Holder of the singleton instance for this module. *)
    private modulesSingletonInstance <AASingleton>
|
) (
private class AASingleton new = ( moduleSingletonInstance isNil ifFalse: [Error signal]. ) (
--
You received this message because you are subscribed to the Google Groups "Newspeak Programming Language" group.
To unsubscribe from this group and stop receiving emails from it, send an email to newspeaklangua...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/newspeaklanguage/CAEc2VK1xu9xisrfEKouPqrf-PcEP7ZZe48rAuBab8aTbfkzvOw%40mail.gmail.com.


--
Cheers, Gilad

Milan Zimmermann

unread,
Nov 15, 2023, 1:26:45 AM11/15/23
to newspeak...@googlegroups.com
Hi Gilad,

Yes, I definitely understand there are more important things in life than this, these days and weeks.  I so much appreciate you taking time to respond.

Your improvement is what I was looking for (obviously now I am thinking 'why did not I think of it').  I have experimented with Newspeak quite a bit again, it fascinates me anew; everything around nested classes makes me think how it would change the 'old' thinking when designing programs, or around what is considered design patterns. But I am way too slow and clumsy. I wonder if there is research in that area.  

But anyway, I will stop, and leave space for one (maybe) one more question later in the week.

Thanks,
Milan

Reply all
Reply to author
Forward
0 new messages