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")
)