Skip to content
"a general relationship, principle, or rule stated, often as an equation, in the form of symbols"
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Type Name Latest commit message Commit time
Failed to load latest commit information.

Carthage compatible Swift 3.0 ß5 Platforms iOS

Note: The lib is currently in flux, so I would advise against using it.


formulae in a nutshell is able to generate observables (Property<T> and MutableProperty<T>) from a string. It does so in two steps:

  1. Generates a reverse polish notation representation from an input string via Dijkstra's [Shunting-yard algorithm] ( Something like 5 + x, in our intermediate representation, would look like this: [.constant(5), .variable("x"), .mathSymbol(.mathOperator(.plus)]
  2. It then transform the .variables into actual observable properties. Internally, it uses memoization to achieve this, since it needs to cache each newly created property and use it when an operation is about to be used. If it didn't cache each property, it would be impossible to chain and create dependencies between them (for example with y = x + 5 the variable y depends on x)

This approaches opens the door to dynamic UI's that rely in mathematical formulas in a simple and expressive way.


Imagine a scenario where we have one slider and a label that represents the sum of 10 plus the slider's value:

let y = "x + 10"
  • x is what we would like to change with our slider.
  • y is what we would like to observe and eventually update the label with.

It's important to notice that y is a read only property (Property<T>) while x is read/write (MutableProperty<T>). The first step is to create a formula (a map between a variable and its equation):

let formula = ["x": "x", "y": "x + 10"])

It needs "x": "x", in order for formulae internal parser to understand that this is a readWrite observable. The second and final step is to create the observables:

let observables = createObservables(withFormula: formula)

  case .some(.readWrite(let propertyX)) = observables["x"],
  case .some(.readOnly(let propertyY)) = observables["y"]
else {

The output will be a chain of properties that respect what was described: y = x + 10.

// propertyY.value == 10 ( 0 + 10 )

propertyX.value = 1 // propertyY.value == 11 ( 1 + 10 )
propertyX.value = 2 // propertyY.value == 12 ( 2 + 10 )

Supported Operators

  • +
  • -
  • *
  • /
  • ^

You can also use parenthesis: x * ( 2 + 3 )


formulae is licensed under the MIT License, Version 2.0. View the license file

Copyright (c) 2016 MailOnline

You can’t perform that action at this time.