Skip to content

Instantly share code, notes, and snippets.

@danielpetisme
Created April 28, 2013 10:44
Show Gist options
  • Save danielpetisme/5476546 to your computer and use it in GitHub Desktop.
Save danielpetisme/5476546 to your computer and use it in GitHub Desktop.
Design patterns are commons concepts for every devlopper. So I'm trying to implement the basic ones in Golo. The very first one is the Singoloton but I'm facing some issues. 1 - Is it possible to implement it in pure Golo? 2- Without DynamicObjects ? This is my shot. Any thoughts are welcomed!
module g0l0.patterns.creationnal.Singleton
local function _instance = -> null
local function _init = -> DynamicObject():
testing(|this| -> println(this + "doing some stuff"))
function MyObject = {
if _instance() is null {
let instance = _init()
^_instance = -> instance
}
return _instance()
}
function main = |args| {
var instance1 = MyObject()
var instance2 = MyObject()
assert (instance1 == instance2)
}
@danielpetisme
Copy link
Author

The code does not compile!

Assumptions:

  • static are replaced by functions
  • Private visibility is replaced by local functions

My idea:
Having a private function returning null. At the first attempt of instanciation, the function will be overrided to return a particular instance.

@k33g
Copy link

k33g commented Apr 28, 2013

function Cock = |name|-> DynamicObject():name(name)

function Farm =  {
    return DynamicObject()
        :giveMeTheOnlyCock(|this, name|{
            if this:get("theOnlyCock") is null {
                this:theOnlyCock(Cock(name))
            } 
            return this:theOnlyCock()
        })
}

function main = |args| {

    let farm = Farm()

    let elvis = farm:giveMeTheOnlyCock("Elvis")
    let dick = farm:giveMeTheOnlyCock("Dick")

    println(elvis:name()) #Elvis
    println(dick:name()) #Elvis

}

@jponge
Copy link

jponge commented Apr 28, 2013

This is a very interesting discussion to have.

Basically Golo wants to avoid global state at all cost. This allows functions to lean towards side-effect free functions, also called pure functions, i.e., functions whose return value only depends on the argument values. Of course things are not perfect, because side-effects can still happen when calling Java code, but you get the idea.

Singletons as we have been taught in Java, C++ or similar languages all rely on some static stuff which is (in disguise) the equivalent of global variables. Relying on some global namespace is messy, and we all kind of know why this is bad in general.

OO-languages have found a cure in the form of dependency-injection containers, where objects have scopes. Even a singleton-scoped object is not a singleton in the traditional sense, as in reality it stays tied to a scope. This is a much better design than relying on static parts of objects, which in reality are objects whose lifespan starts from class loading to garbage-collection, which is anything but deterministic.

I hope it clarifies why Golo does not have module-level state that would translate to static fields.

Now you can easily get around that:

  1. use the application bootstrap functions as scopes,
  2. use closures or function argument partial application (bind / bindAt) to propagate objects belonging to a scope.

In short: static state is a leaky shortcut, so we'd rather avoid that.

@danielpetisme
Copy link
Author

Valuable comment !! It deserves to be copied into the official doc, isn'it?

I would appreciate to have your version of the singleton.

Otherwise, can you confirm we can't define data structures un golo. It's a procedure oriented language?

@jponge
Copy link

jponge commented Apr 28, 2013

We can't have class / value object definition yet, which means that it is coming at some point. It's a young language after all 😉

It's not a procedure-oriented language, but a kind of functional one, but not really, but duck-typed, and a language always has multiple paradigms, so...

@jponge
Copy link

jponge commented Apr 28, 2013

The samples/workers.golo is a good example of scoped objects and dependency injection. It took me a while to realize that scopes and DI are just partial applications on functions...

@danielpetisme
Copy link
Author

What about this

module g0l0.patterns.creationnal.Singleton


local function _init = -> DynamicObject():
  testing(|this| -> println(this + " doing some stuff"))

local function _MyObject = |this| -> this

function MySingletonFactory = -> ^_MyObject: bindTo(_init())

function main = |args| {

  let getInstance =  MySingletonFactory()

  let instance1 = getInstance()
  let instance2 = getInstance()

  require(instance1 == instance2, "Must be the same object")

}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment