Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Techniques to write DSLs in Swift
Search
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
Luis Solano
June 06, 2014
Programming
1.5k
7
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Techniques to write DSLs in Swift
Luis Solano
June 06, 2014
More Decks by Luis Solano
See All by Luis Solano
How I Spent All My Savings Reinventing Programming
luisobo
0
280
Consuming Web APIs, the TDD way
luisobo
6
380
Techniques to write DSLs in Objective-C
luisobo
9
930
Other Decks in Programming
See All in Programming
メソッドのジェネリクスでGoの夢は広がるか? / Kyoto.go #65
utgwkk
3
850
キャリア迷子上等 ─ "ない道"は自分で作ればいい
16bitidol
3
2.2k
エンジニアと一緒にテストコードの設計と実装を改善した話
mototakatsu
0
210
ローカルLLMを使ってB2Bサービスを作っていての学び
yaotti
0
200
Honoでのサプライチェーン侵害対策 〜 3つのライブラリに学ぶ
yusukebe
6
1.4k
セキュリティの専門家じゃなくてもできる。「セキュリティ意識」をアップデートして サプライチェーン攻撃への耐性を高めよう。
tk3fftk
5
890
Inside Stream API
skrb
1
740
スマートグラスで並列バイブコーディング
hyshu
0
180
Spec Driven Development | AI Summit Lisbon
danielsogl
PRO
0
200
CSC307 Lecture 17
javiergs
PRO
0
320
Observability in Practice:Grafana 與 Edge Device SRE 的那些事
blueswen
0
170
Make SRE Operations Easier with Azure SRE Agent
kkamegawa
0
6.9k
Featured
See All Featured
Chasing Engaging Ingredients in Design
codingconduct
0
220
Exploring the relationship between traditional SERPs and Gen AI search
raygrieselhuber
PRO
2
4k
Unlocking the hidden potential of vector embeddings in international SEO
frankvandijk
0
850
Six Lessons from altMBA
skipperchong
29
4.3k
So, you think you're a good person
axbom
PRO
2
2.1k
Docker and Python
trallard
47
3.9k
Leo the Paperboy
mayatellez
7
1.8k
Principles of Awesome APIs and How to Build Them.
keavy
128
18k
Balancing Empowerment & Direction
lara
6
1.2k
From π to Pie charts
rasagy
0
210
How to Get Subject Matter Experts Bought In and Actively Contributing to SEO & PR Initiatives.
livdayseo
0
140
jQuery: Nuts, Bolts and Bling
dougneiner
66
8.5k
Transcript
“Clean code reads like well-written prose” – Grady Booch
asjdañlksjdlaksjdñlak asjdañlksjdla asjdañlksjdlaksjdñlak asjdañlksjdla asjdañlksjdlaksjdñlak asjdañlksjdla asjdañlksjdlaksjdñlak asjdañlksjdla asjdañlksjdlaksjdñlak asjdañlksjdla
asjdañlksjdlaksjdñlak asjdañlksjdla asjdañlksjdlaksjdñlak asjdañlksjdla asjdañlksjdlaksjdñlak asjdañlksjdla
asjdañlksjdlaksjdñlak asjdañlksjdla asjdañlksjdlaksjdñlak asjdañlksjdla asjdañlksjdlaksjdñlak asjdañlksjdla asjdañlksjdlaksjdñlak asjdañlksjdla asjdañlksjdlaksjdñlak asjdañlksjdla
asjdañlksjdlaksjdñlak asjdañlksjdla asjdañlksjdlaksjdñlak asjdañlksjdla asjdañlksjdlaksjdñlak asjdañlksjdla asjdañlksjdlaksjdñlak asjdañlksjdla asjdañlksjdlaksjdñlak asjdañlksjdla asjdañlksjdlaksjdñlak asjdañlksjdla
@implementation Subscription - (id)init { self = [super init]; if
(!self) return nil; self.state = @"pending"; } - (void)activateWithCode:(NSString *)activationCode { if ([self.state isEqualToString:@"pending"] && [self.code isEqualToString:activationCode]) { self.state = @"active"; } } - (void)suspend { if ([self.state isEqualToString:@"active"]) { [self stopBilling]; } } @end IMPLEMENTATION
LSStateMachine *sm = [[LSStateMachine alloc] init]; LSState *s1 = [[LSState
alloc] initWithName:@"pending"]; LSState *s2 = [[LSState alloc] initWithName:@"active"]; [sm addState:s1]; [sm addState:s2]; LSEvent *e1 = [[LSEvent alloc] initWithName:@"activate"]; LSTransition *t1 = [[LSTransition alloc] initWithEvent:e1 from:s1 to:s2]; [sm addTransition:t1]; ABSTRACTION
TECHNIQUES TO WRITE DSLs IN OBJECTIVE-C
TECHNIQUES TO WRITE DSLs IN SWIFT
LUIS SOLANO @luisobo
DOMAIN-SPECIFIC LANGUAGE
LANGUAGE PROGRAMMING
SPECIFIC CONSTRAINT
TO A CERTAIN DOMAIN CERTAIN TYPE OF PROBLEM
LSStateMachine *sm = [[LSStateMachine alloc] init]; LSState *s1 = [[LSState
alloc] initWithName:@"pending"]; LSState *s2 = [[LSState alloc] initWithName:@"active"]; [sm addState:s1]; [sm addState:s2]; LSEvent *e1 = [[LSEvent alloc] initWithName:@"activate"]; LSTransition *t1 = [[LSTransition alloc] initWithEvent:e1 from:s1 to:s2]; [sm addTransition:t1]; ABSTRACTION
asjdañlksjdlaksjdñlak asjdañlksjdla asjdañlksjdlaksjdñlak asjdañlksjdla asjdañlksjdlaksjdñlak asjdañlksjdla asjdañlksjdlaksjdñlak asjdañlksjdla asjdañlksjdlaksjdñlak asjdañlksjdla
asjdañlksjdlaksjdñlak asjdañlksjdla asjdañlksjdlaksjdñlak asjdañlksjdla asjdañlksjdlaksjdñlak asjdañlksjdla asjdañlksjdlaksjdñlak asjdañlksjdla asjdañlksjdlaksjdñlak asjdañlksjdla asjdañlksjdlaksjdñlak asjdañlksjdla asjdañlksjdlaksjdñlak asjdañlksjdla
LSStateMachine *sm = [[LSStateMachine alloc] init]; LSState *s1 = [[LSState
alloc] initWithName:@"pending"]; LSState *s2 = [[LSState alloc] initWithName:@"active"]; [sm addState:s1]; [sm addState:s2]; LSEvent *e1 = [[LSEvent alloc] initWithName:@"activate"]; LSTransition *t1 = [[LSTransition alloc] initWithEvent:e1 from:s1 to:s2]; [sm addTransition:t1]; ABSTRACTION
sm.when("activate", transitionFrom: "pending", to: "active") DSL
DSL luisobo/StateMachine
sm.when("activate", transitionFrom: "pending", to: "active") sm.when("suspend", transitionFrom: "active", to: "suspended")
sm.when("unsuspend", transitionFrom: "suspended", to: "active") sm.when("terminate", transitionFrom: "active", to: "terminated") sm.when("terminate", transitionFrom: "suspended", to: "terminated") ! sm.before("terminate") { subscription in subscription.terminatedAt = NSDate.date() } ! sm.before("suspend") { subscription in subscription.stopBilling() } DSL
asjdañlksjdlaksjdñlak asjdañlksjdla asjdañlksjdlaksjdñlak asjdañlksjdla asjdañlksjdlaksjdñlak asjdañlksjdla asjdañlksjdlaksjdñlak asjdañlksjdla asjdañlksjdlaksjdñlak asjdañlksjdla
asjdañlksjdlaksjdñlak asjdañlksjdla asjdañlksjdlaksjdñlak asjdañlksjdla asjdañlksjdlaksjdñlak asjdañlksjdla asjdañlksjdlaksjdñlak asjdañlksjdla asjdañlksjdlaksjdñlak asjdañlksjdla asjdañlksjdlaksjdñlak asjdañlksjdla asjdañlksjdlaksjdñlak asjdañlksjdla
asjdañlksjdlaksjdñlak asjdañlksjdla asjdañlksjdlaksjdñlak asjdañlksjdla asjdañlksjdlaksjdñlak asjdañlksjdla asjdañlksjdlaksjdñlak asjdañlksjdla Semantic model
Domain-specfic language
DECLARATIVE
imperative
imperative is fine
imperative works
my brain
my brain cannot handle imperative programming’s scale
DECLARATIVE
INTERNAL EXTERNAL INTERNAL
DSL? WHY TO
DSL? WHEN TO
DSL? HOW TO
SWIFT METHODS luisobo/StateMachine sm.when("activate", transitionFrom: "pending", to: "active")
LSStateMachine *sm = [[LSStateMachine alloc] init]; LSState *s1 = [[LSState
alloc] initWithName:@"pending"]; LSState *s2 = [[LSState alloc] initWithName:@"active"]; [sm addState:s1]; [sm addState:s2]; LSEvent *e1 = [[LSEvent alloc] initWithName:@"activate"]; LSTransition *t1 = [[LSTransition alloc] initWithEvent:e1 from:s1 to:s2]; [sm addTransition:t1]; SWIFT METHODS luisobo/StateMachine
SWIFT METHODS luisobo/StateMachine sm.when("activate", transitionFrom: "pending", to: "active")
METHOD CHAINING stubRequest("GET", "http://hello.com/"). andReturn(200).withBody("hola"); luisobo/Nocilla
stubRequest("POST", "http://hello.com"). withHeader("Content-Type", "text/plain"). withHeader("X-MY-AWESOME-HEADER", "sisisi"). withBody("Adios!"). andReturn(200). withHeader("Content-Type", "text/plain").
withBody("hola"); METHOD CHAINING luisobo/Nocilla
EXTENSIONS state.should.eq(“active”)
EXTENSIONS extension NSObject { var should:Matcher { return Matcher() }
}
[1, 2, 3] [1: “one”, 2: “two”, 3: “three”] ARRAY
AND DICTIONARY LITERALS
stubRequest("GET", “http://hello.com"). withHeaders([“Content-Type": “text/plain", "X-MY-AWESOME-HEADER" : “YEAH!”]). andReturn(200); luisobo/Nocilla ARRAY
AND DICTIONARY LITERALS
.adjustTemperature(24.5).at(“nine"). USING LITERALS WITH YOUR TYPES
func adjustTemperature(to: Temp) -> Thermostat func at(time: NSDate) -> Thermostat
USING LITERALS WITH YOUR TYPES
protocol FloatLiteralConvertible { ! typealias FloatLiteralType ! class func convertFromFloatLiteral(value:
FloatLiteralType) -> Self ! } USING LITERALS WITH YOUR TYPES
extension Temp: FloatLiteralConvertible { typealias FloatLiteralType = Double class func
convertFromFloatLiteral(value: Double) -> Temp { return Temp(degrees: value) } } USING LITERALS WITH YOUR TYPES
IntegerLiteralConvertible FloatLiteralConvertible StringLiteralConvertible LogicValue StringInterpolationConvertible ArrayLiteralConvertible DictionaryLiteralConvertible USING LITERALS WITH
YOUR TYPES 1 3.5 “foo” if myValue “hello \(value)” [1, 2, 3] [“one”: 1, “two”: 2]
BLOCKS sm.before("terminate") { subscription in subscription.terminatedAt = NSDate.date() } luisobo/StateMachine
BLOCKS FOR CONTEXT User.defineFactory { f in f["foo"] = "bar"
f["password"] = "hunter2" } luisobo/Defactory
SYNTACTIC SUGAR o.com”).with.body(“Hola”).and.return(200) luisobo/Nocilla
OPERATOR OVERLOAD ^= *= * % + - / <<=
||= << || |= <= >>= !== >= ~= | >> < += &&= %= ... -= &% /= && &* &+ &- &/ === == & .. ^ > &= != ~ ! -- ++ - + -- ++
OPERATOR OVERLOAD let s: Speed = 100.meters / 5.seconds
CUSTOM OPERATORS / = - + * % < >
! & | ^ . ~.
CUSTOM OPERATORS operator infix =>> {}
=>>
stubRequest("GET","http://hello.com/") luisobo/Nocilla stubRequest(method:String, url:String)
stubRequest("GET", "http://hello.com/") stubRequest(“GET", regex(“http://.*\.com”)) luisobo/Nocilla stubRequest(method:String, url:AnyObject)
stubRequest("POST", NSObject()); stubRequest(“POST”, []); luisobo/Nocilla stubRequest(method:String, url:AnyObject)
protocol Matchable { func matcher() -> Matcher } ADD PROTOCOL
TO EXISTING CLASS luisobo/Nocilla
extension NSString: Matchable { func matcher() -> Matcher { return
StringMatcher(pattern: self) } } ADD PROTOCOL TO EXISTING CLASS
ADD PROTOCOL TO EXISTING CLASS extension NSRegularExpression: Matchable { func
matcher() -> Matcher { return RegexMatcher(pattern: self) } }
ADD PROTOCOL TO EXISTING CLASS stubRequest("GET", "http://hello.com/") stubRequest(“GET", regex(“http://.*\.com”)) luisobo/Nocilla
stubRequest(method:String, url:Matcheable)
stubRequest("POST", NSObject()]); stubRequest(“POST”,[]]); stubRequest(method:String, url:Matcheable) ADD PROTOCOL TO EXISTING CLASS
luisobo/Nocilla
None
Thin layer on top of an abstraction. Limited expressiveness and
domain focus. Make your code more maintainable Developer happiness Improved communication Fewer bugs! As seen in TV
! ! Domain-specific languages by Martin Fowler brain photo: flickr/_DJ_
redacted font: github/christiannaths Nocilla: github/luisobo StateMachine: github/luisobo Defactory: github/luisobo Kiwi: github/kiwi-bdd metamacros.h github/jspahrsummers THANKS! @luisobo