Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Making objects more chainable #1431

Closed
redalastor opened this issue Jun 11, 2011 · 8 comments
Closed

Making objects more chainable #1431

redalastor opened this issue Jun 11, 2011 · 8 comments

Comments

@redalastor
Copy link

One of the things I really like about jQuery is how everything is chainable.

I like to be able to write:

object.doFoo().doBar().doBaz()

and have all those things done to object. Unfortunately, some libraries don't code that way and I have to do:

object.doFoo()
object.doBar()
object.doBaz()

I could use the with statement but Douglas Crockford wouldn't be happy. I could use a list comprehension but that doesn't seem like a very clean solution.

Could we have some syntax that would let me write something like:

object!.doFoo()
  !.doBar()
  !.doBaz()

And have it rewritten

object.doFoo()
object.doBar()
object.doBaz()

?

That would give us the advantages of the with statement without the drawbacks.

@breckinloggins
Copy link
Contributor

Doing this natively would involve adding some chaining logic to every function, which is probably in discordance with the design goals of the language.

Note, however, that jQuery does this as part of itself, it doesn't extend JavaScript. So the best approach is to follow their lead:

class SomeClass
   doFoo: ->
      # Foo stuff
      this

    doBar: ->
       # Bar stuff
       this

    doBaz: ->
       # Baz stuff
       this

someClass = new SomeClass
someClass.doFoo().doBar().doBaz()

Now if you want to return stuff in addition to the class, you can return an array and use destructuring assignment in the caller. You could probably even write a "chainify" function to do this cleanly.

With respect to using external libraries, you could probably even write chainify to take a class or set of functions and add this capability to each function by wrapping it and doing clever things with the arguments object.

@redalastor
Copy link
Author

I don't see why we'd have to modify functions.

What I want to do is what clojure used to do with doto (and it's also part of Smalltalk but I do not remember the syntax). It is useful if you have a library that doesn't follow jQuery's lead and where you have no control over their source.

It really about syntactic sugar, CoffeeScript would turn

myobject.setA(foo)!.setB(bar)!.setC(baz)

into

myobject.setA(foo);
myobject.setB(bar);
myobject.setC(baz);

The functions called would be completely undisturbed.

@satyr
Copy link
Collaborator

satyr commented Jun 12, 2011

So it's exactly like cascading (;) in Smalltalk: http://ideone.com/yuBW9

@redalastor
Copy link
Author

Yes! It's Smalltalk's cascading.

@dtinth
Copy link

dtinth commented Jun 12, 2011

For now, this can be accomplished using a helper function:

dowith = (obj) -> (fn) -> fn.call obj

and call it like this instead:

dowith(object) ->
    @doFoo()
    @doBar()
    @doBaz()

@ubunatic
Copy link

The proposed dowith workaround has some significant overhead: http://jsperf.com/propertyaccess-dowith-vs-normal

A Dart-style cascade operator .. (see #2991) for that purpose would be really nice. What are the actual arguments against having a native coffeescript cascade operator (which is more than just method chaining #1495)?

@ethanresnick
Copy link

I'd also be a fan of something like this. Seems like a simple (from the users' perspective) inclusion in the spirit of coffeescript.

@GeoffreyBooth
Copy link
Collaborator

Closing this as there doesn’t appear to a consensus that a shortcut for chaining should be added to the language.

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

No branches or pull requests

7 participants