I’m really interested in Functional Programming, and have made it a point to use map(_:), filter(_:) etc wherever possible while following the iOS tutorials.
I chose to use filter(_:) for the following method:
func countUncheckedItems() -> Int {
var count = 0
for item in items where !item.checked {
count += 1
}
return count
}
my method using filter(_:)
func countUncheckedItems() -> Int {
return items.filter { item in !item.checked }.count
}
A few pages down I found that the author took a moment to make an example of this method as an intro to Functional Programing and wrote the method using reduce(_:_:) which got me thinking…
func countUncheckedItems() -> Int {
return items.reduce(0) { cnt, item in cnt + (item.checked ? 0 : 1) }
}
I understand how to use both, but as a beginner I worry that there is a reason unbeknownst to me as to why filter was not used instead.
If it’s a matter of style / the author’s preference that’s fine.
I am just concerned that perhaps there is a situation where using filter here would fail, and reduce is the better option because it will always produce the same output - which is the goal in functional programming.
I would say both ways will work reliably. The main difference is that filter builds a new list, from which you then get the count; while reduce traverses the existing list, adding a 1 or a 0 to the running total. So reduce does not build a new list, which means less memory use. Reduce is arguably a more direct expression of your intention here, which is also a goal of functional programming.
ahh!!! Brilliant! Thank you so much for your reply!
I’m SUPER interested in functional programming.
So would you consider it self mutating?
I’m making a correlation between it being named reduce(), not reduced() and sort() (which self mutates) vs sorted() which will make a new array?
No, Reduce does not change the array, and does not return an array either. It returns a single value, the result of calling the closure for each element in the array. Filter also does not mutate, it returns a new array.
The dual syntax ala “sort” and “sorted” seems to occur when it could either change the array or return a new array.
Understood.
tbh reduce() is the weakest of all my understandings of Swift’s first class funcs - my exposure to it has been simple: sum arrays/sequences so I wasn’t at all excited about it. Your info is much appreciated, I have a new respect and interest in reduce(_:)
I prefer the trailing closure syntax with shorthand param/arg names because the patterns seem clearer to me. I was able to fool around with reduce and get this to do the same desired affect as the author’s reduce with param names.
My thoughts are either that the author did not wish to go into details on how to implement an Equatable/Conformable protocol, or that there is a good reason why it was written as such.
I have never seen the method .localizedStandardCompare before and the Documentation states it’s a Generic instant Method on StringProtocol.
Is it used primarily if the coder does not expect to utilize Comparable more than once? Is having Checklist adopt the protocol overkill?
I think the reason not to adopt Comparable as you have suggested is that CheckListItems don’t have a natural sort order. CheckListItems could be sorted by name, or by date, or by checked and then date, and so on. Comparable is usually for things that act like a single value and have one natural way to sort them.
.localizedStandardCompare is from NSString, and makes file name comparisons the same in different locales. I don’t think it is needed here; swift lets you just use operators: a.name < b.name