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
FunctionBuilderでコンパイラを表現しようとした
Search
yosshi
June 18, 2019
Technology
0
720
FunctionBuilderでコンパイラを表現しようとした
FunctionBuilderでコンパイラを表現しようとしたけど、できなかったしユースケースも違った話
yosshi
June 18, 2019
Tweet
Share
More Decks by yosshi
See All by yosshi
Object Oriented Software Development
yosshi4486
0
94
SwiftでZeplinのダークモード対応ツールを作ったよ
yosshi4486
0
430
Implement side-menu with SwiftUI
yosshi4486
2
630
Other Decks in Technology
See All in Technology
エンジニアの育成を支える爆速フィードバック文化
sansantech
PRO
3
660
滅・サービスクラス🔥 / Destruction Service Class
sinsoku
6
1.5k
飲食店予約台帳を支えるインタラクティブ UI 設計と実装
siropaca
6
1.4k
「海外登壇」という 選択肢を与えるために 〜Gophers EX
logica0419
0
500
High Performance PHP
cmuench
0
140
自動テストの世界に、この5年間で起きたこと
autifyhq
10
7.1k
依存関係があるコンポーネントは Barrel ファイルでまとめよう
azukiazusa1
3
530
Bounded Context: Problem or Solution?
ewolff
1
210
第13回 Data-Centric AI勉強会, 画像認識におけるData-centric AI
ksaito_osx
0
360
Kubernetes x k6 で負荷試験基盤を開発して 負荷試験を民主化した話 / Kubernetes x k6
sansan_randd
2
730
君も受託系GISエンジニアにならないか
sudataka
1
370
Fintech SREの挑戦 PCI DSS対応をスマートにこなすインフラ戦略/Fintech SRE’s Challenge: Smart Infrastructure Strategies for PCI DSS Compliance
maaaato
0
450
Featured
See All Featured
Faster Mobile Websites
deanohume
306
31k
Helping Users Find Their Own Way: Creating Modern Search Experiences
danielanewman
29
2.4k
10 Git Anti Patterns You Should be Aware of
lemiorhan
PRO
656
59k
Building Better People: How to give real-time feedback that sticks.
wjessup
366
19k
It's Worth the Effort
3n
184
28k
Build your cross-platform service in a week with App Engine
jlugia
229
18k
Put a Button on it: Removing Barriers to Going Fast.
kastner
60
3.7k
Fireside Chat
paigeccino
34
3.2k
YesSQL, Process and Tooling at Scale
rocio
171
14k
No one is an island. Learnings from fostering a developers community.
thoeni
21
3.1k
The Cult of Friendly URLs
andyhume
78
6.2k
Producing Creativity
orderedlist
PRO
343
39k
Transcript
FunctionBuilderͰίϯ ύΠϥΛදݱ͠Α͏ͱͨ͠ Yumemi.inc Αͬ͠ʔɹ
ࣗݾհ ΏΊΈiOSΤϯδχΞ 24ࡀ SwiftUIͱxPlatʹڵຯਂʑ Vue.js/node.js/CS @seijin4486
SwiftUI͔ͬͨ͢͝ શʹDSLʁ͔ͱࢥ͍͖ɺSwiftͷྗΛੜ͔͠ ͬͨه๏ implict return/property wrapper/function builder UIKitͰഓͬͨܦݧ͕ແʹؼ͢͜ͱશ෦ΕͯiOS ΤϯδχΞ྆खͰສࡀ(ͪΖΜUIKitͷݟࠓޙ ੜ͖Δͣ
ࠓͬͯΔͷ ίϯϐϡʔλʔγεςϜͷཧ ͱ࣮ VM͔ΒΞηϯϒϥม͢Δ ͱ͜ΖͰ͑ͳ͍͔ͳ…ɻ
͜͏ॻ͚ͨΒؾ࣋ͪྑ͍ͷͰʂ var body: some VMCommand { Function(name: “mult”) { Push(.constant,
0) Pop(.local, 0) Push(.argument, 1) Pop(.local, 1) Label(“LOOP”) …. Label(“END”) Return } ɹ… } var commands: [Command] = [] func build() -> String { commands.append(Push(.constant, 0)) commands.append(Pop(.argument, 1)) commands.append(Pop(.local, 1)) commands.append(Label(“Loop”)) return commands .map { $0.generate() } .joined(separator: “\n”) } ݱঢ় FunctionBuilderͷظ
ͬͯΈΑ͏ʂ
Ͱ͖ͳ͔ͬͨ
Ұ෦ɺͰ͖ͳ͔ͬͨ TupleViewͷΑ͏ͳΈΛͬͯɺ࣮ࡍʹbody ͷπϦʔΛߏங͢ΔΈ͕͔Βͳ͔ͬͨ SwiftUIͰHTMLͷඳըΛ͢ΔϓϩδΣΫτΛݟͨ ͕ɺMirror࠶ىॲཧΛͬͯؤுͬͯΔ ៉ྷͳղܾ๏ఘΊͯɺҰ୴͜Μͳܗʹͨ͠
FunctionBuilder @_functionBuilder struct CommandBuilder { public static func buildBlock<Content>(_ content:
Content) -> String where Content: Command { content.body } public static func buildBlock<T1, T2>(_ t1: T1, _ t2: T2) -> String where T1: Command, T2: Command { [t1.body, t2.body] .joined(separator: "\n") } struct TupleCommand<T>ͷར༻ఘΊͨ protocol Command { var body: String { get } } struct AssemblyCommand: Command { var body: String init(@CommandBuilder builder: () -> String) { body = builder() } }
͜͏ॻ͚ΔΑ͏ʹͳΓ·ͨ͠ struct Add: Command { var body: String { AssemblyCommand
{ A.symbol(.sp) C.assign(destination: .am, computation: .mMinusOne) C.assign(destination: .d, computation: .m) C.assign(destination: .a, computation: .aMinusOne) C.assign(destination: .m, computation: .dPlusM) }.body } }
ίϯύΠϧ࣌ & ใ͚ͭͨ͠ struct Add: Command { var body: String
{ AssemblyCommand { () -> String in … ᶃ CommandBuilder.buildBlock( … ᶄ A.symbol(.sp), C.assign(destination: .am, computation: .mMinusOne), C.assign(destination: .d, computation: .m), C.assign(destination: .a, computation: .aMinusOne), C.assign(destination: .m, computation: .dPlusM) ) }.body } } @_functionBuilder struct CommandBuilder { public static func buildBlock<T1, T2>(_ t1: T1, _ t2: T2) -> String where T1: Command, T2: Command { [t1.body, t2.body] .joined(separator: "\n") } ᶃ ΫϩʔδϟͷฦΓ ᶄ CommandBuilder
৮ͬͯΈͨײ ࢹ֮తͳཧղ༻ҙੑ্͕͕Δ(Έ͍͢) buildBlockgybͰੜ͞Εͯͦ͏ TupleViewΛͲ͏ͬͯΔ͔Γ͍ͨ Ϣʔεέʔε͕ҧͬͨ
Ϣʔεέʔε͕ҧͬͨ…ͳͥʁ SwiftUIɺ։ൃऀ͕ࣗ༝ʹViewStackΛΊΔ struct MyGroupView : View { var category: String
var categorizedItems: [Item] var body: some View { VStack(alignment: .leading, spacing: 10) { Text(category) .padding(.top, 10) .padding(.leading, 8) .background(Color.green) .cornerRadius(5) .padding(5) Group { ForEach(categorizedItems) { item in ListRow(item: item) } } } .padding(.bottom, 10) } }
Ϣʔεέʔε͕ҧͬͨ…ͳͥʁ Push, Pop, Call, FunctionͳͲɺVMΛׂ/ύʔε͠ ͨ༰ʹґଘͯ͠ߏங͢ΔͷͰɺ։ൃऀ͕ࣗߏ ங͢Δߏ͕΄΅ଘࡏ͠ͳ͍ ϝϦοτ΄΅ͳ͍ VMهड़DSLͱͯ͠FunctionBuilderΛ༻͍ΔͳΒ… ΞϦ(?)
·ͱΊ Apple͕ViewBuilderͰ࡞ͬͨ༰ΛͲ͏ඳը͍ͤͯ͞Δͷ ͔͔Βͳ͍ɻΓ͍ͨ ViewBuilderΛ͏ͱɺ͘͢͝ݟ͘͢ॻ͚Δࣄ͕͔ͬͨ ΤϯδχΞଆ͕ߏΛࣗ༝ʹهड़͢ΔέʔεͰɺઈେ ͳޮՌΛൃش͢Δɻ ࠓճͷόοΫΤϯυίϯύΠϥͰͬͯΈΔࢼΈࣦഊ Ͱ៉ྷʹݟ͑Δ