4 ms·
JQuery is a monad
- burke 18y agoI've casually skimmed a couple explanations of monads over the last little while, but this one finally made it "click" for me. Great post.
- russell 18y agoLikewise, I could never quite get monads. I was afraid that I might have to learn Haskel to understand them. Now, I realize that they are a pattern that I have used for decades but applied inconsistently. This was one of those "Ah ha" moments where I realized that I had almost had it and probably would have gotten it with a little more introspection about Jquery.
- jpcx01 18y agoGreat strength, but also a great weakness of jQuery. My most common jQuery bug is a rule that doesn't get applied correctly (wrong selector) and it just fails quietly. It's very hard to write console.log statements, or even do debugging breakpoints on a long method chain. Probably a way to solve this problem. Maybe jQuery needs a monadic method that logs the current chain object without interupting the flow. $("div.blah > h1").logCurrent("Showing current item:") where log current would display your message along with a representation of the current state of the transitionary object, and then return it back so you can continue on with the chain. Something like this probably already exists. Or it wouldnt be too hard to write a plugin.
- shutter 18y agoSomething like this would work: jQuery.fn.logCurrent = function (title) { console.log(title, $.makeArray(this).join(', ')); return $(this); }; But it depends what you want to log for each element. I think Firebug's output would give clickable links in that case, but you could alternatively cherrypick class names or the like.
- simonw 18y agoYou can also add assertions to jQuery about the length of the chain: jQuery.fn.assertLength = function(i) { if (this.length != i) { throw "Expected " + i + " matching elements, selection was: " + this.get(); } return this; } If you're using jQuery 1.3 (with its new selector property), a better implementation might be: jQuery.fn.assertLength = function(i) { if (this.length != i) { throw "Expected " + i + " matching elements, got " + this.length + ", selector was: " + this.selector; } return this; } You can then introduce the assertLength method in to your chains like so: $('div#intro a').assertLength(3).click(...) If the number of matched elements doesn't match the expected, you get a descriptive exception raised which stops execution and shows up in the error console.
- iamwil 18y agoI remember Raganwald talking about something similar. http://weblog.raganwald.com/2008/01/objectandand-objectme-in-ruby.html http://weblog.raganwald.com/2008/01/objectandand-objectme-in... Scroll down and he talks about #tap in Ruby 1.9, which he uses to insert a "tap" into a long method chain to figure out what's going on there, instead of having to break the chain and store the results in a variable in order to inspect it.
- invisible 18y agoOne thing he mentions is inaccurate: jQuery IS limited to it's own built-in functions; however, it defines functions that utilize a few Array methods using apply (e.g. Array.prototype.map.apply(this, arguments) where this is the jQuery object ). This is possible because jQuery defines it's contents inside each object numerically: var jQueryObj = $(".someClass"); alert(jQueryObj[0].innerHTML);
- andr 18y agoSo monads are essentially decorators with method chaining?
- eelco 18y agoIt's (just) one of the usages of monads, but it's not what monads 'are'.
- d0mine 18y agoAs presented in the post they are. Monads are abstract data types that satisfy three conditions: 1) They wrap themselves around other data types 2) They have an operation, confusingly called return, that actually performs the aforementioned wrapping 3) They have an operation called bind that allows to feed the value wrapped inside the monad into another function, as long as the function returns a monad. </quote> What condition is not satisfied by decorators with method chaining?
- jerf 18y agoYou've got eelco's point backwards... eelco is saying that there are things that are not "decorators with method chaining" that are monads.
- olavk 18y agoAdditionally, decorators with method chaing are not necessarily monads. AFAIK a monad has to be able to wrap any type, while a decorator is usually constrained to wrap some specific type (e.g. DOM nodes in the case of jQuery).
- d0mine 18y agoYou've got my point backwards.. I'm saying that iff "decorators with method chaining" satisfy all conditions presented in the paper then any monad (as they defined in the paper) can be expressed as a "decorators with method chaining". A single counter-example (a monad in the above sense that can't be expressed as a decorator) would suffice.
- rcoder 18y agoThere are a limited subset of the jQuery core functions which function much like a monoid (though not strictly a monad), but the lack of strictness means that you can escape the "monadic" container at any time. Utility functions, global assignments, etc., further compound the issue. That being said, presenting monadic designs in this fashion could well help understand the basics, which is to be applauded.