Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
從 Enumerator 看 Ruby 的迭代器
Search
蒼時弦や
July 27, 2019
Programming
1
110
從 Enumerator 看 Ruby 的迭代器
RubyConf TW 2019
蒼時弦や
July 27, 2019
Tweet
Share
More Decks by 蒼時弦や
See All by 蒼時弦や
2024 - COSCUP - Clean Architecture in Rails
elct9620
2
140
2023 - RubyConfTW - Rethink Rails Architecture
elct9620
0
110
20230916 - DDDTW - 導入 Domain-Driven Design 的最佳時機
elct9620
0
380
2023 - WebConf - 選擇適合你的技能組合
elct9620
0
600
20230322 - Generative AI 小聚 ft. Happy Designer
elct9620
0
320
2022 - 默默會 - 重新學習 MVC 的 Model
elct9620
1
420
MOPCON 2022 - 從 Domain-Driven Design 看網站開發框架隱藏
elct9620
1
440
2022 - COSCUP - 我想慢慢寫程式該怎麼辦?
elct9620
0
220
2022 - COSCUP - 打造高速 Ruby 專案開發流程
elct9620
0
250
Other Decks in Programming
See All in Programming
Introduction to kotlinx.rpc
arawn
0
690
Immutable ActiveRecord
megane42
0
140
Domain-Driven Transformation
hschwentner
2
1.9k
iOSエンジニアから始める visionOS アプリ開発
nao_randd
3
130
SwiftUIで単方向アーキテクチャを導入して得られた成果
takuyaosawa
0
270
Pythonでもちょっとリッチな見た目のアプリを設計してみる
ueponx
1
560
TokyoR116_BeginnersSession1_環境構築
kotatyamtema
0
110
Rubyで始める関数型ドメインモデリング
shogo_tksk
0
100
SpringBoot3.4の構造化ログ #kanjava
irof
2
990
dbt Pythonモデルで実現するSnowflake活用術
trsnium
0
120
How mixi2 Uses TiDB for SNS Scalability and Performance
kanmo
36
14k
ASP. NET CoreにおけるWebAPIの最新情報
tomokusaba
0
370
Featured
See All Featured
The Straight Up "How To Draw Better" Workshop
denniskardys
232
140k
Creating an realtime collaboration tool: Agile Flush - .NET Oxford
marcduiker
27
1.9k
The Pragmatic Product Professional
lauravandoore
32
6.4k
The Web Performance Landscape in 2024 [PerfNow 2024]
tammyeverts
4
410
Adopting Sorbet at Scale
ufuk
74
9.2k
Keith and Marios Guide to Fast Websites
keithpitt
411
22k
Building Better People: How to give real-time feedback that sticks.
wjessup
367
19k
No one is an island. Learnings from fostering a developers community.
thoeni
21
3.1k
How to train your dragon (web standard)
notwaldorf
91
5.8k
How GitHub (no longer) Works
holman
314
140k
Practical Tips for Bootstrapping Information Extraction Pipelines
honnibal
PRO
12
960
Helping Users Find Their Own Way: Creating Modern Search Experiences
danielanewman
29
2.4k
Transcript
Review Ruby s Iterator with Enumerator Photo by Tine Ivanič
on Unsplash
WEB DEVELOPER GAME DEVELOPER ࣌ ݭ @elct9620
None
As a Ruby developer, We use #each every day
BUT How it works?
#iterator Photo by Joel Fulgencio on Unsplash
def iterator(&block) yield 1 yield 2 yield 3 end
VALUE rb_block_call(VALUE obj, ID mid, int argc, const VALUE *
argv, VALUE (*bl_proc) (ANYARGS), VALUE data2) { struct iter_method_arg arg; arg.obj = obj; arg.mid = mid; arg.argc = argc; arg.argv = argv; return rb_iterate(iterate_method, (VALUE)&arg, bl_proc, data2); } The block call is iterate in ruby
def each(&block) @i = 0 yield @i += 1 until
@i >= 10 end
#loop vs #while
static VALUE loop_i(void) { for (;;) { rb_yield_0(0, 0); }
return Qnil; } Loop is a method with a block
#enumerator Photo by Glenn Carstens-Peters on Unsplash
[].each # => #<Enumerator: []:each>
Why we need Enumerator?
enum = [1, 2, 3].to_enum enum.next # => 1 enum.next
# => 2 enum.next # => 3
Enumerator vs Enumerable
class Backpack include Enumerable def initialize(items) @items = items end
def each(&block) @items.each(&block) end end backpack = Backpack.new([:water, :apple]) backpack.map {}
#generator Photo by m0851 on Unsplash
#to_enum vs Enumerator.new
class List def each(&block) #... end end List.new.to_enum # =>
#<Enumerator: #<List:0x00007fa490988a78>:each>
class List def pop(&block) #... end end List.new.to_enum(:pop) # =>
#<Enumerator: #<List:0x00007fa491081fa0>:pop>
If Enumerator.new didn t have target ruby will create a
Generator
Enumerator.new do |yielder| yielder << 1 yielder << 2 end
Why we need Yielder?
enum = Enumerator.new do yield 1 yield 2 end puts
enum.to_a # => no block given (yield) (LocalJumpError)
class Yielder def initialize(&block) @proc = block.to_proc end def <<(value)
@proc.call(value) self end end
class Generator def initialize(&block) @proc = block.to_proc end def each(&_block)
yielder = Yielder.new { |x| yield x } @proc.call(yielder) end end
#lazy Photo by Kate Stone Matheson on Unsplash
It is hard to figure out it, but useful
class Backpack def each(&block) yield p(1) yield p(2) yield p(3)
end end backpack = Backpack.new.to_enum backpack.map(&:rect).take(1).to_a backpack.lazy.map(&:rect).take(1).to_a
class Backpack def each(&block) yield p(1) yield p(2) yield p(3)
end end backpack = Backpack.new.to_enum backpack.map(&:rect).take(1).to_a backpack.lazy.map(&:rect).take(1).to_a
backpack.map(&:rect).take(1).to_a # => 1 # => 2 # => 3
backpack.lazy.map(&:rect).take(1).to_a # => 1
backpack.take(1).to_a # => 1 backpack.lazy.take(1).to_a # => 1
backpack = Backpack.new.to_enum backpack.lazy.reverse_each.take(1).to_a # => 1 # => 2
# => 3
And last, let s discuss implement #lazy in Ruby
Thanks