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

Evolution Of Enumerator

Sponsored · Ship Features Fearlessly Turn features on and off without deploys. Used by thousands of Ruby developers.

Evolution Of Enumerator

Avatar for Akinori MUSHA

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