Fate Programming

Fate is a programming language that targets the V8 JavaScript VM. It is a mostly functional language that provides first-class patterns, invocation guards, list comprehensions, flexible function application, and awesome concurrency.

That’s a lot to take in, so maybe it’s better to just demonstrate. Let’s say you needed to calculate the NOx emissions for an OBD II reporting module. You could do it the obvious way:

def calculateVehicleEmissions(car)
  if car.wheelsInMotion > 2
    car.emissions / 40

But that’s a lot of if statements. Yes, one is too many. It also packs calculations for two different potential states into a single function, which will become more difficult to isolate if you should need to hide the second calculation from government auditors. To correct this, you can break the function up and use a guard on its re-opened version.

def calculateVehicleEmissions(car)

def calculateVehicleEmissions(car) where car.wheelsInMotion <= 2
  car.emissions / 40

That’s better! Now if the EPA come to your place of business, you can simply delete the second function and they’ll be none the wiser! But that where clause is practically like another if statement, and we’ve already established that we don’t like those. So let’s use an in-line pattern instead:

def calculateVehicleEmissions(car)

def calculateVehicleEmissions({ .wheelsInMotion <= 2 } as car)
  car.emissions / 40

Better! But now you have the pattern matching for qualifying cars in a place where it can’t be reused. Let’s clean that up:

def calculateVehicleEmissions(car)

let VehicleUnderTest = ~{ .wheelsInMotion <= 2 }

def calculateVehicleEmissions(VehicleUnderTest as car)
  car.emissions / 40

Done! The problem of vehicle emissions testing is now solved!

A Quick Tour

You’ve seen Functions and Patterns, but there’s more to Fate than that. Let’s take a very quick look at some of those language features.

Branching Statements and Expressions

# Ye Ole 'If' Statement
if myAge > 50
  'should probably retire'
  'good to go'

# Syntactic sugar for 'if not'
unless processFinished
  'process some request'

# Suffix 'if' (can also do unless)
greetWith('hello') if person like Friend

# The 'if let' statement
if let a=getSomeValue(), b=getAnotherValue()
  # as they're not Nothing, do something with those values

# Branching Expressions
let result = 'green' unless turnedOff else 'red'

Iteration And Reducing

# For Loops, with Guards, Else Clauses, and Multiple Ranges
for color in colors where color != 'orange',
    shape in shapes where shape != 'square'
  {color, shape} | "A %color colored %shape" | display
  "No colored shapes were retrieved" | display

# Reduce Statement (Multiple Components)
reduce sum = 0, count = 0
for value in [1, 2, 3, 4, 5, 6, 7]
where value < 4
  let count = count + 1
  let sum = sum + value
let average = sum / count
# Reduce Expression (in a multi-line Lambda)
let sum = (values ->
  reduce result = 0
  for value in values
  select result + value

# For Expression (Lazily evaluated)
let filteredColors = for color in colors where color != 'orange'

# List and Object Comprehensions materializing a For Expression
let result = [
  for color in filteredColors 
  select {color} | 'The color is %color'

let deidentified = {
  for name:value in person
  where name not in ['name', 'address', 'ssn']

Patterns and Destructuring

# Function Composition
from array import sort, reverse
let reverseSort = sort o reverse  # x -> reverse(sort(x))
[9, 15, 35, 2, 17, 6] | reverseSort | print

# Combining Patterns
let Shape = ~{ .type in ['square', 'circle', 'triangle'] },
    Orange = ~{ 'orange' in .colors },
    Large = ~{ .size > 50 }

let LargeOrangeShape = Large && Orange && Shape

# Instead of multiple statements with an 'end', you
# can just use a colon to evaluate a single statement
if shape like LargeOrangeShape: print('bingo!')

# Match against multiple possible Patterns
let matchResult = match shape
  LargeOrangeShape: "Was large and orange"
  Shape: "Was just a shape"
  Person: "Was some person... probably Bill"
  else: "No idea"

# Destructuring Assignment
let person = { name: 'Bill', age: 43 }
let { name, age as yearsOnEarth } = person

let numbers = [1, 2, 3]
let [ first, second, third ] = numbers

Concurrency Expressions

from io import print, timeout

# A basic 'do' expression
let name = do

  {name: await name} | "Hello, %name!" | print

do when [content, _] = http.get("http://www.example.org/")
  content | print

let eventualResult = do
  case name
    print("name resolved first")

  # `_` (wildcard) means the resulting element will be ignored
  case [content, _] = http.get("http://www.example.org/")
    print("http content resolved first")

  case timeout(100)
    print("couldn't get name or http content in 100ms")

# Chained and Awaiting Function calls
let numbers = [100, 150, 400]
  # will eventually print '[ 200, 300, 800 ]'
  numbers | (arr -> [for x in arr select x | timeout])
         :| (arr -> [for x in arr select x * 2])
          | print

Importing To/Exporting From A Module

# Importing into a module
from SomeModule import displayString as display

import SomeModule as aModule
let display = aModule.displayString

# Exporting from a module
export calculateVehicleEmissions as calculate


For source code and releases, see the Fate GitHub Page.

For more information about the language itself, you can read the Fate Programming Guide.

For examples of real code, you can check out the scripts in the project’s Test Directory.

For language support in Visual Studio Code, install the Fate Extension.

For language support in Sublime Text, install the Fate package using Package Control.