How to iterate over an array in FQL passing both the element and its index to the lambda?

Hi, I’d like to iterate over an array and pass both the current element and its index within the array to the corresponding lambda function. In javascript I might do something like:

array.forEach((element, index) => ...

How could I achieve something like this in FQL?

Javascript is fairly unique in how it adds the optional arguments to Array.prototype.map and Array.prototype.forEach. Other languages don’t typically do this, especially those that adhere more strictly to functional programming and the mathematical laws that underpin it.

THAT SAID, the javascript functions are rather convenient and my jibber-jabbering doesn’t help solve your problem. I only want to highlight that it is intentional, and normal, that FQL does not include these extra arguments.

So, how can we track the index as we iterate over an array? How would you do it in javascript if we were to ignore the index argument exists. Well, what other functions or patterns do we have at our disposal?

Just like javascript, there is a Reduce function in FQL. With Reduce we can carry around a counter that tracks which iteration we are on.

forEach with index

For simulating a forEach method, we don’t care about the results of the last iteration, so the only thing we will store in the accumulated value is the index.

Let(
  {
    some_array: ["a", "b", "c"],
    for_each_with_index: Reduce(
      // reducer function
      Lambda(["index", "value"], 
        Do(
          // Some operation you need to do for each item in the array
          Create(Collection("things"), { data: { value: Var("index") } }),
          // The Do function only returns the value from the last expression
          // Increment the index and return it
          Add(Var("index"), 1)
        )
      ),
      // initial index value
      0,
      // array to iterate over
      Var("some_array")
    )
  },
  "DONE!" // some result
)

map with index

For simulating a map method with an index, we do want to carry around the values of the previous iterations.

Let(
  {
    some_array: ["a", "b", "c"],
    map_with_index: Reduce(
      // reducer function
      Lambda(["acc", "value"], Let(
        {
          // pull the previous results from the accumulated value
          results: Select(0, Var("acc")),
          // pull the index out of the accumulated value
          index: Select(1, Var("acc")),
          // Some operation you need to do for each item in the array
          operation: Create(Collection("things"), { data: { value: Var("index") } }),
        },
        // return the entire result with the next index
        [
          // Append the result
          Append(Var("operation"), Var("results")), 
          // Increment the index
          Add(Var("index"), 1)
        ]
      ),
      // initial value = [result, index]
      [[], 0],
      // array to iterate over
      Var("some_array")
    ),
    results: Select(0, Var("map_with_index")),
  },
  // return the results
  Var("results")
)
2 Likes

This topic was automatically closed 2 days after the last reply. New replies are no longer allowed.