Skip to content

Instantly share code, notes, and snippets.

@hooman
Last active August 29, 2015 14:04
Show Gist options
  • Save hooman/5517a5bf9c3b471196c3 to your computer and use it in GitHub Desktop.
Save hooman/5517a5bf9c3b471196c3 to your computer and use it in GitHub Desktop.
Lazy Swift: Double Math Example
// Playground - noun: a place where people can play
/*
I was working on various ways to implement lazy behavior in Swift.
I am sharing this simple example for community feedback and to see
if we can come up with some easy and nice looking ways to integrate
lazy behavior in our daily code.
Apple Developer Forums discussion is here:
https://devforums.apple.com/message/1005900#1005900
*/
typealias LazyDouble = ()->Double
func $<T>(expression: @autoclosure ()->T) -> ()->T { return expression }
func $<T>(expression: @autoclosure ()->[T]) -> ()->[T] { return expression }
func $<K,V>(expression: @autoclosure ()->[K:V]) -> ()->[K:V] { return expression }
func +(lhs:LazyDouble, rhs:LazyDouble)->LazyDouble { return { lhs() + rhs() } }
func -(lhs:LazyDouble, rhs:LazyDouble)->LazyDouble { return { lhs() - rhs() } }
func *(lhs:LazyDouble, rhs:LazyDouble)->LazyDouble { return { lhs() * rhs() } }
func /(lhs:LazyDouble, rhs:LazyDouble)->LazyDouble { return { lhs() / rhs() } }
func %(lhs:LazyDouble, rhs:LazyDouble)->LazyDouble { return { lhs() % rhs() } }
prefix func -( rhs:LazyDouble ) ->LazyDouble { return { -rhs() } }
prefix func +( rhs:LazyDouble ) ->LazyDouble { return { rhs() } }
func +(lhs:Double, rhs:LazyDouble)->LazyDouble { return { lhs + rhs() } }
func -(lhs:Double, rhs:LazyDouble)->LazyDouble { return { lhs - rhs() } }
func *(lhs:Double, rhs:LazyDouble)->LazyDouble { return { lhs * rhs() } }
func /(lhs:Double, rhs:LazyDouble)->LazyDouble { return { lhs / rhs() } }
func %(lhs:Double, rhs:LazyDouble)->LazyDouble { return { lhs % rhs() } }
func +(lhs:LazyDouble, rhs:Double)->LazyDouble { return { lhs() + rhs } }
func -(lhs:LazyDouble, rhs:Double)->LazyDouble { return { lhs() - rhs } }
func *(lhs:LazyDouble, rhs:Double)->LazyDouble { return { lhs() * rhs } }
func /(lhs:LazyDouble, rhs:Double)->LazyDouble { return { lhs() / rhs } }
func %(lhs:LazyDouble, rhs:Double)->LazyDouble { return { lhs() % rhs } }
func +(lhs:Double, rhs:Double)->LazyDouble { return { lhs + rhs } }
func -(lhs:Double, rhs:Double)->LazyDouble { return { lhs - rhs } }
func *(lhs:Double, rhs:Double)->LazyDouble { return { lhs * rhs } }
func /(lhs:Double, rhs:Double)->LazyDouble { return { lhs / rhs } }
func %(lhs:Double, rhs:Double)->LazyDouble { return { lhs % rhs } }
func ==(lhs: LazyDouble, rhs: LazyDouble)->Bool { return lhs() == rhs() }
func ==(lhs: Double, rhs: LazyDouble)->Bool { return lhs == rhs() }
func ==(lhs: LazyDouble, rhs: Double)->Bool { return lhs() == rhs }
func +=(inout lhs:LazyDouble, rhs:LazyDouble) { lhs = { lhs() + rhs() } }
func -=(inout lhs:LazyDouble, rhs:LazyDouble) { lhs = { lhs() - rhs() } }
func *=(inout lhs:LazyDouble, rhs:LazyDouble) { lhs = { lhs() * rhs() } }
func /=(inout lhs:LazyDouble, rhs:LazyDouble) { lhs = { lhs() / rhs() } }
func %=(inout lhs:LazyDouble, rhs:LazyDouble) { lhs = { lhs() % rhs() } }
func +=(inout lhs:LazyDouble, rhs:Double) { lhs = { lhs() + rhs } }
func -=(inout lhs:LazyDouble, rhs:Double) { lhs = { lhs() - rhs } }
func *=(inout lhs:LazyDouble, rhs:Double) { lhs = { lhs() * rhs } }
func /=(inout lhs:LazyDouble, rhs:Double) { lhs = { lhs() / rhs } }
func %=(inout lhs:LazyDouble, rhs:Double) { lhs = { lhs() % rhs } }
func +=(inout lhs:Double, rhs:LazyDouble) { lhs = lhs + rhs() }
func -=(inout lhs:Double, rhs:LazyDouble) { lhs = lhs - rhs() }
func *=(inout lhs:Double, rhs:LazyDouble) { lhs = lhs * rhs() }
func /=(inout lhs:Double, rhs:LazyDouble) { lhs = lhs / rhs() }
func %=(inout lhs:Double, rhs:LazyDouble) { lhs = lhs % rhs() }
/*
The simple idea is: you declare lazy Double variables as LazyDouble and you
may need $(...) wrapper for cases where compiler can't handle, but many
basic expressions will work with the overloaded operators that I have
defined. You force evaluation by calling the variable with () suffix to
evaluate the function.
Another neat trick is that you can even make these lazy evaluations
parametric by enclosing a Double variable in curly brackets, e.g.: {n}
This make it a closure that references n and returns its current value.
See below:
*/
var x:LazyDouble, y:LazyDouble, z:LazyDouble
var n:Double
x = $(17.5)
y = 5 + 17
z = {n} * x + 16 + y * 3
n = 1
z() // 99.5
n = 4
z() // 152.0
@hooman
Copy link
Author

hooman commented Jan 25, 2015

Updated for compatibility with Xcode 6.0/6.1/6.2

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment