Skip to content

Instantly share code, notes, and snippets.

@elm4ward
Forked from marcpalmer/dsltest.swift
Last active September 1, 2016 10:47
Show Gist options
  • Save elm4ward/4d5f5a7133eed652dbfbd6292b9878f1 to your computer and use it in GitHub Desktop.
Save elm4ward/4d5f5a7133eed652dbfbd6292b9878f1 to your computer and use it in GitHub Desktop.
Example of using Swift property change observation to bind models to arguments passed to DSL closures
import UIKit
enum GraphicsCommand {
case setColour(colour: UInt32)
case moveTo(x: Float, y: Float)
case lineTo(x: Float, y: Float)
}
class GraphicsDSL {
var commands = [GraphicsCommand]()
var colour: UInt32 = 0xffffff {
didSet {
if oldValue != colour {
commands.append(.setColour(colour: colour))
}
}
}
func moveTo(x: Float, y: Float){
commands.append(.moveTo(x: x, y: y))
}
func lineTo(x: Float, y: Float){
commands.append(.lineTo(x: x, y: y))
}
}
class GraphicsBuilder {
/// Called with a closure that can access a special list of functions and properties
func build(code: (GraphicsDSL) -> ()) -> [GraphicsCommand] {
let dsl = GraphicsDSL()
code(dsl)
return dsl.commands
}
}
let dsl = GraphicsBuilder()
/// This is what it looks like to use it. You can see what you can do in the arg list.
/// It is likely that moving these things to a struct is better. This would in itself be a nice pattern,
/// using structs to define the functionality of a DSL. However we're demonstrating the possibilities
/// of mutable, observable local vars here...
let commands = dsl.build { b in
b.colour = 0xff0000
b.moveTo(x: 50, y: 50)
b.colour = 0x00ff00
b.lineTo(x: 100, y: 100)
b.colour = 0x0000ff
b.lineTo(x: 0, y: 100)
b.colour = 0xff00ff
b.lineTo(x: 50, y: 50)
}
print(commands.count)
for c in commands {
print(c)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment