Confused about $0 and $1 in array/closure

Hi,

Watching this video:

I don't fully understand his explanation about $0 and $1.
What does it mean that $1 is next iteration?

What would be 1$ in this case?
I can't wrap my head around it. :innocent:

Thanks in advance

$0 and friends are special variable names for parameters passed into closures. So in the case of reduce it is the result and element parameters but written as the shorthand version.

You could write that line as:

let totalUsers = appPortfolio.reduce(0) { total, app in
  total + app.users
}
5 Likes

I played with it a bit and this helped me understand what values are assigned. Thanks.

let numbers = [1, 2, 3, 4, 5]

let totalUsers = numbers.reduce(into: 0) { total, app in
  print(total)
}

Printing total outputs:

0
0
0
0
0
let numbers = [1, 2, 3, 4, 5]

let totalUsers = numbers.reduce(into: 0) { total, app in
  print(app)
}

Printing app outputs:

1
2
3
4
5

I think this probably is a question about the behavior of reduce specifically rather than the behavior of $1 in general, yes?

Not sure if you saw my post above, but I was wondering what exactly gets assigned to $1 and $0 in this case.

Right, Philippe answered about what they mean in general, but I think you were asking about what they mean in this specific case, is that right?

Yes.

I think the problem here is in the video the presenter is giving a confusing description of $0 as “the placeholder for each iteration through the array”. Combined with “remember I told you” this implies $0 here is like $0 in map and filter from earlier but it isn’t. For reduce, $0 is the “accumulation” value as you iterate over the array, and $1 in the reduce closure is like $0 in map or filter – each element from the array. Also the “tricky” autocomplete values they quickly delete show the argument names for the function, which would help explain this difference.

Personally, I think it’s better to teach reduce in the opposite order to this video.

Start with the for loop version:

var totalUsers = 0
for app in appPortfolio {
  totalUsers = totalUsers + app.users
}

Then, introduce reduce with the same variable names, pointing out totalUsers is passed back in on each iteration:

let totalUsers = appPortfolio.reduce(0) { totalUsers, app in
  totalUsers + app.users
}

And then show how you can use the terse shorthand for the two closure arguments:

let totalUsers = appPortfolio.reduce(0) { $0 + $1.users }

Finally, if you want, show the cute trick that you can pass in a function point-free into reduce and, even cuter, that function can be an operator and voila numbers.reduce(0,+) works to sum an array of numbers.

10 Likes

Also addition doesn’t help by being commutative, so you can mix up the order and it’ll still work…

There’s an argument reduce(into:) is better starting point for teaching, especially because most people would write the for loop as totalUsers += app.users.

5 Likes