Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Evolution Of Enumerator

Evolution Of Enumerator

Akinori MUSHA

March 23, 2019
Tweet

More Decks by Akinori MUSHA

Other Decks in Programming

Transcript

  1. ෢ऀ থل (@knu) • ෢ऀ (Musha) • Kanji: martial/brave-one •

    Meaning: samurai • থل (Akinori) • Kanji: shine/bright-age/century • Meaning: (My parents' hope) Shine in the next (21st) century • knu • Meaning: ?
  2. ෢ऀ থل (@knu) • FreeBSD committer (Ports): [email protected] • Ruby

    committer: [email protected] • (Sorted)Setͷ࡞ऀ • Enumeratorͷ࡞ऀ • Rails: 4.1ʙ (2014) • Team Nokogiri, Team Huginn, … • A Father Of Two !" • Working at Machimachi Inc.
  3. झຯ • কع 㽪 !" ΞϚޒஈ (ࢦ͢ɺ؍Δ) • Minecraft ⛏$

    • ϥϯν % (ौ୩ɺத໨ࠇɺֶܳେֶɺࣗ༝ٰ͕͋ͨΓ) • ΫϥϑτϏʔϧΛҿΉ: Craft beer • ԻָΛௌ͘ ' (Progressive, metal music)
  4. ϚνϚνΛࢧ͑Δٕज़ • Ruby / Rails • React.js • PostgreSQL /

    PostGIS • GCP / GAE Flex Environment ٕज़ϒϩάΛॻ͍͍ͯ·͢ʂ https://tech.machimachi.com/ We are hiring!
  5. ֎෦ΠςϨʔλ (External Iterator) • ଟ͘ͷݴޠɾϥΠϒϥϦ͸ͪ͜Β͕جຊ • ܁Γฦ͠Λ੍ޚ͢Δ໾ׂ͕ίϨΫγϣϯΦϒδΣΫτ·ͨ͸ϝιουͷ֎෦ɺ ͭ·Γ࢖͏ଆʹ͋Δ • ࢖͏ଆ͕ࣗ༝ͳλΠϛϯάͰΧʔιϧΛਐΊΒΕΔͷͰɺॲཧͷࣗ༝౓͸ߴ͍

    • ίϨΫγϣϯΛ࢖͏ଆ͕ϧʔϓม਺Λ؅ཧ͢Δඞཁ͕͋Δ఺͸໘౗ • forจͳͲͷ౶ҥߏจͰࢧԉ͢Δͷ͕௨ྫ • eachʹ͋ͨΔॲཧ͸forจɺmapʹ͋ͨΔॲཧ͸Ϧετ಺แදهɺͷΑ͏ʹಉ͡ ܁Γฦ͠Ͱ΋ߏจͷ࢖͍෼͚͕ඞཁʹͳΔ (each: for, map: list comprehension)
  6. ಺෦ΠςϨʔλ (Internal Iterator) • Ruby͸ͪ͜Β͕جຊ • ܁Γฦ͠Λ੍ޚ͢Δ໾ׂ͕ίϨΫγϣϯΦϒδΣΫτ·ͨ͸ϝιουͷ಺෦ɺ ͭ·ΓΦϒδΣΫτଆʹ͋Δ • ࣮ମͱͯ͠͸ɺ܁Γฦ͠͝ͱʹ࣮ߦ͢Δؔ਺Λड͚औΔߴ֊ؔ਺

    • ཁૉ͝ͱͷίʔϧόοΫؔ਺Λॻ͚ͩ͘ͳͷͰɺఆܕͷϧʔϓॲཧͷهड़͸ͱ ͯ΋؆୯ • ෳ਺ͷίϨΫγϣϯΛಉظతʹᢞΊΔͳͲ͸ۤखʢ͋Δ͍͸ແཧʣ • each΋map΋ಉ͡ߏจͰॻ͚Δ (each & map share a common construct)
  7. Rubyͷ಺෦ΠςϨʔλ Internal Iterator In Ruby • each + Enumerable ΛAPIͱͯ͠શ໘࠾༻͍ͯ͠Δ

    • ߴ֊ؔ਺ͱͯ͠ͷ಺෦ΠςϨʔλΛ࢖͍΍͍͢Α͏ɺϒϩοΫͱ͍͏ಛ घߏจΛ༻ҙ • break, next ͳͲϧʔϓʹదͨ͠δϟϯϓ໋ྩΛఏڙ • ͞Βʹ return Ͱ֎ଆͷϝιου͔Β΋ൈ͚ΒΕΔ • ݁Ռͱͯ͠ɺ֎෦ΠςϨʔλͱḮ৭ͳ͍ॲཧͷදݱྗ
  8. Rubyͷ֎෦ΠςϨʔλ External Iterator In Ruby • Ruby 1.8Ҏલ͸ඪ४తͳαϙʔτ͸ͳ͔ͬͨ • IOͳͲ͸ɺgets,

    eof?ͳͲͷʢ఻౷తͳʣ֎෦ΠςϨʔλܕ ͷAPI΋ఏڙ͍ͯ͠Δ • ഑ྻͳͲఴ͑ࣈΞΫηε͕Ͱ͖ΔίϨΫγϣϯͷ৔߹͸ɺࣗ ྗͰΠϯσοΫεม਺Λૢ࡞ͯ͠whileจͰճ͢ͳͲ
  9. ؔ࿈: Ruby 1.8ͷGenerator • Generator: converts an internal iterator to

    an external iteretor • ۩ମతʹ͸ɺEnumerableΦϒδΣΫτΛ౉͢ͱɺnextϝιουΛݺͿ౓ʹ͔ͦ͜Β ཁૉ͕ॱʹฦΔΦϒδΣΫτΛ࡞Δ • callcc (!)Λ࢖͍ɺ಺෦ΠςϨʔλͷ܁Γฦ͠ΛࢭΊͨΓ࠶։੍ͯ͠ޚΛୣ͏߽շͳ ࣮૷ ! • ޙʹThreadʹΑΔϦϥΠτ΋ࢼΈΒΕͨ • ͍ͣΕʹͤΑɺຖճ܁Γฦ͠ΛࢭΊͯ͸࠶։ ͢ΔͷͰΦʔόʔϔου͕͍͢͝ • SyncEnumerator: GeneratorΛ࢖ͬͯෳ਺ͷ಺෦ΠςϨʔλΛಉظతʹ܁Γฦ͢ (lazyͳ zip)
  10. Generatorͷ࢖༻ྫ 2ͭʢҎ্ʣͷίϨΫγϣϯΛಉظతʹϧʔϓॲཧͰ͖Δɻ require "generator" array1 = ["A", "B", "C", "D"]

    array2 = ["A", "B", "D", "C"] g1 = Generator.new(array1) g2 = Generator.new(array2) loop do e1 = g1.next e2 = g2.next # compare elements, etc. end
  11. eachͰ΋2ͭͷ഑ྻͷ֤ཁૉΛൺֱ͍ͨ͠ ෳ਺ͷeach͸ಉظͰ͖ͳ͍ ! array1 = ["A", "B", "C", "D"] array2

    = ["A", "B", "D", "C"] array1.each do |e1| array2.each do |e2| # gets all combinations end end
  12. eachͰ΋2ͭͷ഑ྻͷ֤ཁૉΛൺֱ͍ͨ͠ ยํ͚ͩ಺෦ΠςϨʔλΛ࢖͍ɺ΋͏Ұํ͸ఴ͑ࣈΞΫηε͢Ε͹Մೳ array1 = ["A", "B", "C", "D"] array2 =

    ["A", "B", "D", "C"] array1.each_with_index do |e1, i| e2 = array2[i] # This is OK end ͨͩɺఴ͑ࣈΞΫηεͰ͖ͳ͍ΠςϨʔλಉ࢜ͷ৔߹͸͍ͬͨΜ഑ྻԽ͢ΔͳͲͷલॲཧ͕ඞཁɻ ·ͨɺঢ়گʹΑͬͯยํ͚ͩϙΠϯλΛਐΊΔɺͷΑ͏ͳॲཧ͸Φϑηοτͷ؅ཧ΋ඞཁʹͳ Δɻ
  13. ྻڍ୯Ґ͍Ζ͍Ζ Units For Iteration จࣈྻʢStringʣͷ৔߹: • ࿦ཧߦʢlineʣ • όΠτʢbyteʣ •

    ʮจࣈʯʢcharʣ • ίʔυϙΠϯτʢcodepointʣ • ॻهૉΫϥελʢgrapheme clusterʣ • ͦͷଞɺޠʢwordʣɺจʢsentenceʣɺஈམʢparagraphʣɺ෺ཧߦʢphysical lineʣͳͲ΋ߟ͑ΒΕ Δɻ
  14. Mix-inͱͯ͠ͷݶք • includeͰ͸each͔֦͠ுͰ͖ͳ͍ʂ (Enumerable can only extend each) • each_byte΍each_keyͰ΋map΍select͍ͨ͠

    • ഑ྻ(Array)Խͯ͠΍Ε͹Ͱ͖Δ͚Ͳɺͨͱ͑͹findͷΑ͏ʹ1ͭݟ͔ͭͬ ͨΒ࢒Γ͸ཁΒͳ͍ɺͱ͍͏ͱ͖͸ඇޮ཰ (Intermediate arrays require memory) • ObjectSpace.each_objectͷΑ͏ʹϞδϡʔϧϝιου͕ΠςϨʔλɺ ͱ͍͏ྫ΋͋Δ (ObjectSpace is not an enumerable object, yet provides an iterator method)
  15. EnumeratorͷൃҊ • ͜ͷΞΠσΞʹײ໏Λड͚ͨࢲ͸ɺEnumeratorΛఏҊ (May 2001) • [ruby-list:29604] Importing eachdelegator.rb •

    [ruby-list:29624] Enumerator • [ruby-dev:13202] Re: [ruby-list:29672] Re: Enumerator • [ruby-dev:13259] Enumerator -- Round 2 • Enumerable::EnumeratorΫϥεΛઃ͚ɺ Kernel#enum_with(:each_xxx) ͰͦͷΠϯελϯεΛฦ͢ͱ͍͏಺༰ • each_xxx ϝιουΛࢧԉ͍ͨ͠
  16. ࿈ଓཁૉͷ܁Γฦ͠ • nilຒΊͤͣʹ (size - n + 1) ճ܁Γฦͯ͠ऴΘͬͯ͠· ͏ͷͰɺʮίϯςΩετ෇͖܁Γฦ͠ʯͱͯ͠࢖͏ʹ͸

    ͪΐͬͱ଍Γͳ͍ • ͨͱ͑͹࠷ॳʹ [nil, 1, 2]ɺ࠷ޙʹ [5, 6, nil] Λ଍ ͯ͘͠ΕΕ͹શཁૉͷલޙίϯςΩετ෇͖܁Γฦ͠ʹͳΔ ͷʹ… ! Ruby 2.6ͷchainͰٹࡁ͞Ε·͢ʂʢޙड़ʣ
  17. ༨ஊ: ਖ਼نදݱΤϯδϯͷมߋ • ৽ͨʹॻ͖ى͜͞ΕͨΤϯδϯʮَंʯ(Oniguruma) by K.Kosako • ͦΕ·Ͱ͸GNU regexϥΠϒϥϦΛ(ຐ)վ଄ͯ͠࢖͍ͬͯͨ •

    Perl֦ுΛ͕Μ͹࣮ͬͯ૷͖͕ͯͨ͠ɺ֦ுੑʹ΋ݶք • ϥΠηϯε͕͚ͩ͜͜LGPLͩͬͨͷͰऔΓѻ͍ʹ஫ҙΛཁͨ͠ • RubyͰ͸ະ࣮૷ͩͬͨPerlޓ׵ͷ௥ՃػೳΛ΄΅͢΂ͯඋ͑ɺBSDL Ͱɺ֦ுੑɺੑೳʹ΋༏Ε͍ͯͨ • ݱࡏ(2012-)͸ޙܧͷʮَӢʯ(Onigmo)ʹͳ͍ͬͯΔ
  18. ༨ஊ: CSIํࣜͷM17Nಋೖ • Code Set Independentํࣜ • ݸʑͷStringΦϒδΣΫτ͕ࣗ਎ͰΤϯίʔσΟϯά৘ใΛ࣋ͪɺෳ ਺ͷΤϯίʔσΟϯάͷจࣈྻσʔλ͕ࠞࡏͰ͖Δ •

    ͋·ΓଞͷݴޠʹྨΛݟͳ͍ • ಺෦ΤϯίʔσΟϯά͸UTF-8ͷΈʹ౷Ұ͢Δͷ͕ʢ౰࣌Ͱ΋ʣେ੎ • ͍͍ͤͥબ΂ͯ΋1ͭͷΈ • َंͷෳ਺ΤϯίʔσΟϯάରԠ෦͕ૅͱͳ͍ͬͯΔ
  19. Enumeratorͷ૊ΈࠐΈԽ • ext/enumerator ͔ΒτοϓϨϕϧʹҠಈ͠ɺσϑΥϧτͰϩʔυ͞ΕΔΑ ͏ʹ (2005) • require͕ෆཁʹ ! •

    ૊ΈࠐΈΫϥεʹʮϒϩοΫͳ͠eachʯ͕࣮૷͞ΕΔ • Ruby 1.9ͷFiberΛར༻ͯ͠next, next?, rewind͕࣮૷͞ΕΔ (Aug 2007) ͍ͭʹEnumerator͕֎෦ΠςϨʔλ݉༻ʹʂ (Enumerator became usable as an external iterator) • ͜ΕͰGenerator͸ແࣄҾୀ "
  20. Enumeratorͷਖ਼ࣜͳ૊ΈࠐΈԽ • Ruby 1.9.0-devϦϦʔε ! (Dec 2007) • 1.8ܥʹ΋όοΫϙʔτ͞Εࢲ͕ͯ͠ɺRuby 1.8.7ϦϦʔε

    (Jun 2008) ΍͕ͯདྷΔ1.9.1ͱͷΪϟοϓΛݮΒ͔ͨͬͨ͠ • 1.9.1Ͱͷ҆ఆ൛ϦϦʔεΛ߇͑ɺ͞Βʹ͔͜͜ΒEnumeratorͷ࢓༷٧Ί͕ਐΉ… • ϝϞΦϒδΣΫτͷ෇Ճػೳ (Iteration with a memo object) • ΠϯσοΫεͷ෇Ճ (Iteration with an index number)
  21. Iteration With A Memo Object ϧʔϓ಺ʢ͚ͩʣͰڞ༗Ͱ͖ΔΦϒδΣΫτΛ࣋ͪɺͦ͜ʹ৘ ใΛू໿ͯ݁͠Ռ஋ͱͯ͠ಘ͍ͨ result = {}

    records.each do |record| result[record.id] = record end p result # એݴ/ॳظԽɺૢ࡞ɺࢀরͷ3εςοϓΛ·ͱΊ͍ͨ
  22. Iteration With A Memo Object Enumerator#with_memoͷ໊લͰఏҊͨ͠ (Jun 2008) • [ruby-core:17084]

    Enumerable::Enumerator#with_memo • ࠷௿ݶͷهड़Ͱ࣮ݱͰ͖Δ result = records.each.with_memo({}) { |record, hash| hash[record.id] = record } • with_object, with_obj, withͳͲͷҊ΋ఴ͑ɺͦͷޙɺintroduceͱ͍͏͔͍͍ͬ͜Ҋ ΋ग़ͨ͠ • ͔͠͠ͳ͔ͳ͔ܾΊ͖Εͣɺແ೉ͳ each_with_object ͱ͍͏໊લͰೖΕͯ৸͔ͤΔ͜ͱ ʹͨ͠ ! (To be continued)
  23. Iteration With An Index Number • each_with_index͸͋Δ͕ɺ։࢝஋͕0ݻఆͳͷͰɺoriginΛࢦఆ͍ͨ͠ [ruby-dev:37921] with_index_from by

    mame͞Μ (2009) • ࠓ·Ͱ͸ࣗ෼ͰΦϑηοτΛ଍͍ͯͨ͠ file.each_with_index do |line, i| print "#{i+1}: #{line}" end • each_with_indexʹҾ਺Λ଍͔͕ͨͬͨ͠ɺeach_with_indexʹ౉͞ΕͨҾ਺͸ͦͷ ··eachʹ౉ΔΑ͏ʹͳ͍ͬͯΔ • ͨͱ͑͹String#each͸ΦϓγϣφϧҾ਺Ͱվߦʹ୅ΘΔ۠੾ΓจࣈΛࢦఆͰ͖Δ
  24. Ruby 1.9ͷҰൠ޲͚ϦϦʔε ͦͯ͠ؾ͕෇͘ͱ… Ruby 1.9.1ϦϦʔε ! (Jan 2009) • एׯෆຊҙͳ͕Βɺ

    each_with_object / with_object ͕ͦͷ໊લͰ֬ఆ͢Δ͜ͱʹ ! • ௕͍ͳ͋ͱࢥ͏ਓ΋ଟ͍ͱࢥ͍·͕͢ɺ͜͏͍͏ࣄ৘Ͱ͠ ͨ
  25. Lazy Iterators • find, any?, all?ͳͲɺ৚݅ʹ߹͏ʢ߹Θͳ͍ʣཁૉ͕ग़ݱͨ͠Βଧͪ੾Γɺͱ͍͏ Enumerableͷϝιου͕৭ʑ͋Δ • map΍selectΛ࿈࠯ͤ͞Δͱ͖ɺຖճ഑ྻΛ࡞Δͷ͸ۭؒޮ཰͕ѱ͍ •

    ू໿͍ͨ͠৔߹ɺೖΕ෺Λ༻ҙ͢Δͷ͸࠷ޙ͚ͩͰे෼ͳ͸ͣ • ͦ΋ͦ΋ɺϑΟϧλϦϯά͚͕ͩඞཁͰɺू໿ࣗମ͸ෆཁͳ͜ͱ΋ଟ͍ • [Feature #4653] Enumerable#rude_map by shyouhei (May 2011) • [Feature #4890] Enumerable#lazy by yhara (Jun 2011) • Ruby 1.9.3ʹ͸ؒʹ߹Θͣ (Oct 2011) • Ruby 2.0ͰEnumerable#lazy͓ΑͼEnumerator::Lazy͕࠾༻ (Feb 2013)
  26. Chaining Iterators Enumerator#+ ͕΄͍͠ɺͱ͍͏ཁ๬͕དྷͨͱ͖΋… • [Feature #709] Enumerator#+ (Nov 2008)

    by candlerb ʮ͜ΕͰҰԠͰ͖ΔΑʯ Enumerator.new { |y| collection1.each { |x| y << x } collection2.each { |x| y << x } }.each do |x| # Enumerates collection1, and then collection2 end
  27. Chaining Iterators, A Decate Later • ͦͯ͠े೥ޙɺࠓ౓͸chainͱ͍͏໊લͰఏҊ͕དྷͨ [Feature #15144] Enumerator#chain

    (Sep 2018) by zverok • ͦͷࠒʹ͸ɺࢲࣗ਎ͷܦݧ͔Β΋࿈࠯ͷϢʔεέʔε͸۩ ମతʹݟ͍͑ͯͨ !
  28. Chaining Iterators, A Decate Later • ૝ఆͰ͖ΔϢʔεέʔε • ྫ: ίϚϯυϥΠϯΦϓγϣϯͰͷࢦఆɺ؀ڥม਺ͷ஋ɺઃఆϑΝΠϧ಺ͷઃఆ

    ஋ɺͷॱʹݕࡧύεΛฦ͢ • ྫ: ࠷৽ͷߋ৽σʔλΛAPI͔ΒҾͬுͬͯฦ͠ɺଓ͍ͯϩʔΧϧετϨʔδʹ Ωϟογϡ͞Εͨ෦෼Λฦ͠ɺ͞ΒʹͦΕҎલͷ΋ͷ͕ඞཁͳΒAPI͔ΒҾ͍ͯฦ͢ • first(3), take_while, find ͳͲͰޮՌΛൃش • ୯७ʹɺ഑ྻΛ࡞Δ͜ͱͳ͘ෳ਺ͷετϦʔϜΛॱ࣍૸͍ࠪͨ͜͠ͱ͸࣮ࡍʹଟ͍ • શ߲໨૸ࠪ͢Δ৔߹Ͱ΋ޮ཰త ✨
  29. Chaining Iterators, A Decate Later • MatzΛަ͑ͨٞ࿦Ͱ΋ɺ Enumerator#+ ΛׂΓ౰ͯͯ΋໰ ୊ͳ͔Ζ͏

    ! ͱͳͬͨ • chain ͸ Enumerable ʹ͋ͬͯ΋͍͍ΑͶɺͱͳΓɺ͋Θ ͤͯRuby 2.6Ͱ࠾༻ "
  30. Example: chain + each_cons = Contexual Iteretion a = ["foo",

    "bar", "baz"] [nil].chain(a).each_cons(2) do |prev, curr| if prev.nil? puts "#{curr} comes first." else puts "#{curr} comes after #{prev}." end end # Output: foo comes first. bar comes after foo. baz comes after bar.
  31. Enumerator::Yielder#to_proc • [Feature #15618] Enumerator::Yielder#to_proc (Feb 2019) by knu Enumerator#to_procΛ࣮૷͢Δ͜ͱͰ

    enum = Enumerator.new { |y| Dir.glob("*.rb") { |file| File.open(file) { |f| f.each_line(&y) } # File.open(file) { |f| f.each_line { |line| y << line } } } } ͱॻ͚ΔΑ͏ʹ͢ΔఏҊ • Ruby 2.7Ͱ࠾༻ !
  32. Enumerator.generate • [Feature #14781] Enumerator.generate (May 2018) by zverok •

    Ұͭલͷ஋͔Β࣍ͷཁૉΛܾఆ͢Δ܁Γฦ͠ • ਺ֶͰ͍͏ʮ઴ԽࣜʯʹΑΔ܁Γฦ͠ఆٛ • ϊʔυͷ parent ΛॱʹḷΔͱ͔ • ϦτϥΠͷ଴ͪ࣌ؒΛഒʑʹ͍ͯ͘͠ͱ͔ • ݕ౼ࣄ߲ • ऴྃ৚݅ͷࢦఆํ๏ʢಛఆͷྫ֎ͰऴΘΔͷ͔ɺnilͰऴΘΔͷ͔ɺͦͷ৔߹nilΛؚΉͷ͔ʣ • 2ͭҎ্લ΋ࢀর͍ͨ͠ʁʢྫ: ϑΟϘφον਺ྻ… ͋·Γݱ࣮ʹ͸ͳ͍ʁʣ
  33. Multi-Value Or Array? • Hash#each / map ͸ϖΞΛ1Ҿ਺Ͱ2ཁૉ഑ྻΛϒϩοΫʹ౉ͯ͘͠Δ [1] pry(main)>

    {foo: 1, bar: 2, baz: 3}.each{|x| p x} [:foo, 1] [:bar, 2] [:baz, 3] => {:foo=>1, :bar=>2, :baz=>3} [2] pry(main)> {foo: 1, bar: 2, baz: 3}.map{|x| p x} [:foo, 1] [:bar, 2] [:baz, 3] => [[:foo, 1], [:bar, 2], [:baz, 3]]
  34. Multi-Value Or Array? • Hash#select / reject ͸ϖΞΛ2Ҿ਺ͰϒϩοΫʹ౉ͯ͘͠Δ [3] pry(main)>

    {foo: 1, bar: 2, baz: 3}.reject{|x| p x} :foo :bar :baz => {} [4] pry(main)> {foo: 1, bar: 2, baz: 3}.select{|x| p x} :foo :bar :baz => {:foo=>1, :bar=>2, :baz=>3}
  35. Multi-Value Or Array? • ͜ͷҧ͍͸Ͳ͔͜Βʁ • Hash#each / map ͸ϖΞΛ2ཁૉ഑ྻ1ͭΛϒϩοΫʹ౉ͯ͘͠Δ

    (yield [key, value]) • Hash#select / reject ͸ϖΞΛ2Ҿ਺ͰϒϩοΫʹ౉ͯ͘͠Δ (yield key, value) • Hash#select / reject ͸ɺRuby 1.8·Ͱ͸ArrayΛฦ͢ϝιου͕ͩͬͨɺ1.9͔ ΒHashΛฦ͢Α͏ʹมߋ͞Εͨ • ͦͷͱ͖ʹɺҙਤ͔ͯ͠஌Β͔ͣ2Ҿ਺Ͱ౉͢Α͏ʹͳͬͨ • ࠓ͞Β௚ͤͳ͍ͱͯ͠ɺmulti-value㱻arrayͷ૬ޓม׵͸धཁ͕͋Δ͔΋
  36. Multi-Value Or Array? • λϓϧͷ֤ཁૉʹରͯ͠ɺͦΕͧΕϝιουΛద༻͢Δྫ require "csv" line = "10,foo,3.14"

    modifiers = [:to_i, :to_s, :to_f] # "10".send(:to_i), "foo".send(:to_s), "3.14".send(:to_f) Λظ଴… p CSV.parse_line(line).zip(modifiers).map(&:send) #=> no method name given (ArgumentError) • ࣮ࡍʹ͸ ["10", :to_i].send, … ͕࣮ߦ͞Εͯ͠·͏
  37. Multi-Value Or Array? ͏·͍͘͘ ! require "csv" line = "10,foo,3.14"

    modifiers = [:to_i, :to_s, :to_f] p CSV.parse_line(line).zip(modifiers).each_splat.map(&:send) #=> [10, "foo", 3.14]
  38. ͪͳΈʹ… • CSVʹ͸convertersͱ͍͏͢͹Β͍͠ػೳ͕͋Γ·͢ʂ line = "10,foo,3.14" modifiers = [:to_i, :to_s,

    :to_f] p CSV.parse_line(line, converters: ->(value, field) { value.send(modifiers[field.index]) }) #=> [10, "foo", 3.14] • ͱ͍͏Θ͚Ͱઆಘʹ࢖͏ʹ͸ద͞ͳ͍ϢʔεέʔεͰͨ͠
  39. Lazy: Back To Eager? • Ұ౓lazyʹ͢Δͱɺී௨ͷ(eagerͳ)Enumeratorʹ͸໭ͤͳ͍ lazy = [1, 2,

    3].lazy # Expecting #each would create a normal Enumerator... still_lazy = lazy.each # Not: Enumerator::Lazy#each is overridden to return a Lazy # Not usable as a normal Enumerator p still_lazy.map { |x| x * 2 } #=> #<Enumerator::Lazy: #<Enumerator::Lazy: [1, 2, 3]>:map> • lazyΛۦ࢖ͯ͠࡞ͬͨEnumeratorΛɺmap͢Δͱ഑ྻ͕ฦΔΑ͏ͳ;ͭ͏ͷEnumerableΦϒδΣΫτ ͱͯ͠ฦ͍ͨ͠
  40. Lazy: Back To Eager? ͏·͍͘͘ ! lazy = [1, 2,

    3].lazy eager = lazy.eager # Usable as a normal enumerable object p eager.map { |x| x * 2 } #=> [2, 4, 6]
  41. ·ͱΊ • ΈΜͳେ޷͖Enumerable͸ͲΜͲΜਐԽ͖ͯ͠·ͨ͠ɻ • EnumeratorͷಋೖʹΑΓɺ७ਮʹ܁Γฦࣗ͠ମͷݚڀ͕ਐΈ·ͨ͠ɻ • ࠓ΋ਐԽ͍ͯ͠·͢ʂ • ࠓޙ΋ɺݱ࣮ͷχʔζΛ౿·͑ͯʮ΄͍͠ʂʯػೳΛ֦ॆ͍͖ͯ͠·͢ʂ •

    ࠷ۙ͸RubyͷϦϦʔεαΠΫϧ͕ߴ଎Խ͍ͯ͠ΔͷͰɺ͋ͳͨ΋ཁ๬Λग़ͤ͹ ೥຤ʹ͸۩ݱԽ͢Δ͔΋ʂ • ΫϦεϚεϓϨθϯτ ! • ϚνϚνͰҰॹʹಇ͘஥ؒΛืू͍ͯ͠·͢ʂ