0
window.onload = function () {
    x = '';
    myArray =  [ {a:'a', b:'b'}, {a:'c', b:'d'}, {a:x, b:''} ];
    for (i = 0; i < myArray.length; i += 1) {
        x = myArray[i].a + myArray[i].b;
    }
    alert(x);  // alerts '';
}

Hi, the above is an example of what I'm trying to do. Basically, I would like for x to be evaluated after the 2nd array element computes it. I think this is called lazy evaluation, but not sure... I'm somewhat new.

How can I process my array in the loop and x be evaluated each time such that when I get to the third iteration, x = 'cd' and will alert as 'cd'?

C G
  • 25
  • 1
  • 6

2 Answers2

0

I think I figured out the answer with your help and the other thread I mentioned in the comment. Just need to wrap x in a function and then define a get function to apply to all elements:

window.onload = function () {
    function get(e) {return (typeof e === 'function') ? e () : e; }
    var x = '';
    myArray = [ {a:'a', b:'b'}, {a:'c', b:'d'}, {a:function() {return x; }, b:''} ];
    for (i = 0; i < myArray.length; i += 1) {
        x = get(myArray[i].a) + get(myArray[i].b);
    }
    alert(x); // alerts 'cd';
}

x can be anything then. For example (x + 'xyz') will alert 'cdxyz'. So this way I can have any variable that I want evaluated later (when needed) be evaluated correctly (based on state at that point).

That's what I needed. :)

C G
  • 25
  • 1
  • 6
-1
var elements = [ { a:"a", b:"b"}, {a:"c", b:"d"}, {a:"e", b:"f"} ];
function getter(list, num) {
    var i, agg = { a: "", b: "" };
    for (i = 0; i <= num; i += 1) {
        agg.a += list[i].a;
    }
    return agg;
}

console.log(getter(elements, 0).a); // "a"
console.log(getter(elements, 1).a); // "ac"
console.log(getter(elements, 2).a); // "ace"

You can use a closure so you can't access the values, like:

var elements = [ { a:"a", b:"b"}, {a:"c", b:"d"}, {a:"e", b:"f"} ];
function make_getter(list) {
    return {
        get: function (num) {
            var i, agg = { a: "", b: "" };
            for (i = 0; i <= num; i += 1) {
                agg.a += list[i].a;
            }
            return agg;
        }
    };
}
var getter = make_getter(elements);

console.log(getter.get(0).a); // "a"
console.log(getter.get(1).a); // "ac"
console.log(getter.get(2).a); // "ace"

You can make different implementations of the aggregation function.

With recursion:

var elements = [ { a:"a", b:"b"}, {a:"c", b:"d"}, {a:"e", b:"f"} ];
function getter(list, num) {
    var i, agg = list[num];
    if (num > 0) {
        agg.a = getter(list, num-1).a + agg.a;
    }
    return agg;
}

console.log(getter(elements, 0).a); // "a"
console.log(getter(elements, 1).a); // "ac"
console.log(getter(elements, 2).a); // "aace" <-- note, elements are actually modified!
console.log(getter(elements, 2).a); // "aaacaace" <-- note, elements are actually modified!

old answer

Since x is not an object it's value will be copied, rather than passed as a reference.

If you change your code to:

var element = { a: '', b:'' };
myArray =  [ {a:'a', b:'b'}, {a:'c', b:'d'}, element ];
for (i = 0; i < myArray.length; i += 1) {
    element.a = myArray[i].a + myArray[i].b;
}
alert(el.a);  // alerts 'cd';

You will get "cd".


This is not called lazy evaluation by the way. It's just an aggregate or something.

Halcyon
  • 57,230
  • 10
  • 89
  • 128
  • I see that and it does help, but I have many such arrays with all variety of json objects and various properties. So it would be difficult to separately defined each of these elements. Is there a way to tell Javascript to wait on evaluating x (not do it in the initial assigned of myArray), and to evaluate each array element when it is referred to in the loop. For example, x could be a more complex statement than just a variable. I don't want to use 'eval' either. Thank you. – C G Sep 11 '13 at 15:22
  • Please explain your problem better. – Halcyon Sep 11 '13 at 15:23
  • Each, but not all, of the array elements are dependent on the results from processing a prior array element. The example I gave was very simple. But x could be dependant on what prior myArray iterations created or changed. I don't want to have x be evaluated until it is it's turn to be evaluated (on the 3rd iteration). I may even have more elements after this with other variables which are to be evaluated when it comes their turn. Basically, I don't want variables to be evaluated until it's their turn in the processing of the array elements. Hope that helps. – C G Sep 11 '13 at 15:28
  • The word you're looking for is `on-the-fly`. I can write an example for you. – Halcyon Sep 11 '13 at 15:34
  • Certainly is interesting, but I have to admit this is a bit over my head at the moment. I will need to play with it for a while to fully understand what you're doing. If a:"e" were a:x, then that would help since I'm trying to say a: should have the value x, but not be determined until that iteration. Your example may do all that, but like I said it will take me a bit to play around with it and comprehend it. Thank you. – C G Sep 11 '13 at 15:48
  • I still don't see how this answers my original question. You've removed x from the original array. let's say a: was set to x + 'abc' in the original array: {a:'a', b:'b'}, {a:'c', b:'d'}, {a:x+'abc', b:''}. I still don't want x to evaluated until the first two array items are finished processing in the loop. the a: of the third array element needs to be defined, but not evaluated until ready. Does your example do that? – C G Sep 11 '13 at 16:25
  • This appears to be relevant and may hold the answer I'm looking for: http://stackoverflow.com/questions/2952573/any-way-to-define-getters-for-lazy-variables-in-javascript-arrays?rq=1 – C G Sep 11 '13 at 17:05