Recently, I started learning a couple of functional languages through online MOOCs:
Update: I created a Github page with other functional examples.
Swift isn’t classified as a functional language. However, that doesn’t mean we can’t use lessons learned from functional programming to improve our code. In this article, I illustrate a few ways my programming has changed after a couple of weeks of functional programming.
[].filter
There are many places in my code that looked something like this snippet:
self.retestQuestions = [] for q in questionList { if !q.isAnsweredCorrectly { self.retestQuestions.append(q) } }
This translates to one line of Swift code:
let retestQuestions = questionList.filter({!$0.isAnsweredCorrectly})
In the past, I’ve used filter() to replace NSPredicate statements, which I used extensively in Objective C. In my first conversion to Swift, I directly translated my Objective C to Swift then cast my Swift array back to an NSArray to get the filter to work. Roughly my code looked like this:
let predicate = NSPredicate(format: "numWordsInGroup >= \(minWordCount) and numPicturesInGroup >= \(minPictureCount)") let answer = (a1 as NSArray).filtered(using: predicate)
Embracing the Array filter() function makes a lot more sense:
let answer = a1.filter({$0.numWordsInGroup >= minWordCount && $0.numPicturesInGroup >= minPictureCount})
After only a couple of weeks of functional programming, I’ve noticed many places in my code where this example, and other
[].forEach
The forEach() function isn’t a functional concept. However, without going into detail, my functional programming has led me to prefer using the Array forEach function more often. Here are several snippets from my code:
Add subviews to parent
[pronounView, answerWellView, answerConjugationView].forEach {self.mainContainerView.addSubview($0)}
Update: Someone pointed out on Reddit that this can be simplified:
// Simply pass func to apply to each element [pronounView, answerWellView, answerConjugationView].forEach (mainContainerView.addSubview)
Active constraints
[c1, c2].forEach {NSLayoutConstraint.activate($0)}
Applying the same concept of passing the function as an argument to forEach(), activating constraints is even simpler.
[c1, c2].forEach(NSLayoutConstraint.activate)
translatesAutoresizingMaskIntoConstraints and addSubviews
[answer1Btn, answer2Btn, answer3Btn, answer4Btn].forEach { $0.translatesAutoresizingMaskIntoConstraints = false self.cardFrontSubView.addSubview($0) }
Disable and hide buttons
[answer1Btn,answer1Btn,answer3Btn,answer4Btn].forEach { $0.isEnabled = false $0.isHidden = false }
Conclusion
I’ve just finished the second week, of a six week, Haskell MOOC. Hopefully, soon I’ll be using more functional concepts and my code will be “cleaner”, and more importantly contain fewer bugs.