Search code examples
cfmllucee

Lucee array.each return value


On Lucee 4.5.1.003 I have this function where LineArray is an array of LineItem objects.

public function getLineItemDetailsById(required numeric id){
    this.LineArray.each(function(i){
        if(i.Id == id){
            return i;
        }
    });
}

The function returns null even if there is a match. If I add a var to hold the found object, the var is returned.

public function getLineItemDetailsById(required numeric id){
    var found = '';
    this.LineArray.each(function(i){
        if(i.Id == id){
            found = i;
            //return i;
        }
    });
    return found;
}

Am I doing something wrong expecting array.each to return i or am I misunderstanding how array.each works?

Edit: To be clear, the second function does return the found object.


Solution

  • You need to look slightly closer at the code in your first example:

    public function getLineItemDetailsById(required numeric id){ // first function
        this.LineArray.each(function(i){ // second function
            if(i.Id == id){
                return i; // return for second function
            }
        });
        // no return from first function
    }
    

    I have annotated it slightly to demonstrate your problem. getLineItemDetailsById() "returns null" because you simply aren't returning anything from it. So if you have:

    result = getLineItemDetailsById(1);
    

    then getLineItemDetailsById() is not returning anything, so result ends up being null.

    So that's the problem you're seeing.

    Furthermore, you don't want to be using each() within that function: one would only use each() when you definitely want to iterate over the entire array. In your case it seems like you want to exit as soon as you find a match for id.

    In which case you want something like this:

    public function getLineItemDetailsById(required numeric id){
        var matchedElement = null; 
        this.LineArray.some(function(element){
            if(element.Id == id){
                matchedElement = element;
                return true;
            }
        });
        return matchedElement;
    }
    

    One uses some() when one wants to iterate over an array only until some criteria is matched. Here I'm leveraging this to set the matchedElement when the exit criteria is met.