Download - Блоки, лямбды, замыкания
![Page 1: Блоки, лямбды, замыкания](https://reader033.vdocuments.mx/reader033/viewer/2022052910/559c1d891a28abde298b45ed/html5/thumbnails/1.jpg)
Лямбды, блоки, замыкания
А давайте посмотрим, что у них внутри
![Page 2: Блоки, лямбды, замыкания](https://reader033.vdocuments.mx/reader033/viewer/2022052910/559c1d891a28abde298b45ed/html5/thumbnails/2.jpg)
Дмитрий Кириенко
Twitter: @DimKiriyenko
Github: dmitriy-kiriyenko
![Page 3: Блоки, лямбды, замыкания](https://reader033.vdocuments.mx/reader033/viewer/2022052910/559c1d891a28abde298b45ed/html5/thumbnails/3.jpg)
![Page 4: Блоки, лямбды, замыкания](https://reader033.vdocuments.mx/reader033/viewer/2022052910/559c1d891a28abde298b45ed/html5/thumbnails/4.jpg)
rb_block_t
???
![Page 5: Блоки, лямбды, замыкания](https://reader033.vdocuments.mx/reader033/viewer/2022052910/559c1d891a28abde298b45ed/html5/thumbnails/5.jpg)
10.times do str = "Hello world." puts strend
putstring "Hello world."setlocal str, 0putselfgetlocal str, 0send :puts, 1leave
rb_block_t
iseq
![Page 6: Блоки, лямбды, замыкания](https://reader033.vdocuments.mx/reader033/viewer/2022052910/559c1d891a28abde298b45ed/html5/thumbnails/6.jpg)
str_ext = "Hello"10.times do str = "world." puts "#{str_ext} #{str}"end
![Page 7: Блоки, лямбды, замыкания](https://reader033.vdocuments.mx/reader033/viewer/2022052910/559c1d891a28abde298b45ed/html5/thumbnails/7.jpg)
"Чтобы решить эту проблему мы вводим понятие замыкания как структуры, содержащей лямбда-выражение и окружение, которое будет использовано, когда это выражение будет применено к своим аргументам."Scheme: An Interpreter for Extended Lambda Calculus
![Page 8: Блоки, лямбды, замыкания](https://reader033.vdocuments.mx/reader033/viewer/2022052910/559c1d891a28abde298b45ed/html5/thumbnails/8.jpg)
Внутренний стек YARV
locals: str_ext
rb_control_frame_t
EP
str_ext = "Hello"10.times do str = "world." puts "#{str_ext} #{str}"end
Кадр стека верхнего уровня
![Page 9: Блоки, лямбды, замыкания](https://reader033.vdocuments.mx/reader033/viewer/2022052910/559c1d891a28abde298b45ed/html5/thumbnails/9.jpg)
Внутренний стек YARV
locals: str_ext
rb_control_frame_t
EP
str_ext = "Hello"10.times do str = "world." puts "#{str_ext} #{str}"end
Кадр стека верхнего уровня
rb_block_t
iseq
EP
![Page 10: Блоки, лямбды, замыкания](https://reader033.vdocuments.mx/reader033/viewer/2022052910/559c1d891a28abde298b45ed/html5/thumbnails/10.jpg)
Внутренний стек YARV
locals: str_ext
rb_control_frame_t
EP
str_ext = "Hello"10.times do str = "world." puts "#{str_ext} #{str}"end
Кадр стека Fixnum#times
![Page 11: Блоки, лямбды, замыкания](https://reader033.vdocuments.mx/reader033/viewer/2022052910/559c1d891a28abde298b45ed/html5/thumbnails/11.jpg)
Внутренний стек YARV
locals: str_ext
rb_control_frame_t
EP
Кадр стека Block#yield
str_ext = "Hello"10.times do str = "world." puts "#{str_ext} #{str}"end
locals: str
EP
rb_block_t
iseq
EP
![Page 12: Блоки, лямбды, замыкания](https://reader033.vdocuments.mx/reader033/viewer/2022052910/559c1d891a28abde298b45ed/html5/thumbnails/12.jpg)
DEFINE_INSNgetlocal(lindex_t idx, rb_num_t level)()(VALUE val){ int i, lev = (int)level; VALUE *ep = GET_EP();
for (i = 0; i < lev; i++) { ep = GET_PREV_EP(ep); } val = *(ep - idx);}
https://github.com/ruby/ruby/blob/trunk/insns.def#L43L67
![Page 13: Блоки, лямбды, замыкания](https://reader033.vdocuments.mx/reader033/viewer/2022052910/559c1d891a28abde298b45ed/html5/thumbnails/13.jpg)
"Чтобы решить эту проблему мы вводим понятие замыкания как структуры, содержащей лямбда-выражение и окружение, которое будет использовано, когда это выражение будет применено к своим аргументам."Scheme: An Interpreter for Extended Lambda Calculus
![Page 14: Блоки, лямбды, замыкания](https://reader033.vdocuments.mx/reader033/viewer/2022052910/559c1d891a28abde298b45ed/html5/thumbnails/14.jpg)
typedef struct rb_control_frame_struct { VALUE *pc; VALUE *sp; rb_iseq_t *iseq; VALUE flag; VALUE self; VALUE klass; VALUE *ep; rb_iseq_t *block_iseq; VALUE proc; const rb_method_entry_t *me;
#if VM_DEBUG_BP_CHECK VALUE *bp_check;#endif} rb_control_frame_t;
Control frame Block
typedef struct rb_block_struct { VALUE self; VALUE klass VALUE *ep; rb_iseq_t *iseq; VALUE proc;} rb_block_t;
![Page 15: Блоки, лямбды, замыкания](https://reader033.vdocuments.mx/reader033/viewer/2022052910/559c1d891a28abde298b45ed/html5/thumbnails/15.jpg)
require 'benchmark'require 'benchmark/ips'
Benchmark.ips do |b| b.report 'while' do sum = 0; i = 0 while i <= 10 sum += i; i += 1 end end
b.report 'block' do sum = 0 (1..10).each do |i| sum += 1 end end
b.report 'reduce' do (1..10).reduce {|acc, i| acc+i} endend
while 6763524 in 5.036406sblock 4267105 in 5.016071sreduce 3606540 in 5.054937s
![Page 16: Блоки, лямбды, замыкания](https://reader033.vdocuments.mx/reader033/viewer/2022052910/559c1d891a28abde298b45ed/html5/thumbnails/16.jpg)
def get_helloer str_ext = "Hello" lambda do |who| puts "#{str_ext} #{who}!" endend
helloer = get_helloerhelloer.call('there')
![Page 17: Блоки, лямбды, замыкания](https://reader033.vdocuments.mx/reader033/viewer/2022052910/559c1d891a28abde298b45ed/html5/thumbnails/17.jpg)
В 1930-х годах Алонзо Чёрч ввёл лямбда-нотацию в своём исследовании "Лямбда-исчисление"
![Page 18: Блоки, лямбды, замыкания](https://reader033.vdocuments.mx/reader033/viewer/2022052910/559c1d891a28abde298b45ed/html5/thumbnails/18.jpg)
def get_helloer str_ext = "Hello" lambda do |who| puts "#{str_ext} #{who}!" endend
helloer = get_helloerhelloer.call('there')
![Page 19: Блоки, лямбды, замыкания](https://reader033.vdocuments.mx/reader033/viewer/2022052910/559c1d891a28abde298b45ed/html5/thumbnails/19.jpg)
rb_lambda_t
???
![Page 20: Блоки, лямбды, замыкания](https://reader033.vdocuments.mx/reader033/viewer/2022052910/559c1d891a28abde298b45ed/html5/thumbnails/20.jpg)
Стек
Куча
locals: str_ext rb_control_frame_t
Кадр стека get_helloer
"Hello"
RString
![Page 21: Блоки, лямбды, замыкания](https://reader033.vdocuments.mx/reader033/viewer/2022052910/559c1d891a28abde298b45ed/html5/thumbnails/21.jpg)
Стек
Куча
locals: str_ext rb_control_frame_t
Кадр стека get_helloer
str_extrb_block_t
iseq
EP
rb_proc_t
envval
is_lambda
rb_env_t
env
![Page 22: Блоки, лямбды, замыкания](https://reader033.vdocuments.mx/reader033/viewer/2022052910/559c1d891a28abde298b45ed/html5/thumbnails/22.jpg)
Стек
Куча
locals: str_ext rb_control_frame_t
Кадр стека внешнего кода
helloer
rb_proc_t
rb_env_t str_ext
![Page 23: Блоки, лямбды, замыкания](https://reader033.vdocuments.mx/reader033/viewer/2022052910/559c1d891a28abde298b45ed/html5/thumbnails/23.jpg)
Стек
Куча
locals: str_ext rb_control_frame_t
Кадр стека helloer.call
str_extrb_block_t
iseq
EP
rb_proc_t
envval
is_lambda
rb_env_t
env
argument: whoEP
![Page 24: Блоки, лямбды, замыкания](https://reader033.vdocuments.mx/reader033/viewer/2022052910/559c1d891a28abde298b45ed/html5/thumbnails/24.jpg)
def get_helloer str_ext = "Hello" res = lambda do |who| puts "#{str_ext} #{who}!" end str_ext = "Goodbye" resend
helloer = get_helloerhelloer.call('there')
![Page 25: Блоки, лямбды, замыкания](https://reader033.vdocuments.mx/reader033/viewer/2022052910/559c1d891a28abde298b45ed/html5/thumbnails/25.jpg)
def get_helloer str_ext = "Hello" res = lambda do |who| puts "#{str_ext} #{who}!" end str_ext = "Goodbye" resend
helloer = get_helloerhelloer.call('there')
Goodbye there!
![Page 26: Блоки, лямбды, замыкания](https://reader033.vdocuments.mx/reader033/viewer/2022052910/559c1d891a28abde298b45ed/html5/thumbnails/26.jpg)
Стек
Куча
locals: str_ext rb_control_frame_t
Кадр стека get_helloer
str_ext
rb_env_t
env
EP
![Page 27: Блоки, лямбды, замыкания](https://reader033.vdocuments.mx/reader033/viewer/2022052910/559c1d891a28abde298b45ed/html5/thumbnails/27.jpg)
501491
def create_counter(start) value = start { inc: ->{value+=1}, dec: ->{value-=1}, get: ->{value} }end
counter = create_counter(500)counter[:inc].callputs counter[:get].call #=> 50110.times { counter[:dec].call }puts counter[:get].call #=> 491
![Page 28: Блоки, лямбды, замыкания](https://reader033.vdocuments.mx/reader033/viewer/2022052910/559c1d891a28abde298b45ed/html5/thumbnails/28.jpg)
block 19659752 in 5.000587slambda 4574745 in 5.033561s
require 'benchmark/ips'
def do_with_block yieldend
def do_with_lambda(&block) block.callend
Benchmark.ips do |b| b.report 'block' do do_with_block { 1+1 } end b.report 'lambda' do do_with_lambda {1+1} endend
![Page 29: Блоки, лямбды, замыкания](https://reader033.vdocuments.mx/reader033/viewer/2022052910/559c1d891a28abde298b45ed/html5/thumbnails/29.jpg)
JRuby
_file_
RubyFixnum.times
block_0$RUBY$__file__DynamicScope
DynamicScopestr_ext
str_ext = "Hello"10.times do str = "world." puts "#{str_ext} #{str}"end
родитель
![Page 30: Блоки, лямбды, замыкания](https://reader033.vdocuments.mx/reader033/viewer/2022052910/559c1d891a28abde298b45ed/html5/thumbnails/30.jpg)
Rubinius
Integer.times
код блокаVariableScope
VariableScopestr_ext
str_ext = "Hello"10.times do str = "world." puts "#{str_ext} #{str}"end
код верхнего уровня
родитель
![Page 31: Блоки, лямбды, замыкания](https://reader033.vdocuments.mx/reader033/viewer/2022052910/559c1d891a28abde298b45ed/html5/thumbnails/31.jpg)