305 Views
April 28, 20
スライド概要
2020/4/28 の Swift 愛好会で「_Function Builders」についての話したときに使った資料をアップしました。この機能は発展途上中で、今回は Swift 5.2 の時点での Function Builders を試行錯誤で試したときのお話になります。
※ Docswell での公開に移行する直前の Slideshare での閲覧数は 713 でした。
正統派趣味人プログラマー。プログラミングとは幼馴染です。
@ 'VODUJPO#VJMEFST JO4XJGU ۽୩༑ !FT@LVNBHBJ ू·Ε4XJGU͖ʂ4XJGUѪձWPM!ΦϯϥΠϯ
۽୩༑ 5PNPIJSP,VNBHBJ ⾣ 4XJGU͢Ͱ͖͕ޠݴɻ ⾣ ΈΜͳͰָ͠Ήษڧձ͕͖Ͱ͢ɻ ⾣ ϓϩάϥϛϯάͷָ͠͞Λ͍͖͍͑ͯͨɻ w ಉਓࢽଈചձʁ w ωοτϥδΦʁ w ษڧձͷ౦֎ژ։࠵ʁ
ࠓ׆ಈ࠶։ ͷػӡ ͩͬͨͣͳͷͰ͚͢ΕͲɻ
ۙ׆گಈ લճͷ4XJGU%BZT'VLVPLB ͋ͨΓҎ߱Λத৺ʹհ
ษڧձͷ౦֎ژ։࠵ ΈΜͳͰ4XJGU෮शձ(0 JOࡳຈr TU⒌ JOؠखr UI⒌ 4XJGU%BZ JOԭೄr OE⒌ 4XJGU%BZ JOࡳຈr UI⒌ NJOJ JOઋr SE⒌ JOԬr TU⒌ JOԬr UI⒌ 4XJGU%BZ JOԬr UI⒌ JOژr UI⒌ JOr UI⒌ XJUI/4&( JOԬr UI⒌ தࢭ JOࡳຈr UI⒌⒌ NJOJ ࠶ձ JOԬr OE⒌⒌ 4XJGU%BZT
ษڧձͷ౦֎ژ։࠵ ΈΜͳͰ4XJGU෮शձ(0 ˞͜ͷ࣌͝ੈͰ͢͠ɺ࣍ճ։࠵ະఆ
ಉਓࢽଈചձ ٕज़ॻయ̔
ಉਓࢽଈചձ ٕज़ॻయ̔ ˞͜ͷ࣌͝ੈʹΑΓɺ։࠵தࢭ
ٕज़ಉਓࢽ ࣥ͘͘චձ ࣥ͘͘චձ ʙٕज़ܥಉਓࢽʗࢽۀɾൃදࢿྉɾϒϩάʙ IUUQTUFDICPPLNFFUVQDPOOQBTTDPN
ٕज़ಉਓࢽ ࣥ͘͘චձ ˞͜ͷ࣌͝ੈʹΑΓɺ݄̓·Ͱ։࠵ࢭٳத ࣥ͘͘චձ ʙٕज़ܥಉਓࢽʗࢽۀɾൃදࢿྉɾϒϩάʙ IUUQTUFDICPPLNFFUVQDPOOQBTTDPN
ωοτϥδΦ ۽୩ͱ៸໘͕ϓϩάϥϛϯάίʔυͷ͔Β ௌ͑ͯ͘͜ΔʹࣖΛָ͚ͯ͠ΉϥδΦ ⾣ ୈ ίʔυϨϏϡʔͷҙٛΛ͔Έ͠ΊΔ ⾣ ୈ ྲྀసͷٕज़ಉਓࢽଈചձͱษڧձ ⾣ ୈ ࡾ߲ԋࢉࢠ ⾣ ୈ 5FDI-5ɺޭͷ ͭͷλω ⾣ ୈ 04ͷΞοϓσʔτରԠͷཪ ⾣ ୈ ٕज़ಉਓࢽɺϓϩάϥϛϯάͷ͋Δৗ ⾣ ୈ ͱ͖Ί͍ٕͨज़ॻ
ωοτϥδΦ ۽୩ͱ៸໘͕ϓϩάϥϛϯάίʔυͷ͔Β ௌ͑ͯ͘͜ΔʹࣖΛָ͚ͯ͠ΉϥδΦ ˞ؔऀ֤ҐͷڥมԽʹΑΓɺ৴ऴྃ ⾣ ୈ ίʔυϨϏϡʔͷҙٛΛ͔Έ͠ΊΔ ⾣ ୈ ྲྀసͷٕज़ಉਓࢽଈചձͱษڧձ ⾣ ୈ ࡾ߲ԋࢉࢠ ⾣ ୈ 5FDI-5ɺޭͷ ͭͷλω ⾣ ୈ 04ͷΞοϓσʔτରԠͷཪ ⾣ ୈ ٕज़ಉਓࢽɺϓϩάϥϛϯάͷ͋Δৗ ⾣ ୈ ͱ͖Ί͍ٕͨज़ॻ
ษڧձ Γ߹͍গਓ͚ͩͰͷษڧձ ͜ͷ࣌͝ੈͰ͢͠ ෆಛఆଟɺີۭؒΛආ͚ͯ։࠵
ษڧձ Γ߹͍গਓ͚ͩͰͷษڧձ ˞ࣄٸۓଶએʹྩൃݴΑΓɺࣗॗ ͜ͷ࣌͝ੈͰ͢͠ ෆಛఆଟɺີۭؒΛආ͚ͯ։࠵
ͭ͡ʹɺ͜·ͬͨɻ
-*/&-*7& ͡ΊͯΈ·ͨ͠ɻ
͜ͷࠒͷؔ৺Ͳ͜Ζ ू·ΕΔॴͷେ͞
੍࡞
ಉਓࢽ ٕज़ಉਓࢽ w w w w w w 4XJGUΠχγϟϥΠβʔେશ +BWB4DSJQU$PSFͰ༡΅͏ 4XJGUΒ͍͠දݱΛࢦͦ͏ 1SPUPDPM0SJFOUFE*OUFHFSTʹ ͏δΣωϦοΫϓϩάϥϛϯάͷະདྷ ϓϩάϥϚʔͷͨΊͷ ৽ઍࡀۭߓೖ J04$POJO-POEPOೖ IUUQTF[OFUKQCPPL
ษڧձΛָ͠ΉΞϓϦ $PEF1JFDFGPSNBD04 ιʔείʔυΛ5XJUUFSͱ(JTUʹಉ࣌ߘͰ͖Δ ษڧձͰݟΛΈΜͳͱڞ༗͍ͨ࣌͠ͱ͔ʹศརʂ
'VODUJPO#VJMEFST ؔϏϧμʔ
'VODUJPO#VJMEFST ֓ཁ %4-ΛຒΊࠐΉΈ มنଇΛؔϏϧμʔͰܕఆٛ ؔϏϧμʔଐੑΛ༩ͨ͠ϒϩοΫͰ%4-Λهड़ தؒޠݴ4*-ੜ࣌ʹຒΊࠐ·ΕΔ w w มߏػΛϥϯλΠϜʹ࣋ͪӽ͞ͳ͍ ੩తϝιουͱܕγεςϜͰม ࡏݱɺൃల్্
'VODUJPO#VJMEFST
ීஈͷίʔυͷॻ͖ํ
func serialization() -> String {
var serialized = ""
serialized += String(SerializedValue(turn: turn))
serialized += "\n"
serialized += String(SerializedValue(board: board))
serialized += "\n"
}
return serialized
'VODUJPO#VJMEFST ؔϏϧμʔΛఏ͖ͱͨ͠ڙ @Serialization func serialization() -> String { } turn board
'VODUJPO#VJMEFST %4 తʹಛԽͨ͠ίϯϐϡʔλʔޠݴ w w ಛఆͷతୡ͚ͩΛఆ ൚༻ੑ͕ͳ͍ΘΓʹѻ͍͍͢ ମͷ͕͋ޠݴΔ߹ʮΈࠐΈ%4-ʯͱݺΕΔ ઃܭඪ w w w ൚༻ੑɾแׅੑඞཁͳ͍ هड़Λද͠ݱ͍͢ͷʹ͢Δ ੑɾखଓ͖࠷খ͢ʹݶΔ
'VODUJPO#VJMEFST ؔϏϧμʔܕ ܕͷఆٛ࣌ʹ!@GVODUJPO#VJMEFSଐੑΛఴ͑Δ ؔߏஙϝιουͰมنଇΛ࣮͢Δ ੩తϝιου͚ͩͰ࣮͢Δ @_functionBuilder enum Sample { // ؔߏஙϝιουΛ࣮ }
'VODUJPO#VJMEFST ؔϏϧμʔଐੑ ؔɺҾɺܕࢉܭϓϩύςΟʔɺఴࣈߏจͰ͑Δ ܕࢉܭϓϩύςΟʔͱఴࣈߏจɺήολʔͰޮྗΛൃش ੩తϝϯόʔͰར༻Մೳ @Sample func execute() -> Component { init(@Sample body:()->Component) { // DSL Ͱࡌه // DSL Ͱࡌه } }
'VODUJPO#VJMEFST ؔߏஙϝιου ؔຊମΛੜ͢Δͷʹ༻ ؔϏϧμʔʹܕTUBUJDGVODͰఆٛ w w ༻్ʹԠͯ͡ϝιουॺ໊͕نఆ͞Ε͍ͯΔ Φʔόʔϩʔυ͕ར༻Մೳ
'VODUJPO#VJMEFST ༻ҙ͞Ε͍ͯΔϝιου 1. buildExpression(_: Expression) -> Component w w w w w w ϒϩοΫͷ֤ධՁࣜΛม ೖΕࢠʹͳ͍ͬͯΔϒϩοΫͷධՁࣜର 2. buildBlock(_: Component ...) -> Component ϒϩοΫʹ͓͚Δ֤ධՁࣜͷม݁ՌΛ݁߹ ೖΕࢠͷϒϩοΫΛઌʹධՁ 3. buildDo(_: Component ...) -> Component EPϒϩοΫͷม݁ՌΛ݁߹͢Δͷʹ͏ CVJME#MPDLͷ݁Ռ͕͚̍ͭͩͬͯ͘Δ༷ࢠ
'VODUJPO#VJMEFST ༻ҙ͞Ε͍ͯΔϝιου buildEither(first: Component) -> Component ̎ͭҎ্ͷπϦʔͰ࠷ॳͷଆͷ݁ՌΛੜ buildEither(second: Component) -> Component ̎ͭҎ্ͷπϦʔͰ࣍ͷଆͷ݁ՌΛੜ
'VODUJPO#VJMEFST ଘࡏෆ໌ͳϝιου buildFunction(_: Components...) -> Return ؔͷτοϓϨϕϧͰม݁ՌΛ݁߹͢Δͷʹ͏Β͍͠ʁ buildOptional(_: Component?) -> Component ΦϓγϣφϧͳαϒϒϩοΫ͔Β݁ՌΛऔಘ͢Δͷʹ͏ʁ
5SBOTGPSNBUJPO ؔϏϧμʔͷมنଇ
5SBOTGPSNBUJPO ϒϩοΫͱධՁࣜ ϒϩοΫͷ֤ධՁࣜΛ࿈ଓతʹม w w w CVJME&YQSFTTJPO͕͋Εมɺͳ͚Εແม CVJME%P͕͋ΕɺEPߏจΛධՁࣜͱͯ͠ѻ͑Δ CVJME&JUIFS͕͋ΕɺJGߏจΛධՁࣜͱͯ͠ѻ͑Δ ม֤ͨ͠ධՁࣜͷ݁ՌΛ݁߹ w CVJME#MPDLϝιουͰ֤ධՁࣜͷ݁ՌΛ݁߹
5SBOTGPSNBUJPO มͷએͱݴೖ ࠓͷͱ͜Ζ͑ͳ͍ʁ w w ϒϩοΫͰͷɺϩʔΧϧมͷએݴ ϒϩοΫͰͷɺมͷͷೖ
5SBOTGPSNBUJPO ݅ͱذΤϥʔϋϯυϦϯά ݅ذ w w w CVJME&JUIFS͕͋ΕɺJGߏจΛධՁࣜͱͯ͠ѻ͑Δ TFMFDUจ·ͩ͑ͳ͍ʁ CVJME0QUJPOBM·ͩ͑ͳ͍ʁ ΤϥʔϋϯυϦϯά UISPXεςʔτϝϯτ·ͩ͑ͳ͍ʁ EFGFSεςʔτϝϯτ·ͩ͑ͳ͍ʁ DBUDIΛ͏EPεςʔτϝϯτɺ͑ͳ͍ʁ
CVJME#MPDL ϒϩοΫͷධՁࣜΛଋͶͯ݁ՌΛಋ͘ ධՁࣜ ධՁࣜ ϒϩοΫͷ݁Ռ ộ ධՁࣜ
CVJME#MPDL ཁॴ ϒϩοΫͷ֤ධՁࣜͷΛଋͶͯม ධՁࣜͷݸΓͷʹܕԠͯ͡ΦʔόʔϩʔυՄೳ ࠷্ҐϒϩοΫͷ߹ɺ ߏஙϝιουͷΓ͕ɺؔͷΓͱͳΔ ೖΕࢠϒϩοΫͷ߹ɺ ߏஙϝιουͷΓ͕ɺϒϩοΫͱͯ͠ͷධՁ݁ՌͱͳΔ
CVJME#MPDL ෳͷ͔Β̍ͭͷʹม ⾣ ϒϩοΫͷධՁࣜͷ͕ɺϥϕϧͳ͠ҾͰ͞ΕΔ ⾣ Γͷܕࣗ༝ʹܾఆՄೳʢධՁ݁Ռͷܕʣ static func buildBlock( _ a: Component, _ b: Component) -> Component { }
CVJME#MPDL ड͚औΔܕࠞࡏՄೳ ⾣ ධՁࣜͷɺͦΕͧΕҟͳΔͰܕड͚औΓՄೳ ⾣ ΦʔόʔϩʔυͰෳύλʔϯΛڞଘՄೳ static func buildBlock(_ a: Int, _ b: String, _ c: Bool) -> Component { }
CVJME#MPDL ՄมҾΛར༻Մೳ ⾣ ධՁࣜͷʹݸॊೈʹରԠՄೳ ⾣ ಉ͋͡ͰܕΕՄมҾͰड͚औΕΔ static func buildBlock(_ components: Component...) -> Component { }
CVJME#MPDL ධՁࣜͷʹ7PJEΛར༻Մೳ ⾣ ධՁࣜͷ͕7PJEͷ߹ߟྀՄೳ ⾣ 7PJEΛฦؔ͢ΛɺϒϩοΫͰར༻Մೳʹ static func buildBlock(_ a: Int, _: Void) -> Component { }
CVJME#MPDL ۭͷϒϩοΫΛఆՄೳ ⾣ Λड͚औΒͳ͍͜ͱՄೳ ⾣ ධՁࣜΛแ͠ͳ͍ϒϩοΫΛ୲ static func buildExpression() -> Component { }
CVJME&YQSFTTJPO ධՁ͔ࣜΒ݁ՌΛಋ͘ ධՁࣜ ධՁࣜͷ݁Ռ
CVJME&YQSFTTJPO ཁॴ ϒϩοΫͷ֤ධՁࣜΛม লུՄೳ w লུ࣌ɺධՁࣜͷ݁Ռ͕ͦͷ··ΘΕΔ ධՁࣜͷΓͷʹܕԠͯ͡ΦʔόʔϩʔυՄೳ ͻͱͭͰఆٛ͢ΔͱɺඞͣͲΕ͔͕ద༻͞ΕΔ ϝιουͷΓɺͦͷධՁࣜͷධՁ݁Ռͱͯ͠ CVJME#MPDLʹ͞ΕΔ
CVJME&YQSFTTJPO ධՁࣜͷΛม ⾣ ධՁࣜͷΛϥϕϧͳ͠ҾͰड͚औΔ ⾣ ΓɺҙͷͰܕฦ٫ՄೳʢධՁࣜͷ࠷ऴ݁Ռʣ static func buildExpression(_ expression: Expression) -> Component { }
CVJME&YQSFTTJPO ධՁࣜͰͷQSJOUରԠ ⾣ 7PJEܕΛड͚औΓɺదͳΓΛࢦఆ ⾣ Γ͕7PJEͷؔΛɺϒϩοΫͰར༻Մೳʹ static func buildExpression(_: Void) -> Component { }
CVJME&YQSFTTJPO ධՁࣜͰͷGBUBM&SSPSରԠ ⾣ /FWFSܕΛड͚औΓɺϒϩοΫ͕ఆ͢ΔܕΛฦ٫ ⾣ Γͷ͕ܕ/FWFSͷؔΛɺϒϩοΫͰར༻Մೳʹ static func buildExpression(_: Never) -> Component { }
CVJME&YQSFTTJPO ແม ⾣ ͨͱ͑/FWFSܕͷධՁࣜΛఆͭͭ͠ɺ ͦΕҎ֎มෆཁͳΒɺδΣωϦΫεͰදݱՄೳ static func buildExpression(_: Never) -> Component { } static func buildExpression<T>(_ expression: T) -> T { } return expression
CVJME%P %PϒϩοΫͷ૯߹݁Ռ͔Β࠷ऴతͳ݁ՌΛಋ͘ ϒϩοΫͷ݁Ռ Do ϒϩοΫͷ݁Ռ
CVJME%P ཁॴ ϒϩοΫͷ૯߹݁ՌΛ%Pͱͯ͠ͷ࠷ऴ݁Ռʹม ҾɺଆͷCVJME#MPDL͔Βͷ݁ՌΛड͚औΔ Γɺ֎ଆͷCVJME#MPDLʹҾ͖͞ΕΔ ఆٛ͢Δ͜ͱͰɺϒϩοΫͰEPߏจͷར༻ΛڐՄ
CVJME%P EPߏจͷར༻ΛڐՄ ⾣ EPϒϩοΫͷධՁ݁ՌΛड͚औΓɺϒϩοΫͷ݁ՌΛੜ ⾣ ड͚औΔͱܕฦ͢ܕɺҟͳΔͷΛࢦఆՄೳ static func buildDo(_ component: Component) -> Component { }
CVJME&JUIFS ϒϩοΫͷ૯߹݁Ռ͔Β݅ࣜͷ݁ՌΛಋ͘ ݅ʹ߹கͨ͠ ϒϩοΫͷ݁Ռ If ϒϩοΫͷ݁Ռ
CVJME&JUIFS ཁॴ ݅ʹ߹கͨ͠ϒϩοΫͷ݁ՌΛ*Gͱͯ͠ͷ࠷ऴ݁Ռʹม ෳͷ݅ذΛߏͰද͢ݱΔ ҾͰड͚औΕΔͷ̎௨Γ ཱ݅ͨ͠ϒϩοΫଆͷCVJME#MPDL͔Βͷ݁Ռ ཱ݅ͨ͠CVJME&JUIFS͔Βͷ݁Ռ Γ͕͞ΕΔͷ̎௨Γ ݅จͷ֎ଆͷCVJME#MPDL ߏͰΈͨ֎ଆͷCVJME&JUIFS
CVJME&JUIFS ذઌ͕ͭͷ߹ if … { BLOCK ① } else { ② } 1st ᶃ 2nd ᶄ
CVJME&JUIFS ذઌ͕ͭͷ߹ if … { BLOCK ① } else if { ② } else { ③ } 1st 1st ᶃ 2nd ᶅ 2nd ᶄ
CVJME&JUIFS ذઌ͕ͭͷ߹ if … { BLOCK ① } else if … { 1st 2nd ② } else if … { ③ } else { ④ } 1st ᶃ 2nd ᶄ 1st ᶅ 2nd ᶆ
CVJME&JUIFS ذઌ͕ͭͷ߹ if … { BLOCK ① } else if … { 1st 2nd ᶇ ② } else if … { 1st ③ 2nd } else if … { ④ } else { ⑤ 1st ᶃ 2nd ᶄ 1st ᶅ 2nd ᶆ
CVJME&JUIFS ذઌ͕ͭͷ߹ BLOCK 1st 2nd 1st 1st ᶃ 1st ᶇ 2nd 2nd ᶄ 1st ᶅ 2nd ᶆ 2nd ᶈ
CVJME&JUIFS ذઌ͕ͭͷ߹ BLOCK 1st 2nd 1st 1st ᶃ 1st 2nd 2nd ᶄ 1st ᶅ 2nd ᶆ 1st ᶇ 2nd ᶉ 2nd ᶈ
CVJME&JUIFS ذઌ͕ͭͷ߹ BLOCK 1st 2nd 1st 1st ᶃ 1st 2nd 2nd ᶄ 1st ᶅ 2nd ᶆ 1st ᶇ 2nd 2nd ᶈ 1st ᶉ 2nd ᶊ
CVJME&JUIFS ذઌ͕ͭͷ߹ BLOCK 1st 2nd ᶋ 1st 2nd 1st 1st ᶃ 2n 2n 1st ᶅ 1st 2n 1st ᶇ 2n 2n 1st ᶉ 2n
CVJME&JUIFS ذઌ͕ݸͷ߹ BLOCK 1st 2nd 1st 1st 1st ᶃ 2n 2n 1st ᶋ 2nd 1st ᶅ 1st 2n 1st ᶇ 2n 2n 1st ᶉ 2n 2nd ᶌ
CVJME&JUIFS ذઌ͕ݸͷ߹ BLOCK 1st 2nd 1st 1st 1st ᶃ 2n 2n 1st 2nd 1st ᶅ 1st 2n 1st ᶇ 1st ᶋ 2n 2n 1st ᶉ 2n 2nd ᶍ 2n
CVJME&JUIFS JGจ͕ೖΕࢠͷ߹ if … { BLOCK ① } else { if … { 1st ᶃ 2nd ② } } else { ③ } BLOCK 1st ᶄ 2nd ᶅ
CVJME&JUIFS ௐͯΈͨҹ ҙߦͷϒϩοΫͷ߹ɺ֊Λ੍͖ͰޚΔ͍ͳ͕͠ؾ ͳ͓ɺೖΕࢠͨ݅͠จɺೖΕࢠͨ͠ઌͷϒϩοΫʹॴଐ ༻׆ͷҊͱͯ͠ ⾣ CVJME&JUIFS pSTU ͱCVJME&JUIFS TFDPOE Λ ۠ผ͠Α͏ͱ͠ͳ͍ ⾣ CVJME&JUIFSͰ݅ͷ֊ΛѲ͠Α͏ͱ͠ͳ͍ ⾣ มCVJME#MPDLʹͤͯɺCVJME&JUIFS pSTU ͱ CVJME&JUIFS TFDPOE ม݁ՌͷதܧͷΈ
"11&/%*9 'VODUJPO#VJMEFST
'VODUJPO#VJMEFST ؔͷߏ Build Block Build Function Build Build Expression Expression Build If Build Build Do Do Build Optional Build Block Build Build Either Do Build Block
&OKPZ4XJGU 5IBOLZPV ۽୩༑ !FT@LVNBHBJ