Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Code Block
languagejavascript
themeConfluence
select when pageviewwovyn url "/archives/"
new_temperature
  foreach [1, 2, 3] setting (x,i)

The foreach statement Is an iterator. This statement would execute the entire rule three times with the variable x bound to 1, 2, and 3 in each successive execution. A second name is optional in the setting clause. Here, the name i will be bound to the index of each array element, i.e. 0, 1, and 2 in each successive execution.

The value following the keyword foreach can be any KRL expression that yields an array or map.  If the variable f were bound to a JSON data structurean array, you could use a pick and JPex loop over the f like so:

Code Block
languagejavascript
themeConfluence
select when web pageview url "/archives/"re#archives#
  foreach f.pick("$..store") setting (x)

To use the foreach statement with a map, you provide two variables in the setting clause that will be bound the name and value of that entry in the map:

Code Block
languagejavascript
themeConfluence
select when web pageview url "/archives/"re#archives#
  foreach {"a" : 1, "b" : 2, "c" : 3} setting (v,n,v)

This would bind a, b, and c to n along with 1, 2, and 3 to v on each successive iteration through the loop.

...

titleEngine Compatibility

...

.

You can have more than one loop in a rule by simply nesting one foreach inside another:

Code Block
languagejavascript
themeConfluence
select when web pageview url "/archives/"re#archives#
  foreach [1, 2, 3] setting (x)
    foreach ["a", "b", "c"] setting (y)

...

The entire rule body—everything after the select—is executed once for every loop. If the rule condition is true, an action is produced, so a rule with a foreach over a three-element array would produce three actions if the condition were true each time. (Note: KRL optimizes rule preludes by automatically moving expressions that don’t depend on the variable being set in the foreach statement outside the loop during execution so that only those things that really need to be executed multiple times are.)

There is also a guard condition called "on final" that will allow you to execute a postlude statement only on the last iteration of the foreach.

When to Use a Loop

Warning
titleEngine Compatibility

Much of the example code in this section needs to be rewritten; it uses deprecated features like pick() and page:url() only found in the classic pico engine. But, the idea of using a filter instead of a loop is still valid. 

Your instincts might be to use foreach loops in places where it’s less efficient than using implicit looping. To see when you might want to use a JPex instead of a foreach statement let’s walk through an example. 

...

Code Block
languagejavascript
themeConfluence
rule using_foreach {
   select when web pageview url ".*"
      foreach items setting (d)
      pre {
         h = d.pick("$.header") + " using foreach";
         c = d.pick("$.content");
         domain = page:url("domain");
      }
      if(domain eq d.pick("$.page")) then
        notify(h,c);
 }

...

Code Block
languagejavascript
themeConfluence
rule using_foreach_with_filter {
   select when web pageview url ".*"
      foreach items.filter(
               function(x) {page:url("domain") eq
                            x.pick("$.page")}) 
         setting (d)
      pre {
         h = d.pick("$.header") + " using foreach";
         c = d.pick("$.content");
         domain = page:url("domain");
      }
      if(domain eq d.pick("$.page")) then
        notify(h,c);
 }

...

Code Block
languagejavascript
themeConfluence
rule without_foreach {
   select when web pageview url ".*"
   pre {
     dom = page:url("domain");
     item = site_data.pick(
            "$..items[?(@.page eq '"+dom+"')]");
     content = item.pick("$..content");
     header = item.pick("$..header")
        + " without foreach";
   }
   if(dom eq item.pick("$..page")) then
     notify(header,content);
}

...

As we’ve seen, foreach causes the same rule to be fired multiple times in a single ruleset evaluation. Some actions are better suited to use inside a foreach loop than others. For example, issuing multiple redirect() actions from a single rule doesn’t usually make sense. But other actions like append(), replace(), send_directive(), and so on are often done over and over with different data. An example illustrates this idea.

...

Code Block
languagejavascript
themeConfluence
rule prepend {
   select when web pageview where url == "windley.com"
     foreach replacements.pick("$.replacements")
             setting (r)
     pre {
       sel = r.pick("$.selector");
       new_text = r.pick("$.text");
     }
     prepend(sel,new_text);
}

...