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
770
FunctionBuilderでコンパイラを表現しようとした
FunctionBuilderでコンパイラを表現しようとしたけど、できなかったしユースケースも違った話
yosshi
June 18, 2019
Tweet
Share
More Decks by yosshi
See All by yosshi
Object Oriented Software Development
yosshi4486
0
100
SwiftでZeplinのダークモード対応ツールを作ったよ
yosshi4486
0
460
Implement side-menu with SwiftUI
yosshi4486
2
640
Other Decks in Technology
See All in Technology
5分でカオスエンジニアリングを分かった気になろう
pandayumi
0
240
会社紹介資料 / Sansan Company Profile
sansan33
PRO
6
380k
Webアプリケーションにオブザーバビリティを実装するRust入門ガイド
nwiizo
7
830
roppongirb_20250911
igaiga
1
230
RSCの時代にReactとフレームワークの境界を探る
uhyo
10
3.4k
「何となくテストする」を卒業するためにプロダクトが動く仕組みを理解しよう
kawabeaver
0
410
Aurora DSQLはサーバーレスアーキテクチャの常識を変えるのか
iwatatomoya
1
990
CDK CLIで使ってたあの機能、CDK Toolkit Libraryではどうやるの?
smt7174
4
180
生成AI時代のデータ基盤設計〜ペースレイヤリングで実現する高速開発と持続性〜 / Levtech Meetup_Session_2
sansan_randd
1
150
今!ソフトウェアエンジニアがハードウェアに手を出すには
mackee
12
4.8k
現場で効くClaude Code ─ 最新動向と企業導入
takaakikakei
1
250
2つのフロントエンドと状態管理
mixi_engineers
PRO
3
110
Featured
See All Featured
Let's Do A Bunch of Simple Stuff to Make Websites Faster
chriscoyier
507
140k
Designing Experiences People Love
moore
142
24k
Building an army of robots
kneath
306
46k
What's in a price? How to price your products and services
michaelherold
246
12k
The Pragmatic Product Professional
lauravandoore
36
6.9k
Measuring & Analyzing Core Web Vitals
bluesmoon
9
580
Making the Leap to Tech Lead
cromwellryan
135
9.5k
[Rails World 2023 - Day 1 Closing Keynote] - The Magic of Rails
eileencodes
36
2.5k
Building Flexible Design Systems
yeseniaperezcruz
328
39k
A designer walks into a library…
pauljervisheath
207
24k
Done Done
chrislema
185
16k
Java REST API Framework Comparison - PWX 2021
mraible
33
8.8k
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Λ͏ͱɺ͘͢͝ݟ͘͢ॻ͚Δࣄ͕͔ͬͨ ΤϯδχΞଆ͕ߏΛࣗ༝ʹهड़͢ΔέʔεͰɺઈେ ͳޮՌΛൃش͢Δɻ ࠓճͷόοΫΤϯυίϯύΠϥͰͬͯΈΔࢼΈࣦഊ Ͱ៉ྷʹݟ͑Δ