1

I am doing a library in ClojureScript that will expose a public JavaScript API. Since it has to mimic the API of an existing JavaScript library, I would like to present the same kind of fluent API :

myLib.prepareToDo()
     .something()
     .and('also')
     .somethingElse()
     .run(function(err, result) {
         console.log("yay!");
});

In Javascript, one could create a fluent API like this site point):

var MyClass = function(a) {
    this.a = a;
}

MyClass.prototype.foo = function(b) {
    // Do some complex work   
    this.a += Math.cos(b);
    return this;
}

I can then call it like :

var obj = new MyClass(5);
obj.foo(1).foo(2).foo(3);

Now, as far as I know, there is no notion of this in ClojureScript, although apparently it is possible to access it this-as.

I don't get how to use it though, hence my question.

How can I create a fluent interface in ClojureScript ?

nha
  • 17,623
  • 13
  • 87
  • 133

1 Answers1

5

(defrecord) and this answer to the rescue. Extending the "magic" protocol Object to our record or type causes the defined methods to appear as member functions in the JavaScript object. To enable the "fluent interface", some methods return an instance of MyClass.

(defrecord MyClass [a b]
    Object
      (something [this] this)
      (and-then [this s] (assoc this :a s))
      (something-else [this] (assoc this :b (str a "-" a)))
      (run [this f] (f a b)))

Then we can have a JavaScript client like so:

var myClass = new my_namespace.core.MyClass();
myClass.something()
   .and_then("bar")
   .something_else()
   .run(function(a, b) { 
       console.log(a + " - " + b) });
Community
  • 1
  • 1
ez121sl
  • 2,371
  • 1
  • 21
  • 28