1.9 ã§ã¯ Enumerator ãçµã¿è¾¼ã¿ã«ãªãã大ããæ¡å¼µããã¦ãã¾ããã¤ãã§ã«ãããã¯ã®çç¥ã«å¯¾ããèãæ¹ã«ãå½±é¿ãããã¾ããçµæ§é大ãªå¤æ´ã®ããã«ããã®è©±ã¯ãã¾ãè°è«ãå¨ç¥ãããã¦ããªããããªæ°ãããã®ã§ãç¾ç¶ã® Enumerator ã«ã¤ãã¦ããã®æ©è½ã¨åé¡ç¹ãã¾ã¨ãã¦ã¿ã¾ããã
Enumerator ã®æ©è½
ã¾ããeach ã map ãªã©ãã¤ãã¬ã¼ã¿ã£ã½ãã¡ã½ããããããã¯ãªãã§å¼ã³åºã㨠Enumerator ãå¾ããã¾ãã
p [1,2,3].each #=> #<Enumerable::Enumerator:0xb7d38260> p [1,2,3].map #=> #<Enumerable::Enumerator:0xb7d38210>
Object#to_enum ã¾ã㯠enum_for ã使ã£ã¦ãæå®ããã¡ã½ããã«ãã Enumerator ãæ示çã«ä½ããã¨ãã§ãã¾ãã
p [1,2,3].to_enum(:each) #=> #<Enumerable::Enumerator:0xb7d51350>
Enumerator ã«ã¯ (åãç¥ãéã) 3 ã¤ã®æ©è½ãããããã§ãã
å¤é¨ã¤ãã¬ã¼ã¿ã¨ãã¦ä½¿ãã
æã大ããªæ©è½ã§ãã大ããªæ©è½ã ãã©ãã©ã®ããã使ããã®ãã¯ãããããã¾ãããPython æ´¾ã«ã¯åããããï¼
e = [1,2,3].each # é ã«åãåºã p e.next #=> 1 p e.next #=> 2 # å·»ãæ»ã e.rewind # é ã«åãåºã p e.next #=> 1 p e.next #=> 2 p e.next #=> 3 # å ¨é¨åãåºããå¾ã次ãåãåºããã¨ãããä¾å¤ p e.next #=> iteration reached at end (StopIteration)
ããã«ãããã¦ãKernel#loop ã®ãããã¯ã®ä¸ã§ä¾å¤ StopIteration ãçºçããã loop ãçµäºãããã¨ã«ãªã£ã¦ãã¾ãã
p loop { raise StopIteration } #=> nil e = [1,2,3].each loop { p e.next } #=> 1, 2, 3
Enumerable#with_index ã使ãã
æãå¤ãã®äººãå¾ ã¡æãã§ããæ©è½ã§ããeach ã«ã¯ each_with_index ãããã¾ããããããã each 以å¤ã®ã¤ãã¬ã¼ã¿ã§ã使ããããã«ãªãã¾ãã
p ["a","b","c"].map.with_index {|v, i| v + i.to_s } #=> ["a0", "b1", "c2"] p [2,1,0].find.with_index {|v, i| v == i } #=> 1
Enumerable#zip ã®å¼æ°ã«æ¸¡ãã
æãå°å³ãªæ©è½ã§ããzip ã®å¼æ°ã« Enumerable ã渡ããã¨ãã§ãã¾ãã
e1 = [4,5,6].each e2 = [7,8,9].each [1,2,3].zip(e1, e2) do |a, b, c| p [a, b, c] #=> [1, 2, 3], [4, 5, 6], [7, 8, 9] end
Enumerable#cycle ã¨åãããã¨ããæãï¼ åè: これを使って Fizzbuzz を書いた例ã
Enumerator ã®åé¡ç¹
ããããã¯çç¥ â Enumerator ãè¿ããã® convention ãå¾æ¥ã¨éäºæ
ãããã¯ã®æç¡ã¯ block_given? ã«ãã£ã¦ã¡ã½ããå´ã§å¤æã§ããã®ã§ããããã¯ã®æç¡ã«ãã£ã¦ã¡ã½ããã®æåãå¤ãããã¨ãã§ãã¾ãããFile.open ã String#gsub ãå ¸åä¾ã§ãã
# ãã¡ã¤ã«ãã³ãã©ãæ示çã« close ãã fh = File.open("foo"); puts fh.read; fh.close # ãã¡ã¤ã«ãã³ãã©ãæ示çã« close ãã File.open("foo") {|fh| puts fh.read } # b ã c ã d ã * ã«ç½®ãæãã "abcde".gsub(/[bcd]/, "*") #=> "a***e" # b ã c ã d ããã®å¤§æåã«ç½®ãæãã "abcde".gsub(/[bcd]/) {|s| s.upcase } #=> "aBCDe"
ã¤ã¾ãããããã¯ãçç¥ããã¨ãã®æåã¯ãã®ã¡ã½ããã®è¨è¨è ãå¤æãã¦ãã¾ãããã§ããããã¤ãã¬ã¼ã¿ã£ã½ãã¡ã½ããã¯ãããã¯çç¥æã« Enumerator ãè¿ããã¨ããä½æ³ãçºçãããã¨ã§ããã®æ±ºå®æ¨©ãå¶éããã¾ããã¾ããã¤ãã¬ã¼ã¿ã£ã½ãã¡ã½ãããèªåã§å®ç¾©ããã¨ãããã®ä½æ³ã«å¾ãããã®ãã¾ããªããæåã§å ¥ããå¿ è¦ãããã®ãé¢åã§ãã
module Enumerable # å¥æ°çªç®ã®å¤ã ãåæãã def leapfrog # ãã¾ããªã return to_enum(:leapfrog) unless block_given? f = false each {|x| yield x if f = !f } end end e = [1,2,3,4,5].leapfrog; loop { p e.next } #=> 1, 3, 5
ããããã¯çç¥ â Enumerator ãè¿ããã¨ãã¹ãã¡ã½ããã®åºæºãããããªã
Enumerable#grep ãcount ãall? ãany? ãtake_while ãªã©ã¯ãåã®æè¦ã§ã¯ååã¤ãã¬ã¼ã¿ã£ã½ãã¡ã½ãããªãã§ãããããããã¯çç¥ â Enumerator ãè¿ããã¨ãªã£ã¦ãã¾ãããã¤ã¾ã [1,2,3].count.with_index {|v, i| ... } ã¨ã¯ã§ãã¾ããã(追è¨: count 㨠take_while ã¯å¯¾å¿ããã¾ããã)ãããã®ã¡ã½ããããã¨ãã¨ãããã¯ã®çç¥ã«æå³ãä¸ãã¦ããããã§ããããã
p ["a","b","c","b","a"].grep("b") #=> ["b", "b"] p ["a","b","c","b","a"].grep("b") {|x| x + "." } #=> ["b.", "b."] p ["a","b","c","b","a"].count("b") #=> 2 p ["a","b","c","b","a"].count {|x| x != "b" } #=> 3 p [true, true, true].all? #=> true p [true, false, true].all? #=> false
ã§ã Enumerable#map ã zip ããããã¯çç¥ã«æå³ãä¸ãã¦ããã®ã§ããããªãããããã¯ä»æ§å¤æ´ããããããã¯çç¥ â Enumerator ãè¿ããã¨ãªã£ã¦ãã¾ãããããããã¾ããã
ã¡ã½ãããã§ã¤ã³ããã¨ã¤ãã¬ã¼ã¿ã®æå³ãæ¶ãã
a = [1,2,3] p a.reject!.map {|x| x == 2 } #=> [false, true, false] p a #=> [1, 2, 3]
reject! ã®æå³ãã©ãã«ãç¾ãã¾ããããããã©ããªãã¹ããã¨ããã¨ãããããããªããã§ããã©ããªã«ã well-defined ã§ãªããããªæ°åã«ãªãã¾ãã
å人çãªæè¦
ä¸ã®è¨è¿°ãååå人çãªæè¦ã®å
¥ã£ãæ¸ãæ¹ã«ãªã£ã¦ãã¾ãããä¸å¿ã¡ããã¨æ¸ãã¾ãã
å©ç¹ã®å
訳ã with_index ã 9 å²ãå¤é¨ã¤ãã¬ã¼ã¿ã 1 å²ã¨ããå°è±¡*1ã§ãããã»ã¨ãã© with_index ã®ããã ãã«ã¯ã¡ãã£ã¨å¤§ãããªéå
·ã ã¨æã£ã¦ãã¾ãããã¡ãã with_index ã«ç¸å½ããæ©è½ã¯æ¬²ãããã©ãååé·ãããç¾å¨ã®ã¤ãã¬ã¼ã¿ã®åæ°ãè¿ãçµã¿è¾¼ã¿å¤æ°ã¨ãã®æ¹ãå¬ãããã§ã *2 ã
ãã¨ãããããã¯çç¥ â Enumerator ãè¿ããã¨ãã convention ã¯å¾æ¥ã¨éäºæãªã¡ã½ããè¨è¨ã®å¶ç´ã«ãªãã®ã§ãã¡ãã£ã¨ã ãå対ã§ãã
*1:å¤é¨ã¤ãã¬ã¼ã¿ã Fiber ã¨åã表ç¾åãæã£ã¦ãã 4 å²ãããã«æ¥ä¸æã ãã©ã
*2:çµã¿è¾¼ã¿å¤æ°å¢ããã®ã¯æ代ã«éè¡ãã¦ãæããããã©ã