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
690
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
420
Implement side-menu with SwiftUI
yosshi4486
2
620
Other Decks in Technology
See All in Technology
New Relicを活用したSREの最初のステップ / NRUG OKINAWA VOL.3
isaoshimizu
3
670
100 名超が参加した日経グループ横断の競技型 AWS 学習イベント「Nikkei Group AWS GameDay」の紹介/mediajaws202411
nikkei_engineer_recruiting
1
180
SDNという名のデータプレーンプログラミングの歴史
ebiken
PRO
2
200
複雑なState管理からの脱却
sansantech
PRO
1
170
rootlessコンテナのすゝめ - 研究室サーバーでもできる安全なコンテナ管理
kitsuya0828
3
390
Next.jsとNuxtが混在? iframeでなんとかする!
ypresto
2
1.1k
20241120_JAWS_東京_ランチタイムLT#17_AWS認定全冠の先へ
tsumita
2
320
LINEヤフーにおけるPrerender技術の導入とその効果
narirou
2
630
Flutterによる 効率的なAndroid・iOS・Webアプリケーション開発の事例
recruitengineers
PRO
0
160
オープンソースAIとは何か? --「オープンソースAIの定義 v1.0」詳細解説
shujisado
12
1.5k
【令和最新版】AWS Direct Connectと愉快なGWたちのおさらい
minorun365
PRO
5
810
電話を切らさない技術 電話自動応答サービスを支える フロントエンド
barometrica
2
500
Featured
See All Featured
Fireside Chat
paigeccino
34
3k
CoffeeScript is Beautiful & I Never Want to Write Plain JavaScript Again
sstephenson
159
15k
Fantastic passwords and where to find them - at NoRuKo
philnash
50
2.9k
The Language of Interfaces
destraynor
154
24k
How to Ace a Technical Interview
jacobian
276
23k
Teambox: Starting and Learning
jrom
133
8.8k
Practical Tips for Bootstrapping Information Extraction Pipelines
honnibal
PRO
10
730
Designing the Hi-DPI Web
ddemaree
280
34k
Ruby is Unlike a Banana
tanoku
97
11k
10 Git Anti Patterns You Should be Aware of
lemiorhan
655
59k
Build your cross-platform service in a week with App Engine
jlugia
229
18k
Evolution of real-time – Irina Nazarova, EuRuKo, 2024
irinanazarova
4
380
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Λ͏ͱɺ͘͢͝ݟ͘͢ॻ͚Δࣄ͕͔ͬͨ ΤϯδχΞଆ͕ߏΛࣗ༝ʹهड़͢ΔέʔεͰɺઈେ ͳޮՌΛൃش͢Δɻ ࠓճͷόοΫΤϯυίϯύΠϥͰͬͯΈΔࢼΈࣦഊ Ͱ៉ྷʹݟ͑Δ