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
95
SwiftでZeplinのダークモード対応ツールを作ったよ
yosshi4486
0
430
Implement side-menu with SwiftUI
yosshi4486
2
630
Other Decks in Technology
See All in Technology
プロセス改善による品質向上事例
tomasagi
2
2.2k
次世代KYC活動報告 / 20250219-BizDay17-KYC-nextgen
oidfj
0
150
なぜ私は自分が使わないサービスを作るのか? / Why would I create a service that I would not use?
aiandrox
0
510
あれは良かった、あれは苦労したB2B2C型SaaSの新規開発におけるCloud Spanner
hirohito1108
2
370
第13回 Data-Centric AI勉強会, 画像認識におけるData-centric AI
ksaito_osx
0
370
トラシューアニマルになろう ~開発者だからこそできる、安定したサービス作りの秘訣~
jacopen
2
1.8k
人はなぜISUCONに夢中になるのか
kakehashi
PRO
6
1.5k
エンジニアのためのドキュメント力基礎講座〜構造化思考から始めよう〜(2025/02/15jbug広島#15発表資料)
yasuoyasuo
16
6.3k
飲食店予約台帳を支えるインタラクティブ UI 設計と実装
siropaca
7
1.6k
Larkご案内資料
customercloud
PRO
0
650
滅・サービスクラス🔥 / Destruction Service Class
sinsoku
6
1.6k
運用しているアプリケーションのDBのリプレイスをやってみた
miura55
1
490
Featured
See All Featured
Designing Dashboards & Data Visualisations in Web Apps
destraynor
231
53k
The Pragmatic Product Professional
lauravandoore
32
6.4k
A Tale of Four Properties
chriscoyier
158
23k
Measuring & Analyzing Core Web Vitals
bluesmoon
6
240
Dealing with People You Can't Stand - Big Design 2015
cassininazir
366
25k
How to train your dragon (web standard)
notwaldorf
91
5.8k
Why Our Code Smells
bkeepers
PRO
336
57k
Fight the Zombie Pattern Library - RWD Summit 2016
marcelosomers
233
17k
No one is an island. Learnings from fostering a developers community.
thoeni
21
3.1k
The Myth of the Modular Monolith - Day 2 Keynote - Rails World 2024
eileencodes
21
2.5k
Chrome DevTools: State of the Union 2024 - Debugging React & Beyond
addyosmani
3
320
Build your cross-platform service in a week with App Engine
jlugia
229
18k
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Λ͏ͱɺ͘͢͝ݟ͘͢ॻ͚Δࣄ͕͔ͬͨ ΤϯδχΞଆ͕ߏΛࣗ༝ʹهड़͢ΔέʔεͰɺઈେ ͳޮՌΛൃش͢Δɻ ࠓճͷόοΫΤϯυίϯύΠϥͰͬͯΈΔࢼΈࣦഊ Ͱ៉ྷʹݟ͑Δ