Last active
August 29, 2015 14:04
-
-
Save hooman/5517a5bf9c3b471196c3 to your computer and use it in GitHub Desktop.
Lazy Swift: Double Math Example
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Updated for compatibility with Xcode 6.0/6.1/6.2