3
function setStyle(x) {
    with (x.style) {
        padding = '10px'
        marginBottom = '10px'
        width = '100%'
    }
    return setStyle
}

setStyle(account)(password)(login)

I often use the above pattern, but when I need to talk about it, I have no idea what is it called? How to refer to this kind of approach in the conversation?

UPDATE:

Someone closed this question as duplicate, but I cannot see why is that a duplicate. Other question is about some framework, the poster is trying to understand the code. I do not try to understand the code, I am asking about an English term for a known pattern. Even though the discussed concept is the same, the question is different. It is like saying that "Who was the youngest in Jasckson's Five" and "Whose album is Thriller" both are the same question, only because it happens to be about the same person. But those are different questions, not the same.

exebook
  • 32,014
  • 33
  • 141
  • 226
  • 2
    I'd say "fluent interface" and "call chaining", but usually that is with methods that return "this" so you can keep calling other methods on the same object. In your case you return the function so that you can repeatedly call it with different arguments. Same idea, but a little different (I've never seen it). – Thilo Nov 14 '14 at 08:34
  • 2
    `with`? Let's call that style _"bad"_. And just curious: Why do you prefer using this over passing multiple variables, or an array of parameters? – Cerbrus Nov 14 '14 at 08:35
  • 1
    Are you asking about "currying"? – elclanrs Nov 14 '14 at 08:36
  • 3
    @elclanrs: No, this is not currying. The function being returned is not a curried function, it is just the same function again. – Thilo Nov 14 '14 at 08:37
  • Why is it not just a functionnal pattern, since your function is what is called a higher-order function? – laruiss Nov 14 '14 at 08:38
  • Seems more natural to have a "vararg" type function that can take a list of args. Then it would be `setStyles(account, password, login)` (and not look like currying). – Thilo Nov 14 '14 at 08:39
  • 1
    @laruiss: How is this a higher-order function when it does not manipulate or work on other functions? (it would be a bit of a stretch to say that it produces a function). – Thilo Nov 14 '14 at 08:40
  • 1
    @Thilo: `setStyle(account, password, login)` is a lot cleaner, indeed. – Cerbrus Nov 14 '14 at 08:40
  • 2
    http://stackoverflow.com/a/3799269/887675 – user887675 Nov 14 '14 at 08:42
  • 1
    _"Use of the `with` statement is not recommended, as it may be the source of confusing bugs and compatibility issues. See the "Ambiguity Con" paragraph in the "Description" section below for details."_ ([Source](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/with)) – Cerbrus Nov 14 '14 at 08:42
  • 1
    `with` is so little used it leads to performance problems. For example a function containing `with` isn't optimized by V8. Never use `with`. – Denys Séguret Nov 14 '14 at 08:44
  • My question is not whether this is a good practice or bad practice. Even if it is a bad, doomed, unpleasant, ridiculous, useless pattern, unclean, dirty, and just plain wrong -- it still deserves a name to be referred to. – exebook Nov 14 '14 at 09:05
  • @Cerbrus, forget about `with` it is well known to be not-recommended. It has nothing to do with the question. You should close questions on reason not on your emotions. Someone using `with` statement in the example is not a reason to close a question that has nothing to do with that `with`. – exebook Nov 14 '14 at 09:07
  • 1
    @exebook If you just want to get the name of the pattern not the detail about that you may have just seen in the duplicate question that is **function chaining pattern** . – Bhojendra Rauniyar Nov 14 '14 at 09:08
  • @C-linkNepal, if you make it into an answer I'll accept it. Because clearly this is exactly what I ask. – exebook Nov 14 '14 at 09:09
  • @exebook: I didn't close this question because of the `with`. For a second there I thought it was a duplicate of that `()()` pattern. – Cerbrus Nov 14 '14 at 09:53

1 Answers1

4

This pattern is not "function chaining", because chained (=composed, pipelined) functions work by passing result of one function as an argument to the next one. For example, if you have something like:

str = removeBadChars(str)
str = makeLowerCase(str)
str = convertToURL(str)

you can rewrite this more concisely as

str = chain(removeBadChars, makeLowerCase, convertToURL)(str)

(Exercise: write chain()).

Your pattern doesn't appear to have a name, probably because it's fairly useless. Mr. Crockford coined the term retursion, but it doesn't seem to be used widely.

Note that this pattern is essentially anti-functional, because in functional programming we prefer to work with pure functions, while a "retursive" function can only do anything useful as a side effect.

UPD: this reasoning applies to functions that just blindly return itself, like in your example, however, the f()()() syntax can also be used with functions that return something else on each invocation. In this case, the "root" function accepts a hidden parameter ("accumulator") used to carry state around. A good example of such approach would be chain() like above, but written in the applicative style: chain(func1)(func2)(func3):

function chain(f, fun) {

    fun = fun || function(x) { return x };

    if(typeof f != "function")
        return fun(f);

    return function(x) {
        return chain(x, function(y) { return f(fun(y)) })
    }
}

// Example:

makeLowerCase  = function(str) { return str.toLowerCase() };
removeBadChars = function(str) { return str.replace(/\W/g, "") };
makeURL        = function(str) { return "http://" + str };

funcs = chain(makeLowerCase)(removeBadChars)(makeURL);
x = funcs('!!! HELLO ???');
alert(x);

In this case, this syntax is used to implement "partial application", because we return a closure which calls the root function yet again, with a predefined second argument.

georg
  • 211,518
  • 52
  • 313
  • 390