A blog exploring functional programming and Swift.

Announcing SwitchStore for the Composable Architecture

Monday Jun 14, 2021

This week’s episode took a deep dive into how we can embrace some of Swift’s most important data modeling tools (optionals and enums) in the Composable Architecture without sacrificing composition of our application’s behavior. We showed that one our very own case study applications, the Tic-Tac-Toe app demo, modeled its root state in a less than ideal fashion: using two optional values instead of an enum. This allows invalid states to be representable in our application, which leaks into application logic making it more complex, and so we’d love to make those states unrepresentable by the compiler.

Unfortunately, the Composable Architecture does not come with the tools necessary to properly use enums for state… well, until today that is! We are releasing a new version of the library that adds a pullback method on Reducer and a SwitchStore view that are specifically tuned for breaking down behaviors modeled on enum state into behavior for each case of the enum.

Reducer.pullback

We often want to model the state of a part of our applications using an enum to represent mutually exclusive states. For example, at the root of our application we may separate the logged-in and logged-out states into cases of an enum:

enum AppState {
  case loggedIn(LoggedInState)
  case loggedOut(LoggedOutState)
}

In the Composable Architecture we like to define reducers on sub-state and then use the pullback and combine operators to piece multiple reducers together into one big reducer that operates on bigger pieces of state. The pullback operator accomplishes this by using a WritableKeyPath to extract out sub-state, operate on it, and then plug it back into the whole state. So we would hope we could define a reducer for each of the logged-in domain and logged-out domain that could then be pieced together to operate on the entire app domain.

However, when state is modeled as an enum we do not have access to key paths. We instead need a way to try to extract a particular case from the state enum, operate on it, and then embed it back into the state enum. This is precisely what case paths excel at, which is the analogous concept for key paths, but tuned specifically for enums instead.

So, rather than pulling back a reducer along a key path to some sub-state we can instead pull back along a case path to a sub-case:

let loggedInReducer: Reducer<LoggedInState, LoggedInAction, LoggedInEnvironment> = ...

let loggedOutReducer: Reducer<LoggedOutState, LoggedOutAction, LoggedOutEnvironment> = ...

let appReducer = Reducer.combine(
  loggedInReducer.pullback(
    state: /AppState.loggedIn,
    action: /AppAction.loggedIn,
    environment: { LoggedInEnvironment(...) }
  ),

  loggedOutReducer.pullback(
    state: /AppState.loggedOut,
    action: /AppAction.loggedOut,
    environment: { LoggedOutEnvironment(...) }
  )
)

SwitchStore

While the pullback operator helps us compose the logic of our application, the SwitchStore view helps us compose the behavior of our application. It serves the same purpose that the IfLetStore serves for optionals and the ForEachStore serves for collections, but is tuned specifically for enums. It allows you to destructure a store into multiple stores, one for each case of your state’s enum.

For example, if we had a LoggedInView and LoggedOutView to represent the root view for each of the logged in and out states, then we could “switch” on the root store in order to figure out which view to display:

SwitchStore(self.store) {
  CaseLet(state: /AppState.loggedIn, action: AppAction.loggedIn) { loggedInStore in
    LoggedInView(store: loggedInStore)
  }

  CaseLet(state: /AppState.loggedOut, action: AppAction.loggedOut) { loggedOutStore in
    LoggedOutView(store: loggedOutStore)
  }
}

Under the hood the SwitchStore view figures out whenever your state enum’s case changes from the .loggedIn case to the .loggedOut case (or vice-versa), and will make sure the correct view is displayed. You can also leverage SwiftUI’s transition APIs to automatically animate when the views appear or disappear:

SwitchStore(self.store) {
  CaseLet(state: /AppState.loggedIn, action: AppAction.loggedIn) { loggedInStore in
    LoggedInView(store: loggedInStore)
      .transition(.opacity.combined(with: .offset(x: 0, y: 20))
  }

  CaseLet(state: /AppState.loggedOut, action: AppAction.loggedOut) { loggedOutStore in
    LoggedOutView(store: loggedOutStore)
      .transition(.opacity)
  }
}

This will make it so that the LoggedInView appears with a crossfade and a small vertical translation, whereas the LoggedOutView will just appear with a crossfade.

Performance

The SwitchStore view has a few tricks up its sleeve in order to do its job with the best performance possible. If implemented naively, the SwitchStore would re-compute its body when any piece of state changes inside the enum. However, we only care when the state enum changes from one case to another case so that we can show the respective view. We don’t need to know about all the changes within a particular case.

By taking advantage of Swift’s powerful metadata embedded in every Swift program we can write a function that determines the case of any enum, and so so blazingly fast. This metadata is the same info that SwiftUI uses to its seemingly magic behavior. It’s an advanced feature of Swift that doesn’t get enough attention, but it allows the SwitchStore to minimize the number of times it needs to re-compute its body.

Try it today

Upgrade to the latest version of swift-composable-architecture to immediately gain access to these tools today, and enhance your applications with the expressiveness of enum state. We’ve already made use of SwitchStore to refactor the Tic-Tac-Toe demo to improve its domain modeling by using proper enums instead of two optionals 🥳.


WWDC Sale

Monday Jun 7, 2021

The year’s biggest Apple event is here, and to celebrate we are offering a 25% discount off the first year for first-time subscribers. Click here to redeem the coupon now. The offer will only remain valid until June 11th.

This is the perfect time to get full access to our videos. Some of our hits include:

  • Building an application architecture from scratch that is perfectly suited for SwiftUI and UIKit applications.
  • Case studies that dive deep into solving common, real-world problems.
  • An extensive and practical study of dependencies, showing how to take control of dependencies to unleash some amazing benefits.
  • A deep-dive into parsing exploring techniques for parsing complex string formats, with a focus on composition and performance.
  • And more…

We hope you’ll join us for all of the great material we have planned for the rest of the year!


A Tour of isowords

Wednesday May 12, 2021

This past month we released four completely free videos dedicated to diving into the real-world Swift code base of an iOS game we recently launched and open sourced: isowords.

In them we explore the client app and its backend Swift server to show how concepts covered in previous episodes of Point-Free can be applied to a production code base.

  • A Tour of isowords: Part 1: We start the tour by pulling down the repo and bootstrapping the iOS app. Then, we dive into the code to show off our modern approach to project management using the Swift Package Manager. We also explore how the Composable Architecture, a library we built from first principles over a number of Point-Free episodes, powers the entire application.

  • A Tour of isowords: Part 2: We explore how adopting the Composable Architecture aided in the ability to easily (and extensively) modularize the code base. This unlocked many things that would have otherwise been much more difficult, including the ability to add an onboarding experience without any changes to feature code, an App Clip experience, and even automated App Store assets.

  • A Tour of isowords: Part 3: We take a peek at the Swift server that powers the game’s backend. We get things running the server locally and explore some of the benefits of developing both client and server in Swift, such as simultaneously debugging both applications together, and how code and concepts can be shared across each application.

  • A Tour of isowords: Part 4: We wrap up our tour by showing off two powerful ways the iOS client and Swift server share code: not only does the same code that routes server requests simultaneously power the API client, but we can write integration tests that exercise the full client-server lifecycle.

We hope these episodes provide a small taste of some ideas in application development and architecture that we find interesting, and we hope you do too. If you want a go deeper in your exploration of topics related to architecture, dependency management, SwiftUI, and more, check out our ever-growing collections of episodes today!


Older blog posts

Monday Mar 22, 2021

Better Testing Bonanza

We're open sourcing a library that makes it easier to be more exhaustive in writing tests.

Wednesday Mar 17, 2021

Open Sourcing isowords

We're open sourcing the entire code base to our newly released iOS word game, isowords!

Wednesday Mar 17, 2021

Announcing: isowords

We are excited to release isowords to the App Store, a new word search game for your phone. Download today!

Monday Mar 8, 2021

Composable Architecture Test Store Improvements

Composable Architecture 0.16.0 comes with significant improvements to its testing capabilities for tracking down effect-related failures.

Monday Feb 1, 2021

Composable Forms: Say "Bye" to Boilerplate!

Today we are releasing first-party support for concisely handling form data in the Composable Architecture.

Wednesday Dec 23, 2020

End-of-year sale: 25% off Point-Free

Through the new year, we're offering personal Point-Free subscriptions for 25% off the first year!

Wednesday Dec 23, 2020

2020 Year-in-review

The Composable Architecture, dependency management, parsers, Combine schedulers and more! Join us for a review of everything we accomplished in 2020!

Monday Dec 21, 2020

Open Sourcing Parsing

Today we are open sourcing Parsing, a library for turning nebulous data into well-structured data, with a focus on composition, performance, and generality.

Tuesday Jun 30, 2020

The Composable Architecture and SwiftUI Alerts

Today we are releasing a new version of the Composable Architecture with helpers that make working with SwiftUI alerts and action sheets a breeze.

Monday Jun 22, 2020

Core Motion support in the Composable Architecture

We are releasing our second mini-library for the Composable Architecture, which makes it easy to use Core Motion.

Monday Jun 15, 2020

Open Sourcing CombineSchedulers

Today we are open-sourcing CombineSchedulers, a library that introduces a few schedulers that makes working with Combine more testable and more versatile.

Wednesday May 27, 2020

Instrumenting features built in the Composable Architecture

Today we are releasing first-party support for instrumenting features built in the Composable Architecture.

Wednesday May 20, 2020

Core Location support in the Composable Architecture

We are releasing a mini-library that makes it easy to use Core Location inside the Composable Architecture.

Tuesday May 12, 2020

Regional Discounts

Regional discounts takes 50% off a monthly or yearly personal subscription to anyone whose credit card is issued from a particular list of countries.

Monday May 4, 2020

Composable Architecture, the library

Today we are releasing the Composable Architecture as an open-source library. It is a way to build applications in a consistent and understandable way, with composition, testing and ergonomics in mind.

Wednesday Mar 11, 2020

Announcing Episode Collections

After over two years and nearly 100 episodes we are finally launching episode collections on Point-Free!

Friday Feb 21, 2020

Share Point-Free with friends and save!

Today we're excited to announce support for referral bonuses! When friends and colleagues of yours subscribe to Point-Free with your referral link, both of you will get one month free.

Tuesday Feb 4, 2020

Open Sourcing Case Paths

Today we are open sourcing CasePaths, a library that introduces the power and ergonomics of key paths to enums!

Monday Dec 30, 2019

2019 Year-in-review

Random number generators, parsers, SwiftUI, composable architecture and more! Join us for a review of everything we accomplished in 2019!

Monday Dec 23, 2019

Snapshot Testing SwiftUI

Snapshot testing gives us broad test coverage on our SwiftUI views with very little up front work.

Wednesday Dec 18, 2019

Free Video: Testing SwiftUI

A free video exploring how to test SwiftUI.

Wednesday Nov 20, 2019

A Crash Course in Combine

Two free videos exploring Apple's new Combine framework, its core components, and how to integrate it in your code.

Thursday Nov 7, 2019

Higher-Order Snapshot Testing

How to enrich snapshot testing strategies with additional behavior using higher-order constructions.

Tuesday Jul 30, 2019

SwiftUI and State Management Corrections

Xcode 11 beta 5 has brought lots of changes to SwiftUI, and we'd like to take a moment to provide corrections to our episodes based on these changes.

Thursday May 9, 2019

Enterprise Subscriptions

Point-Free now supports enterprise subscriptions, making it easier than ever to manage a team subscription for larger organizations! For a fixed yearly rate, everyone with an email from your company's domain will get instant access to everything Point-Free has to offer. Contact us for more info!

Monday Apr 29, 2019

Open Sourcing Enum Properties

We wanted to make Swift enum data access as ergonomic as struct data access, so today we are open sourcing a code generation tool to do just that!

Monday Mar 18, 2019

Open Sourcing Gen

Today we are open sourcing Gen: a lightweight wrapper around Swift's randomness API's that makes randomness more composable, transformable and controllable!

Tuesday Jan 8, 2019

Announcing swift-html 0.2.0

Announcing swift-html 0.2.0: support for CocoaPods, Carthage, SnapshotTesting, and more!

Wednesday Dec 19, 2018

2018 Year-in-Review

41 episodes, 19 hours of video, 25 blog posts, 8 open source libraries, 3.8K stars, 36K visitors, and we’re just getting started?

Monday Dec 3, 2018

SnapshotTesting 1.0: Delightful Swift snapshot testing

Today we are open sourcing SnapshotTesting 1.0: a modern, composable snapshot testing library built entirely in Swift!

Monday Oct 29, 2018

Some news about contramap

We've seen that contramap is a powerful operation, but the name isn't fantastic. We propose a much more intuitive name for this operation, and in doing so make our code much easier to read.

Tuesday Oct 9, 2018

How to Control the World

APIs that interact with the outside world are unpredictable and make it difficult to test and simulate code paths in our apps. Existing solutions to this problem are verbose and complicated, so let's explore a simpler solution by embracing singletons and global mutation, and rejecting protocol-oriented programming and dependency injection.

Monday Oct 8, 2018

Watch episodes in your favorite podcast app!

Follow along with the newest Point-Free episodes using your favorite podcast app. We now support podcast-friendly RSS feeds for viewing all of our videos.

Thursday Sep 20, 2018

Random Zalgo Generator

Let's create a random Zalgo text generator using the simple Gen type we defined in this week's episode!

Thursday Sep 13, 2018

Type-safe HTML with Kitura

Today we're releasing a Kitura plug-in for rendering type-safe HTML. It provides a Swift compile-time API to HTML that prevents many of the runtime errors and vulnerabilities of traditional templated HTML rendering.

Thursday Sep 13, 2018

Type-safe HTML with Vapor

Today we're releasing a Vapor plug-in for rendering type-safe HTML. It provides a Swift compile-time API to HTML that prevents many of the runtime errors and vulnerabilities of traditional templated HTML rendering.

Wednesday Sep 12, 2018

Open sourcing swift-html: A Type-Safe Alternative to Templating Languages in Swift

Today we are open sourcing a new library for building HTML documents in Swift. It's extensible, transformable, type-safe, and provides many benefits over templating languages.

Friday Aug 17, 2018

Overture 0.3.0: Now with Zip

Today we are releasing Overture 0.3.0 with a bunch of useful zip functions.

Friday Aug 17, 2018

Open Sourcing Validated

Today we are open sourcing Validated, a tiny functional Swift library for handling multiple errors: functionality that you don't get from throwing functions and the Result type.

Thursday Aug 16, 2018

Solutions to Exercises: Zip Part 3

Today we solve the exercises to the third and final part of our introductory series on zip.

Wednesday Aug 15, 2018

Solutions to Exercises: Zip Part 2

Today we solve the exercises to the second part of our introductory series on zip.

Tuesday Aug 14, 2018

Solutions to Exercises: Zip Part 1

Today we solve the exercises to the first part of our introductory series on zip.

Monday Aug 6, 2018

Announcing Student Discounts

Get 50% off your Point-Free subscription with proof of enrollment at a university or coding school.

Monday Jul 30, 2018

Celebrating 6 Months

This week marks 6 months since our launch, and we’re making one of our most popular episodes free to the public!

Monday Jul 2, 2018

Conditional Coding

What happens when we combine Swift's conditional conformance with codability?

Monday Jun 25, 2018

Open Sourcing NonEmpty

Today we are open sourcing NonEmpty, a Swift library for modeling non-empty collection types. This small library can help make your code safer and more expressive with very little work.

Monday Jun 18, 2018

Tagged Seconds and Milliseconds

Let's create a type-safe interface for dealing with seconds and milliseconds in our programs. We'll use the `Tagged` type, which allows us to construct all new types in a lightweight way.

Wednesday May 30, 2018

Styling with Functions: Free for Everyone!

We are making one of our early episodes, “UIKit Styling with Functions”, free to everyone today! It’s a seminal episode that sets the foundation for some later work in the Point-Free series.

Tuesday May 15, 2018

Overture: Now with Functional Setters

Announcing Overture 0.2.0! This release is all about setters: functions that allow us to build complex transformations out of smaller units.

Monday May 7, 2018

Solutions to Exercises: Contravariance

This week we solve the exercises from our episode on contravariance, because there were _a lot_ of them!

Monday Apr 23, 2018

Case Study: Algebraic Data Types

Let’s look at a real world use for algebraic data types. We will refactor a data type that is used in the code on this very site so that the invalid states are unrepresentable by the compiler.

Monday Apr 23, 2018

Announcing Point-Free Pointers!

Today we are excited to announcement launch of Point-Free Pointers, a blog to supplement our video series for all the content we couldn’t fit in. Expect to find regularly postings here that dive even deeper into functional programming, showing real world use cases and more!