A blog exploring functional programming and Swift.

The Composable Architecture and SwiftUI Alerts

Tuesday Jun 30, 2020

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

Because the Composable Architecture demands that all data flow through the application in a single direction, we cannot leverage SwiftUI’s two-way bindings directly because they can make changes to state without going through a reducer. This means we can’t use the standard API to display alerts and sheets without manually deriving these bindings.

However, the library now comes with two new types, AlertState and ActionSheetState, which can be used in your application to control the presentation, dismissal, and logic of alerts and action sheets.

For example, suppose you have a delete button that when tapped it will show an alert asking the user to confirm their deletion. You can model the actions of tapping the delete button, confirming the deletion, as well as canceling the deletion, in your domain’s action enum:

enum AppAction: Equatable {
  case alertCancelTapped
  case alertConfirmTapped
  case deleteButtonTapped

  // Your other actions
}

And you can model the state for showing the alert in your domain’s state, which can start at nil to represent “dismissed”:

struct AppState: Equatable {
  var alert: AlertState<AppAction>?

  // Your other state
}

Then, in your reducer you can construct an AlertState value to represent the alert you want to show the user:

let appReducer = Reducer<AppState, AppAction, AppEnvironment> { state, action, environment in
  switch action
    case .deleteButtonTapped:
      state.alert = AlertState(
        title: "Delete",
        message: "Are you sure you want to delete this? It cannot be undone.",
        primaryButton: .default("Confirm", send: .alertConfirmTapped),
        secondaryButton: .cancel()
      )
      return .none

    case .alertCancelTapped:
      state.alert = nil
      return .none

    case .alertConfirmTapped:
      state.alert = nil
      // Do deletion logic...
  }
}

And then, in your view you can use the .alert(_:dismiss:) method on View in order to present the alert in a way that works best with the Composable Architecture:

Button("Delete") { viewStore.send(.deleteTapped) }
  .alert(
    self.store.scope(state: \.alert),
    dismiss: .alertCancelTapped
  )

This makes your reducer in complete control of when the alert is shown or dismissed, and makes it so that any choice made in the alert is automatically fed back into the reducer so that you can handle its logic.

Even better, you can instantly write tests that your alert behavior works as expected:

let store = TestStore(
  initialState: AppState(),
  reducer: appReducer,
  environment: .mock
)

store.assert(
  .send(.deleteTapped) {
    $0.alert = AlertState(
      title: "Delete",
      message: "Are you sure you want to delete this? It cannot be undone.",
      primaryButton: .default("Confirm", send: .alertConfirmTapped),
      secondaryButton: .cancel()
    )
  },
  .send(.deleteTapped) {
    $0.alert = nil
    // Also verify that delete logic executed correctly
  }
)

Clean up your alert and action sheet logic today

We’ve just released version version 0.6.0 of the Composable Architecture, so you can start using these new helpers immediately. Let us know what you think!


Core Motion support in the Composable Architecture

Monday Jun 22, 2020

Just over a month a month ago we released ComposableCoreLocation, our first mini-library for the Composable Architecture, which made it easy to integrate with Core Location. We teased more support libraries coming soon, so today, to pass the time in the morning before the WWDC keynote, we’re excited to release ComposableCoreMotion, which makes it easy to use Core Motion in the Composable Architecture.

ComposableCoreMotion is a wrapper around Core Motion’s CMMotionManager that exposes its functionality through effects and actions, making it easy to use with the Composable Architecture, and easy to test.

To use in your application, you can add an action to your feature’s domain that represents the type of motion data you are interested in receiving. For example, if you only want motion updates, then you can add the following action:

import ComposableCoreMotion

enum FeatureAction {
  case motionUpdate(Result<DeviceMotion, NSError>)

  // Your feature's other actions:
  ...
}

This action will be sent every time the motion manager receives new device motion data.

Next, add a MotionManager type, which is a wrapper around a CMMotionManager that this library provides, to your feature’s environment of dependencies:

struct FeatureEnvironment {
  var motionManager: MotionManager

  // Your feature's other dependencies:
  ...
}

Then, create a motion manager by returning an effect from our reducer. You can either do this when your feature starts up, such as when onAppear is invoked, or you can do it when a user action occurs, such as when the user taps a button.

As an example, say we want to create a motion manager and start listening for motion updates when a “Record” button is tapped. Then we can can do both of those things by executing two effects, one after the other:

let featureReducer = Reducer<FeatureState, FeatureAction, FeatureEnvironment> {
  state, action, environment in

  // A unique identifier for our location manager, just in case we want to use
  // more than one in our application.
  struct MotionManagerId: Hashable {}

  switch action {
  case .recordingButtonTapped:
    return .concatenate(
      environment.motionManager
        .create(id: MotionManagerId())
        .fireAndForget(),

      environment.motionManager
        .startDeviceMotionUpdates(id: MotionManagerId(), using: .xArbitraryZVertical, to: .main)
        .mapError { $0 as NSError }
        .catchToEffect()
        .map(AppAction.motionUpdate)
    )

  ...
  }
}

After those effects are executed you will get a steady stream of device motion updates sent to the .motionUpdate action, which you can handle in the reducer. For example, to compute how much the device is moving up and down we can take the dot product of the device’s gravity vector with the device’s acceleration vector, and we could store that in the feature’s state:

case let .motionUpdate(.success(deviceMotion)):
   state.zs.append(
     motion.gravity.x * motion.userAcceleration.x
       + motion.gravity.y * motion.userAcceleration.y
       + motion.gravity.z * motion.userAcceleration.z
   )

case let .motionUpdate(.failure(error)):
  // Do something with the motion update failure, like show an alert.

And then later, if you want to stop receiving motion updates, such as when a “Stop” button is tapped, we can execute an effect to stop the motion manager, and even fully destroy it if we don’t need the manager anymore:

case .stopButtonTapped:
  return .concatenate(
    environment.motionManager
      .stopDeviceMotionUpdates(id: MotionManagerId())
      .fireAndForget(),

    environment.motionManager
      .destroy(id: MotionManagerId())
      .fireAndForget()
  )

That is enough to implement a basic application that interacts with Core Motion.

But the true power of building your application and interfacing with Core Motion this way is the ability to instantly test how your application behaves with Core Motion. We start by creating a TestStore whose environment contains a .mock version of the MotionManager. The .mock function allows you to create a fully controlled version of the motion manager that does not deal with a real CMMotionManager at all. Instead, you override whichever endpoints your feature needs to supply deterministic functionality.

For example, let’s test that we properly start the motion manager when we tap the record button, and that we compute the z-motion correctly, and further that we stop the motion manager when we tap the stop button. We can construct a TestStore with a mock motion manager that keeps track of when the manager is created and destroyed, and further we can even substitute in a subject that we control for device motion updates. This allows us to send any data we want to for the device motion.

func testFeature() {
  let motionSubject = PassthroughSubject<DeviceMotion, Error>()
  var motionManagerIsLive = false

  let store = TestStore(
    initialState: .init(),
    reducer: appReducer,
    environment: .init(
      motionManager: .mock(
        create: { _ in .fireAndForget { motionManagerIsLive = true } },
        destroy: { _ in .fireAndForget { motionManagerIsLive = false } },
        startDeviceMotionUpdates: { _, _, _ in motionSubject.eraseToEffect() },
        stopDeviceMotionUpdates: { _ in
          .fireAndForget { motionSubject.send(completion: .finished) }
        }
      )
    )
  )

  ...
}

We can then make an assertion on our store that plays a basic user script. We can simulate the situation in which a user taps the record button, then some device motion data is received, and finally the user taps the stop button. During that script of user actions we expect the motion manager to be started, then for some z-motion values to be accumulated, and finally for the motion manager to be stopped:

let deviceMotion = DeviceMotion(
  attitude: .init(quaternion: .init(x: 1, y: 0, z: 0, w: 0)),
  gravity: CMAcceleration(x: 1, y: 2, z: 3),
  heading: 0,
  magneticField: .init(field: .init(x: 0, y: 0, z: 0), accuracy: .high),
  rotationRate: .init(x: 0, y: 0, z: 0),
  timestamp: 0,
  userAcceleration: CMAcceleration(x: 4, y: 5, z: 6)
)

store.assert(
  .send(.recordingButtonTapped) {
    XCTAssertEqual(motionManagerIsLive, true)
  },
  .do { motionSubject.send(deviceMotion) },
  .receive(.motionUpdate(.success(deviceMotion))) {
    $0.zs = [32]
  },
  .send(.stopButtonTapped) {
    XCTAssertEqual(motionManagerIsLive, false)
  }
)

This is only the tip of the iceberg. We can access any part of the CMMotionManager API in this way, and instantly unlock testability with how the motion functionality integrates with our core application logic. This can be incredibly powerful, and is typically not the kind of thing one can test easily.

To see a more advanced usage of ComposableCoreMotion, check out our demo application, which uses a MotionManager to show a sinusoidal curve of a device’s motion, and tracks the direction a device is facing, reflecting this in the background color of the interface. It is also fully tested.

Try it out today

We’re excited to release our second support library for the Composable Architecture, and hope it will simplify and strengthen your application’s interaction with Core Motion. Get access to it today by updating to version 0.5.0.

Keep an eye out for future support libraries!


Open Sourcing CombineSchedulers

Monday Jun 15, 2020

We are excited to announce the 0.1.0 release of CombineSchedulers, a library that introduces a few schedulers that makes working with Combine more testable and more versatile.

Motivation

The Combine framework provides the Scheduler protocol, which is a powerful abstraction for describing how and when units of work are executed. It unifies many disparate ways of executing work, such as DispatchQueue, RunLoop and OperationQueue.

However, the Combine framework is still quite new and missing some fundamental pieces needed to make asynchronous Combine code more testable. This library intends to fill those gaps with some handy schedulers and publishers, including AnyScheduler, TestScheduler, UIScheduler, ImmediateScheduler, and Publishers.Timer.

AnyScheduler

The AnyScheduler provides a type-erasing wrapper for the Scheduler protocol, which can be useful for being generic over many types of schedulers without needing to actually introduce a generic to your code. The Combine framework ships with many type-erasing wrappers, such as AnySubscriber, AnyPublisher and AnyCancellable, yet for some reason does not ship with AnyScheduler.

This type is useful for times that you want to be able to customize the scheduler used in some code from the outside, but you don’t want to introduce a generic to make it customizable. For example, suppose you have an ObservableObject view model that performs an API request when a method is called:

class EpisodeViewModel: ObservableObject {
  @Published var episode: Episode?
  private var cancellables: Set<AnyCancellable> = []

  let apiClient: ApiClient

  init(apiClient: ApiClient) {
    self.apiClient = apiClient
  }

  func reloadButtonTapped() {
    self.apiClient.fetchEpisode()
      .receive(on: DispatchQueue.main)
      .sink { self.episode = $0 }
      .store(in: &self.cancellables)
  }
}

Notice that we are using DispatchQueue.main in the reloadButtonTapped method because the fetchEpisode endpoint most likely delivers its output on a background thread (as is the case with URLSession).

This code seems innocent enough, but the presence of .receive(on: DispatchQueue.main) makes this code harder to test since you have to use XCTest expectations to explicitly wait a small amount of time for the queue to execute. This can lead to flakiness in tests and make test suites take longer to execute than necessary.

One way to fix this testing problem is to use an “immediate” scheduler instead of DispatchQueue.main, which will cause fetchEpisode to deliver its output as soon as possible with no thread hops. In order to allow for this we would need to inject a scheduler into our view model so that we can control it from the outside:

class EpisodeViewModel<S: Scheduler>: ObservableObject {
  @Published var episode: Episode?
  private var cancellables: Set<AnyCancellable> = []

  let apiClient: ApiClient
  let scheduler: S

  init(apiClient: ApiClient, scheduler: S) {
    self.apiClient = apiClient
    self.scheduler = scheduler
  }

  func reloadButtonTapped() {
    self.apiClient.fetchEpisode()
      .receive(on: self.scheduler)
      .sink { self.episode = $0 }
      .store(in: &self.cancellables)
  }
}

Now we can initialize this view model in production by using DispatchQueue.main and we can initialize it in tests using DispatchQueue.immediateScheduler. Sounds like a win!

However, introducing this generic to our view model is quite heavyweight as it is loudly announcing to the outside world that this type uses a scheduler, and worse it will end up infecting any code that touches this view model that also wants to be testable. For example, any view that uses this view model will need to introduce a generic if it wants to also be able to control the scheduler, which would be useful if we wanted to write snapshot tests.

Instead of introducing a generic to allow for substituting in different schedulers we can use AnyScheduler. It allows us to be somewhat generic in the scheduler, but without actually introducing a generic.

Instead of holding a generic scheduler in our view model we can say that we only want a scheduler whose associated types match that of DispatchQueue:

class EpisodeViewModel: ObservableObject {
  @Published var episode: Episode?
  private var cancellables: Set<AnyCancellable> = []

  let apiClient: ApiClient
  let scheduler: AnySchedulerOf<DispatchQueue>

  init(apiClient: ApiClient, scheduler: AnySchedulerOf<DispatchQueue>) {
    self.apiClient = apiClient
    self.scheduler = scheduler
  }

  func reloadButtonTapped() {
    self.apiClient.fetchEpisode()
      .receive(on: self.scheduler)
      .sink { self.episode = $0 }
      .store(in: &self.cancellables)
  }
}

Then, in production we can create a view model that uses a live DispatchQueue, but we just have to first erase its type:

let viewModel = EpisodeViewModel(
  apiClient: ...,
  scheduler: DispatchQueue.main.eraseToAnyScheduler()
)

And similarly in tests we can use an immediate scheduler as long as we erase its type:

let viewModel = EpisodeViewModel(
  apiClient: ...,
  scheduler: DispatchQueue.immediateScheduler.eraseToAnyScheduler()
)

So, in general, AnyScheduler is great for allowing one to control what scheduler is used in classes, functions, etc. without needing to introduce a generic, which can help simplify the code and reduce implementation details from leaking out.

TestScheduler

A scheduler whose current time and execution can be controlled in a deterministic manner. This scheduler is useful for testing how the flow of time effects publishers that use asynchronous operators, such as debounce, throttle, delay, timeout, receive(on:), subscribe(on:) and more.

For example, consider the following race operator that runs two futures in parallel, but only emits the first one that completes:

func race<Output, Failure: Error>(
  _ first: Future<Output, Failure>,
  _ second: Future<Output, Failure>
) -> AnyPublisher<Output, Failure> {
  first
    .merge(with: second)
    .prefix(1)
    .eraseToAnyPublisher()
}

Although this publisher is quite simple we may still want to write some tests for it.

To do this we can create a test scheduler and create two futures, one that emits after a second and one that emits after two seconds:

let scheduler = DispatchQueue.testScheduler

let first = Future<Int, Never> { callback in
  scheduler.schedule(after: scheduler.now.advanced(by: 1)) { callback(.success(1)) }
}
let second = Future<Int, Never> { callback in
  scheduler.schedule(after: scheduler.now.advanced(by: 2)) { callback(.success(2)) }
}

And then we can race these futures and collect their emissions into an array:

var output: [Int] = []
let cancellable = race(first, second).sink { output.append($0) }

And then we can deterministically move time forward in the scheduler to see how the publisher emits. We can start by moving time forward by one second:

scheduler.advance(by: 1)
XCTAssertEqual(output, [1])

This proves that we get the first emission from the publisher since one second of time has passed. If we further advance by one more second we can prove that we do not get anymore emissions:

scheduler.advance(by: 1)
XCTAssertEqual(output, [1])

This is a very simple example of how to control the flow of time with the test scheduler, but this technique can be used to test any publisher that involves Combine’s asynchronous operations.

UIScheduler

A scheduler that executes its work on the main queue as soon as possible.

If UIScheduler.shared.schedule is invoked from the main thread then the unit of work will be performed immediately. This is in contrast to DispatchQueue.main.schedule, which will incur a thread hop before executing since it uses DispatchQueue.main.async under the hood.

This scheduler can be useful for situations where you need work executed as quickly as possible on the main thread, and for which a thread hop would be problematic, such as when performing animations.

ImmediateScheduler

The Combine framework comes with an ImmediateScheduler type of its own, but it defines all new types for the associated types of SchedulerTimeType and SchedulerOptions. This means you cannot easily swap between a live DispatchQueue and an “immediate” DispatchQueue that executes work synchronously. The only way to do that would be to introduce generics to any code making use of that scheduler, which can become unwieldy.

So, instead, this library’s ImmediateScheduler uses the same associated types as an existing scheduler, which means you can use DispatchQueue.immediateScheduler to have a scheduler that looks like a dispatch queue but executes its work immediately. Similarly you can construct RunLoop.immediateScheduler and OperationQueue.immediateScheduler.

This scheduler is useful for writing tests against publishers that use asynchrony operators, such as receive(on:), subscribe(on:) and others, because it forces the publisher to emit immediately rather than needing to wait for thread hops or delays using XCTestExpectation.

This scheduler is different from TestScheduler in that you cannot explicitly control how time flows through your publisher, but rather you are instantly collapsing time into a single point.

As a basic example, suppose you have a view model that loads some data after waiting for 10 seconds from when a button is tapped:

class HomeViewModel: ObservableObject {
  @Published var episodes: [Episode]?
  var cancellables: Set<AnyCancellable> = []

  let apiClient: ApiClient

  init(apiClient: ApiClient) {
    self.apiClient = apiClient
  }

  func reloadButtonTapped() {
    Just(())
      .delay(for: .seconds(10), scheduler: DispachQueue.main)
      .flatMap { apiClient.fetchEpisodes() }
      .sink { self.episodes = $0 }
      .store(in: &self.cancellables)
  }
}

In order to test this code you would literally need to wait 10 seconds for the publisher to emit:

func testViewModel() {
  let viewModel(apiClient: .mock)

  var output: [Episode] = []
  viewModel.$episodes
    .sink { output.append($0) }
    .store(in: &self.cancellables)

  viewModel.reloadButtonTapped()

  _ = XCTWaiter.wait(for: [XCTestExpectation()], timeout: 10)

  XCTAssert(output, [Episode(id: 42)])
}

Alternatively, we can explicitly pass a scheduler into the view model initializer so that it can be controller from the outside:

class HomeViewModel: ObservableObject {
  @Published var episodes: [Episode]?
  var cancellables: Set<AnyCancellable> = []

  let apiClient: ApiClient
  let scheduler: AnySchedulerOf<DispatchQueue>

  init(apiClient: ApiClient, scheduler: AnySchedulerOf<DispatchQueue>) {
    self.apiClient = apiClient
    self.scheduler = scheduler
  }

  func reloadButtonTapped() {
    Just(())
      .delay(for: .seconds(10), scheduler: self.scheduler)
      .flatMap { self.apiClient.fetchEpisodes() }
      .sink { self.episodes = $0 }
      .store(in: &self.cancellables)
  }
}

And then in tests use an immediate scheduler:

func testViewModel() {
  let viewModel(
    apiClient: .mock,
    scheduler: DispatchQueue.immediateScheduler.eraseToAnyScheduler()
  )

  var output: [Episode] = []
  viewModel.$episodes
    .sink { output.append($0) }
    .store(in: &self.cancellables)

  viewModel.reloadButtonTapped()

  // No more waiting...

  XCTAssert(output, [Episode(id: 42)])
}

Publishers.Timer

A publisher that emits a scheduler’s current time on a repeating interval.

This publisher is an alternative to Foundation’s Timer.publisher, with its primary difference being that it allows you to use any scheduler for the timer, not just RunLoop. This is useful because the RunLoop scheduler is not testable in the sense that if you want to write tests against a publisher that makes use of Timer.publisher you must explicitly wait for time to pass in order to get emissions. This is likely to lead to fragile tests and greatly bloat the time your tests take to execute.

It can be used much like Foundation’s timer, except you specify a scheduler rather than a run loop:

Publishers.Timer(every: .seconds(1), scheduler: DispatchQueue.main)
  .autoconnect()
  .sink { print("Timer", $0) }

Alternatively you can call the timerPublisher method on a scheduler in order to derive a repeating timer on that scheduler:

DispatchQueue.main.timerPublisher(every: .seconds(1))
  .autoconnect()
  .sink { print("Timer", $0) }

But the best part of this timer is that you can use it with TestScheduler so that any Combine code you write involving timers becomes more testable. This shows how we can easily simulate the idea of moving time forward 1,000 seconds in a timer:

let scheduler = DispatchQueue.testScheduler
var output: [Int] = []

Publishers.Timer(every: 1, scheduler: scheduler)
  .autoconnect()
  .sink { _ in output.append(output.count) }
  .store(in: &self.cancellables)

XCTAssertEqual(output, [])

scheduler.advance(by: 1)
XCTAssertEqual(output, [0])

scheduler.advance(by: 1)
XCTAssertEqual(output, [0, 1])

scheduler.advance(by: 1_000)
XCTAssertEqual(output, Array(0...1_001))

Learn More

The design of this library was explored in the following Point-Free episodes:

Try It Out Today!

The official 0.1.0 release of CombineSchedulers is on GitHub now, and we have more improvements and refinements coming soon. We hope that CombineSchedulers will help you test your application’s Combine code.


Older blog posts

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!