6
\$\begingroup\$

For fun, I made a function queue in JavaScript. I named it tinyq. You can add functions to it, and each function is passed the next function in the queue. You can also pass parameters to the functions, and they can return values.

function q(){
    var Q = [], t = this;
    this.length = 0;
    this.add = function (f){
        Q.push(f);
        this.length++;
    };
    this.run = function(){
        var n = Q.shift();
        this.length = Q.length;
        if(typeof n === 'function'){
            var a = Array.prototype.slice;
            return n.apply(window,[function(){
                return t.run.apply(t, a.call(arguments));
            }].concat(a.call(arguments)));
        }
    };
}

Here's a simple example of its use.

var Q = new q;
Q.add(function(next, A, B){
    return A + ": "+ next(B);
});
Q.add(function(next, C){
    return C + "123";
});
console.log(Q.length); // 2
console.log(Q.run("Test", "ABC")); // "Test: ABC123"

So, what do you think of my function queue? Any improvements, or anything I'm doing wrong?

P.S. I was also trying to make this small, any suggestions on making it smaller?

\$\endgroup\$
  • 1
    \$\begingroup\$ I feel like I'm not really understanding the purpose behind this. It seems like really complicated function composition. I realize the sample is purposely simple, so how else could this be used in a way more complicated than functional composition? \$\endgroup\$ – jdmichal Jan 30 '12 at 5:30
  • \$\begingroup\$ @jdmichal: To be honest, I just wrote this for fun, with no reason for its existence. Is there a better way to do function composition that would still work with a queue? \$\endgroup\$ – Rocket Hazmat Jan 30 '12 at 15:22
  • \$\begingroup\$ No worries; just trying to wrap my brain around the intended functionality. :) I'll add an answer to show how I would do simple function composition. \$\endgroup\$ – jdmichal Jan 31 '12 at 1:56
  • 1
    \$\begingroup\$ Hi @RocketHazmat I just came up with my own Queue implementation a few days ago when answering an SO question. Here is my CR OP: codereview.stackexchange.com/q/28380/3163 ^_^ Have fun with it! \$\endgroup\$ – Naftali aka Neal Jul 11 '13 at 20:00
2
+50
\$\begingroup\$

I'm not entirely sure where queue semantics are coming into play here. If you just walked up to me and told me you had a function queue for JavaScript, I would expect that I could add a bunch of functions to it, and then it would call them in sequence. But that's not what I'm seeing here.

What I am seeing is a really weirdly formed function composition. Here's how I would do the sample given:

// Create function to show a value with a label.
// Note that it takes a value function, rather than a pure value.
// It also takes any number of arguments for that function, as an array.
var showWithLabel = function (label, valueFunction, valueArguments) {
    return (label + ": " + valueFunction.apply(undefined, valueArguments));
};

// Create a function to append "123" onto a string.
var append123 = function (string) {
    return (string + "123");
};

// Simple call to execute them together.
showWithLabel("Test", append123, ["ABC"]);

// Actually composite them into a new function.
// This function is the equivalent of the run function.
var composite = function (label, value) {
    return showWithLabel(label, append123, [value]);
};

// Now call the composite.
composite("Test", "ABC");

Please comment and discuss here. I want to have a conversation about this, because I feel like there's probably some functionality I'm not understanding about the queue.

\$\endgroup\$
  • \$\begingroup\$ This queue can support adding functions and calling them in sequence. Just remove all parameters (except next) and it'll work that way. I added the parameter thing for fun. Guess it really doesn't have much real use. This is a neat example, btw. Nice and simple. \$\endgroup\$ – Rocket Hazmat Jan 31 '12 at 2:08
  • 1
    \$\begingroup\$ Oh, I see. You can call run multiple times and it will keep reducing the queue down. I must admit that I also don't see much use for that, and I have done a pretty good amount of browser JavaScript coding. Interesting idea though. \$\endgroup\$ – jdmichal Jan 31 '12 at 2:15
  • \$\begingroup\$ You can call run to run the next item and reduce the queue. Each item is passed next. Calling next will also call the next function and reduce the queue. Both run and next can pass parameters to the function in the queue that's being ran. \$\endgroup\$ – Rocket Hazmat Jan 31 '12 at 3:27
8
\$\begingroup\$

I'm still trying to wrap my head around what exactly is happening in that apply/call mass :-)

But that may be a hint, that those three lines aren't really well readable. I'm aware you want to keep it small, but unless the code needs to be really, really fast (which I doubt it does) I would prefer readability over shortness.

In that line, I would prefer to have long, more expressive variable names. It be better to use complete words instead of Q, t, n, a etc.

If in the end, shortness is still important, then use a JavaScript compressor.

BTW, you should keep JavaScript naming conventions in mind, too. Constructor functions ("classes") should be named with capital letters (Q instead of q) and fields should use small letters (q instead of Q).

Just out of interest: Can you give a concrete use case for this kind of queue?

\$\endgroup\$
  • \$\begingroup\$ I really don't have a real use case right now, this is just something I made for fun. I was trying to make a queue like jQuery's .queue with more features. Yeah, the .apply/.call thing is the heart of this script, and I agree it looks odd. I can try to explain it. a.call(arguments) turns the arguments "array" into a real array, so I can pass it to apply. n.apply calls the next function in the queue, and t.run.apply is a reference to run which when called triggers the next function in the queue. \$\endgroup\$ – Rocket Hazmat Jan 13 '12 at 14:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.