JavaScript ( 時々 TypeScript ) で ゆるやかにはじめる関数型プログラミング

JavaScript ( 時々 TypeScript ) で ゆるやかにはじめる関数型プログラミング

初夏のJavaScript祭 2018 での登壇時に発表した資料です。
https://javascript-fes.doorkeeper.jp/events/73314
#jsfes

82ed567f8497acfed7f7b464225dd536?s=128

wakamsha

May 19, 2018
Tweet

Transcript

  1. +BWB4DSJQU ࣌ʑ5ZQF4DSJQU Ͱ ΏΔ΍͔ʹ͸͡ΊΔؔ਺ܕϓϩάϥϛϯά Introducing functional programming w/ JavaScript (

    & sometimes TypeScript ) ॳՆͷ+BWB4DSJQUࡇ  !XBLBNTIB /BPLJ:"."%"
  2. ͸͡Ίʹ +BWB4DSJQUʹ͸ؔ਺ܕϓϩάϥϛϯάͷΤοηϯε͕ଟ෼ʹؚ·Ε͍ͯΔ ϦΞΫςΟϒɾϓϩάϥϛϯάͷྲྀߦʹΑΓɺXFCϑϩϯτΤϯυͷੈք ʹ΋ਁಁ͖ͯͨ͠ ͦΜͳؔ਺ܕϓϩάϥϛϯάͷ͞ΘΓ෦෼Λ͝঺հ

  3. ·ͣ͸ͪ͜ΒͷίʔυΛޚཡ͍ͩ͘͞ First, please take a look at this code… TS

  4. ['foo', 'bar', 'baz'].map((val: string) => { return `${val}!!!`; }); //=>

    ['foo!!!', 'bar!!!', 'baz!!!'] function double(x: number): number { return x * 2; } double(3); //=> 6
  5. ['foo', 'bar', 'baz'].map((val: string) => { return `${val}!!!`; }); //=>

    ['foo!!!', 'bar!!!', 'baz!!!'] function double(x: number): number { return x * 2; } double(3); //=> 6 ͲͪΒ΋ؔ਺ܕϓϩάϥϛϯάͷఆٛʹଈͨ͠΋ͷͰ͢
  6. ['foo', 'bar', 'baz'].map((val: string) => { return `${val}!!!`; }); //=>

    ['foo!!!', 'bar!!!', 'baz!!!'] function double(x: number): number { return x * 2; } double(3); //=> 6 ͦ΋ͦ΋ؔ਺ܕϓϩάϥϛϯάͱ͸ʁ ෳ਺ͷࣜΛؔ਺ͷద༻ʹΑͬͯ૊Έ߹ΘͤΔϓϩάϥϛϯάελΠϧ ؔ਺߹੒ ෭࡞༻ͷແ͍ؔ਺ΛϝΠϯʹѻ͏ϓϩάϥϛϯάελΠϧ ७ਮ
  7. ['foo', 'bar', 'baz'].map((val: string) => { return `${val}!!!`; }); //=>

    ['foo!!!', 'bar!!!', 'baz!!!'] function double(x: number): number { return x * 2; } double(3); //=> 6 ରٛʹҐஔ͢Δͷ͕ʰखଓ͖ܕϓϩάϥϛϯάʱ ม਺Λഁյతʹॻ͖׵͑ΔͳͲɺ෭࡞༻Λۦ࢖͢Δ ໨తͷͨΊʹ࣮ߦ͢΂͖Ұ࿈ͷεςοϓΛҰͭͷؔ਺ʹ࣋ͨͤΔ ఆٛͨؔ͠਺͸ϓϩάϥϜ࣮ߦதͷ೚ҙͷλΠϛϯάͰݺͼग़ͤΔ
  8.  ؔ਺߹੒  খ͞ͳؔ਺Λ૊Έ߹ΘͤΔͱ͍͏͜ͱ  ߴ֊ؔ਺  ७ਮ  ෭࡞༻Λແ͘͢ͱ͍͏͜ͱ

     ෆมੑ *NNVUBCMF   ࢀরಁաੑ  ͜Ε͔Βؔ਺ܕϓϩάϥϛϯάΛֶͿਓ΁ ຊ೔͓࣋ͪؼΓ͍͖͍ͨͩͨ͜ͱ 1PJOUTUP MFBSO
  9. ؔ਺߹੒ ෳ਺ͷࣜΛؔ਺ͷద༻ʹΑͬͯ૊Έ߹ΘͤΔϓϩάϥϛϯάελΠϧ

  10. ͱɺͦͷલʹߴ֊ؔ਺ʹ͍ͭͯ About a higher-order function

  11. ͱɺͦͷલʹߴ֊ؔ਺ʹ͍ͭͯ [1, 4, 9, 16].map(x => x * 2); ['spray',

    'limit', 'exuberant', 'present'].filter(word => word.length > 6 ); "SSBZͷ*UFSBUJWFͳϝιου͸ؔ਺ΛҾ਺ʹऔΔ ؔ਺ΛҾ਺PS໭Γ஋ͱͯ͠ѻ͏΋ͷΛʰߴ֊ؔ਺ʱͱ͍͏ ߴ֊ؔ਺͸ؔ਺Λ߹੒͢Δ΋ͷͰ͋Δ
  12. ؆୯ͳؔ਺߹੒Λ΍ͬͯΈΑ͏ Basic Examples

  13. /** * ཁ݅: ͋Δ਺஋ʹ 1 Λ଍ͯ͠ 2ഒͨ݁͠ՌΛฦ͢ػೳ */ // Ұͭͷؔ਺Ͱ࣮ݱ͢Δͱ͜͏ͳΔ

    // ಛԽ͗ͯͯ͢͠൚༻ੑʹ͚ܽΔͨΊɺอकੑ΋௿͍ function addOneTimesTwo(x: number): number { return (x + 1) * 2; } // Ҿ਺ʹ 1 Λ଍͚ͩ͢ function addOne(x: number): number { return x + 1; } // Ҿ਺Λ 2ഒ͢Δ͚ͩ function timesTwo(x: number): number { return x * 2; }
  14. /** * ཁ݅: ͋Δ਺஋ʹ 1 Λ଍ͯ͠ 2ഒͨ݁͠ՌΛฦ͢ػೳ */ // ݁Ռ͸શͯಉ͡

    addOneTimesTwo(2); //=> 6 const x = addOne(2); timesTwo(x); //=> 6 timesTwo(addOne(2)); //=> 6
  15. DPNQPTF߹੒༻ͷؔ਺Λ࡞ͬͯΈΑ͏ Basic Examples

  16. function compose(fn1, fn2) { return function(x0) { return fn1(fn2(x0)); }

    } // TypeScript Ͱॻ͘ͱ͜Μͳײ͡ function compose<V0, T1, T2>( fn1: (x: T1) => T2, fn2: (x0: V0) => T1, ): (x0: V0) => T2 { return function(x0: V0): T2 { return fn1(fn2(x0)); }; }
  17. const addOneTimesTwo = compose<number, number, number>(timesTwo, addOne); addOneTimesTwo(2); //=> 6

    compose<number, number, number>(timesTwo, addOne)(2); //=> 6
  18. const addOneTimesTwo = compose<number, number, number>(timesTwo, addOne); addOneTimesTwo(2); //=> 6

    compose<number, number, number>(timesTwo, addOne)(2); //=> 6 ؔ਺߹੒ ؔ਺͸ͻͱ·ͱ·Γʹͤͣɺࡉ͔͘෼ղ͢Δ খ͞ͳؔ਺Λ૊Έ߹Θͤͯେ͖ͳػೳΛ࣮ݱ͢Δ খ͘͞୯७ͳؔ਺͸ɺͦΕ͚ͩ൚༻ੑ͕ߴ͍ 6OJU5FTUΛॻ͘ͷ͕༰қʹͳΔ
  19. ७ਮ ෭࡞༻ͷͳ͍ؔ਺ΛϝΠϯʹѻ͏ϓϩάϥϛϯάελΠϧ

  20. ·ͣ͸ͪ͜ΒͷίʔυΛޚཡ͍ͩ͘͞ First, please take a look at this code…

  21. // 1 function sum(x: number, y: number): number { return

    x + y; } // 2 let i: number = 0; function sum2(x: number, y: number): number { i += x + y; return x + y; } // 3 function sum3(x: number, y: number): number { return x + y + i; } // 4 function sum4(x: number, y: number): number { const result = x + y; console.log(result); return result; }
  22. // 1 function sum(x: number, y: number): number { return

    x + y; } // 2 let i: number = 0; function sum2(x: number, y: number): number { i += x + y; return x + y; } // 3 function sum3(x: number, y: number): number { return x + y + i; } // 4 function sum4(x: number, y: number): number { const result = x + y; console.log(result); return result; } Ұͭ໨͚͕ͩ७ਮͳؔ਺Ͱ͢ ଞ͸શͯʰෆ७ʱͳؔ਺Ͱ͢
  23. // 1 function sum(x: number, y: number): number { return

    x + y; } // 2 let i: number = 0; function sum2(x: number, y: number): number { i += x + y; return x + y; } // 3 function sum3(x: number, y: number): number { return x + y + i; } // 4 function sum4(x: number, y: number): number { const result = x + y; console.log(result); return result; } ७ਮͳؔ਺ͱ͸ ໭Γ஋͸ඞͣҾ਺ͱͯ͠༩͑ΒΕͨ஋͔ΒͷΈܭࢉ͞ΕΔ ؔ਺ͷ֎෦Ͱมߋ͞ΕΔՄೳੑͷ͋ΔσʔλʹҰ੾ґଘ͠ͳ͍ ؔ਺࣮ߦ෦ͷ֎ଆʹଘࡏ͢ΔԿ͔͠Βͷঢ়ଶΛҰ੾มߋ͠ͳ͍
  24. // Ҿ਺ͷ஋Λ଍͠ࢉ͚ͨͩ͠ ( ७ਮ ) function sum(x: number, y: number):

    number { return x + y; } // άϩʔόϧม਺Λมߋ͍ͯ͠Δ let i: number = 0; function sum2(x: number, y: number): number { i += x + y; return x + y; } // ໭Γ஋͕Ҿ਺͚ͩ͡Όͳ͘άϩʔόϧม਺ʹґଘͯ͠Δ function sum3(x: number, y: number): number { return x + y + i; } // console.log ͱ͍͏׬શʹ֎ͷੈքʹׯবͯ͠Δ function sum4(x: number, y: number): number { const result = x + y; console.log(result); return result; }
  25. ෭࡞༻͸ͳΔ΂͘ແ͍ํ͕๬·͍͠ ঢ়ଶΛؔͨ͠ґଘؔ܎͕ੜ·Εͯ͠·͏ ঢ়ଶͱ͸άϩʔόϧม਺΍ΠϯελϯεͳͲ ґଘؔ܎ͱ͸ؔ਺ͷݺͼग़͠ॱংͳͲ ࠶ݱੑʹ੍໿͕ൃੜ͢Δ

  26. ෭࡞༻Λແͨ͘͢ΊͷୈҰา The first step to eliminate side effects…

  27. ෭࡞༻Λແͨ͘͢ΊͷୈҰา let i: number = 0; function sum3(x: number, y:

    number, i: number): number { return x + y + i; } ॲཧʹඞཁͳσʔλ͸શͯҾ਺ͱͯ͠ड͚औΔ άϩʔόϧม਺΋Ҿ਺ͱͯ͠ड͚औΕ͹0,
  28. interface User { firstName: string; lastName: string; greet(): string; }

  29. class User { constructor(private firstName: string, private lastName: string) {}

    public updateFirstName(name: string): User { return new User(name, this.lastName); } public updateLastName(name: string): User { return new User(this.firstName, name); } public greet(): string { return `hello, ${this.firstName} ${this.lastName}!!`; } }
  30. class User { constructor(private firstName: string, private lastName: string) {}

    public updateFirstName(name: string): User { return new User(name, this.lastName); } public updateLastName(name: string): User { return new User(this.firstName, name); } public greet(): string { return `hello, ${this.firstName} ${this.lastName}!!`; } } ΦϒδΣΫτ͸$MBTTͱͯ͠ఆٛ͢Δ ֤ϝιουͷ࠷ޙʹࣗ਎ͷ৽͍͠ΠϯελϯεΛ໭Γ஋ʹฦ͢ ຖճ৽͍͠ΠϯελϯεΛͦͷ࣌ͷ಺෦஋͔Βੜ੒͢Δ ݺͼग़͠ͷίϯϑϦΫτ͕ൃੜ͠ͳ͍
  31. ࢀরಁաੑ ؔ਺Λͦͷ໭Γ஋ࣗମʹࠩ͠ସ͑ͯ΋ϓϩάϥϜશମ͕յΕͳ͍͜ͱ ೔ຊͷࠃձ͸೔ຊͷट౎Ͱ։͔ΕΔ ೔ຊͷࠃձ͸౦ژͰ։͔ΕΔ

  32. ७ਮ ґଘؔ܎Λ࣋ͨͳ͍ͱ͍͏͜ͱ͸ɺͦΕ͚ͩίʔυͷݟ௨͕͠ྑ͍ ݟ௨͠ͷྑ͍ίʔυ͸อकੑ͕ߴ͍ ґଘؔ܎Λ࣋ͨͳ͍७ਮؔ਺͸6OJU5FTU͕͠΍͍͢ 6OJU5FTUͷ͠΍͍͢ίʔυ͸อकੑ͕ߴ͍ ७ਮؔ਺͸߹੒͕͠΍͍͢

  33. 3BNEBKT ௒ڧྗͳؔ਺ܕϓϩάϥϛϯά༻ JavaScript ϥΠϒϥϦ

  34. 3BNEBKT ίϨΫγϣϯૢ࡞ܥͱෆมੑ୲อ ७ਮ ͷೋ໘ੑΛซͤ࣋ͭ ΄΅શͯͷ"1*͸ෆมੑͱ෭࡞༻ͷͳ͍ػೳ *NNVUBCMF ͱͯ͠ઃܭ "1*໊͕)BTLFMM΍4DBMBͷͦΕʹΠϯεύΠΞ͞Ε໋໊ͨ

  35. PSYENCE:MEDIA PRODUCED BY ৄ͘͠͸ฐࣾϒϩάΛ͝ࢀর͍ͩ͘͞

  36. ؔ਺ܕϓϩάϥϛϯάͷϝϦοτσϝϦοτ First, please take a look at this code… TS

  37. ؔ਺ܕϓϩάϥϛϯάͷϝϦοτ ҰͭҰͭͷ෦඼ ؔ਺ ͕খ͍͞ͷͰอकੑɾ֦ுੑ͕ߴ͍ 6OJU5FTU͕ॻ͖΍͍͢ ґଘؔ܎Ͱ಄Λ೰·͢͜ͱ͕গͳ͍ ෭࡞༻Λ௥͍ग़͢͜ͱͰ༧ظͤ͵ಈ࡞ ෆ۩߹ Λະવʹ๷͛Δ TS

  38. ؔ਺ܕϓϩάϥϛϯάͷϝϦοτ Ұൠతͳ(6*ΞϓϦέʔγϣϯͱͷ૬ੑ͕ྑ͍ ϦΞΫςΟϒϓϩάϥϛϯά 3Y΍'MVYͳͲ ͕ద͍ͯ͠Δ TS

  39. ؔ਺ܕϓϩάϥϛϯάͷσϝϦοτ ෋߽ϓϩάϥϛϯάʹͳΓ͕ͪ ඞવతʹؔ਺ͷݺͼग़͠ճ਺͕૿͑Δ ؔ਺߹੒ͳͲ  ֶशίετ͕ߴ͍ खଓ͖ܕͱ͸ύϥμΠϜ͕ͥΜͥ̽ҧ͏ TS

  40. ͜Ε͔Βؔ਺ܕϓϩάϥϛϯάΛֶͿਓ΁

  41. ͜Ε͔Βؔ਺ܕϓϩάϥϛϯάΛֶͿਓ΁

  42. ͜Ε͔Βؔ਺ܕϓϩάϥϛϯάΛֶͿਓ΁ ʰ1BSTFSΛ࡞ͬͯΈΔʱ͕୊ࡐͱ͓ͯ͢͢͠Ί ద౰ͳ+40/σʔλΛߏ଄ղੳͯ͠ΈΔͱ͔ ؆୯ͳίʔυϑΥʔϚολΛ࡞ͬͯΈΔͱ͔

  43. ͜Ε͔Βؔ਺ܕϓϩάϥϛϯάΛֶͿਓ΁ ຊ֨తʹֶͼ͍ͨͳΒ)BTLFMM ਖ਼ਅਖ਼໏ͷʰ७ਮؔ਺ܕϓϩάϥϛϯάݴޠʱ ੩తܕ෇͚ݴޠ XFCܥͷۀ຿ʹ௚݁͢Δ͜ͱ͸গͳ͍͕ɺʰڭཆʱͱͯ͠ ֶͿͳΒ͜Ε͕࠷ద ʰ͍͢͝)ຊʱҰ࡭ࣸܦ͢Δ͚ͩͰ΋͔ͳΓͷֶͼʹͳΔ

  44. *OUSPEVDFNZTFMG Զͷ໊ΛݴͬͯΈΖ ࣗݾ঺հ

  45. !XBLBNTIB *OUSPEVDFNZTFMG /BPLJ:"."%"ࢁా௚थ XFCϑϩϯτΤϯυΤϯδχΞ ॴଐגࣜձࣾϦΫϧʔτϚʔέςΟϯάύʔτφʔζ ෭ۀۀ຿ҕୗͱͯ͠๭ελʔτΞοϓاۀΛ͓ख఻͍த

  46. PSYENCE:MEDIA PRODUCED BY

  47. PSYENCE:MEDIA PRODUCED BY ϦΫϧʔτϚʔέςΟϯάύʔτφʔζͷެࣜςοΫϒϩά ٕज़ྗɾϊ΢ϋ΢ͷମܥԽ 3.1ͷ಺੡։ൃ૊৫͓Αͼࣥචऀͷࣾ֎ϓϨθϯε޲্ ࠾༻ϒϥϯσΟϯάڧԽ ۀք׆ੑԽ΁ͷߩݙ 14:&/$&.&%*"

  48. None
  49. https://tech.recruit-mp.co.jp 3.1 ϒϩά

  50. 5IBOLZPV