Iterators in ColdFusion

In ColdFusion, an iterator is an object, which defines a sequence and a return value upon its termination. The iterator protocol defines a standard way to produce a sequence of values (either finite or infinite), and potentially a return value when all values have been generated.

ColdFusion Components can be made iterable and UDF's are used as iterators.

How to make a cfc iterable ?               

If the CFC implements __iter__ function with no arguments it will be called to get the iterator instance. The iterable function can return array, String, query, function (like below) or a cfc which has a function named __next()__.

CFC as an iterator

1
2
3
4
5
6
// Iterator.cfc
component {
    public any function __next__(previous, count){ // Follows Iteration Protocol as UDF
    return {value: count+1, done: count > 11};
}
}
1
2
3
4
5
6
# cfcAsIterator.cfc
component {
   public any function __iter__() {
      return new Iterator();
   }
}
1
2
3
4
5
6
7
8
9
// stringAsIterator.cfc
component{
    public any function __iter__() {
      
    str1="ColdFusion 2021";
    str2="Project Stratus";
      return [...str1,...str2];
   }
}

UDF as iterator

1
2
3
4
5
6
7
8
9
10
// udfAsIterator.cfc
//Example using UDF as Iterator and CFC is the Iterable
component {
   public any function __iter__() {
      var startFrom = 100;
      return function(previous, index){//Iterator UDF
         return {"value": startFrom + index, "done": index > 9};
      }
   }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
// udfAsIterator.cfm
<cfscript>
/*
Plain UDF/Closure/Lambda as Iterator
Invoking iterators using forin loop
 
*/
    iterator = (previous, count) =>{
      
        return {"value": count + 2, "done": count > 9};
    };
 
    writeoutput("----------- UDF/Closure/Lambda as Iterator -------------<hr>")
    for(i in iterator) {
        writeoutput(i & " " & "");
    }
     
    udfIteratorOBj = new udfAsIterator();
    stringIteratorObj= new stringAsIterator();
    cfcIteratorObj = new cfcAsIterator();
     
      
     writeoutput("----------- UDF as Iterator -------------<hr>")
     for(i in udfIteratorOBj) {
            writeoutput(SerializeJson(i) & "");
    }
    writeoutput("----------- String as Iterator -------------<hr>")
     for(i in stringIteratorObj) {
            writeoutput(SerializeJson(i) & "");
    }
     
    writeoutput("----------- CFC as Iterator -------------<hr>")
    for(i in cfcIteratorObj ) {
            writeoutput(SerializeJson(i) & "");
    }
</cfscript>

Output

----------- UDF/Closure/Lambda as Iterator -------------
3 4 5 6 7 8 9 10 11 12

----------- UDF as Iterator -------------
101.0102.0103.0104.0105.0106.0107.0108.0109.0110.0

----------- String as Iterator -------------
"C""o""l""d""F""u""s""i""o""n"" ""2""0""2""1""P""r""o""j""e""c""t"" ""S""t""r""a""t""u""s"

----------- CFC as Iterator -------------
2.03.04.05.06.07.08.09.010.011.012.013.0

Array as iterator

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// arrayAsIteratorwithSpread.cfc
component{
    public any function __iter__() {
     
    arr1=[1,2,3]
    arr2=[4,5,6]
      return [...arr1,...arr2];
   }
    
   function demofunc(){
    
    return "demostring!"
    
   }
}
1
2
3
4
5
6
7
8
9
10
// arrayAsIterator.cfm
<cfscript>
    arrayIteratorObj1= new arrayAsIteratorwithSpread();
 
writeoutput("----------- Array as Iterator 1-------------<hr>")
    for(i in arrayIteratorObj1 ) {
            writeoutput(i & "");
    }
 
</cfscript>

Output

123456