Dynamic Ruby. Lesson #3: Blocks, procs and lambdas

Preview:

Citation preview

LESSON 3: BLOCK, PROC AND LAMBDA

DYNAMIC RUBY

BLOCKS

BLOCKS

BLOCK

BLOCKS

В других языках схожие синтаксические конструкции называют “замыкания”. В некотором смысле блоки ведут себя как анонимные методы.

BLOCKS

Нечто похожее на метод

▸ имеет свою локальную область видимости переменных;

▸ имеет возвращаемое значение;

▸ может принимать аргументы;

▸ Имеют обособленный контекст как в отношении переменных, так и возвращаемого значения (с некоторой спецификой);

▸ имеет доступ к переменным, которые были объявлены в том же контексте, в котором был описан блок;

▸ ключевое слово return не используется - в контексте main оно вызовет exception LocalJumpError, в контексте любой иной функции приведет к выходу из нее;

▸ при вызове можно передавать иное число аргументов, чем было объявлено;

▸ имеет отличительный синтаксис объявления;

Нечто непохожее на метод

BLOCKS

{ }

DO END

: более высокий приоритет

: более низкий приоритет

Синтаксически блоки описываются при помощи ключевых символов:

BLOCKS

YIELD

BLOCK_GIVEN?

: вызов блока внутри метода

: проверка на наличие передаваемого блока в методе

Прочие особенности синтаксиса блоков:

{ |PARAM| … } : синтаксис описания принимаемых блоком параметров

BLOCKS

Блоки передаются всегда последним параметром. В большинстве случаев эта передача происходит сразу по факту описания, но так же блок можно передать как процедурный объект (об этом позже).

BLOCKS

ITERATORS

ITERATORS

ITERATOR

ITERATORS

EACH, MAP, SELECT, FIND, TIMES…

Так вот, многие из итераторов вам уже должны быть знакомы:

Все они работают с блоками.

ITERATORS

ITERATORS

Напишем собственный итератор:

PROCS

PROCS

PROC

PROCS

В чем смысл такого представления? В том, что теперь блок кода не подвязан к вызову метода yield и не обременен соответствующими ограничениями.

PROCS

PROCS

Как мы видим, одно из ключевых отличий блока от прока в том, что последний легко передавать как параметр.На самом деле, конкретный код модифицировать, чтобы передача блока как параметра все же состоялась.

PROCS

PROCS

Впрочем, это все равно не отменяет концептуальных ограничений блока.

С методом может быть связан только один блок и его нельзя присвоить переменной.

PROCS

Зато все виды процедурных объектов могут вызываться неявно.

Для этого достаточно указать в описании метода, который будет вызывать proс, псевдоаргумент, начинающийся с &.

PROCS

PROCS

Любой объект, реализующий метод to_proc и возвращающий процедурный объект, может быть передан методу как псевдоаргумент.

PROCS

PROCS

Существует синтаксический сахар, который позволяет передавать вместо блока просто символ.

Таким образом будет определен блок, в котором к аргументу блока будет вызываться одноименный с символом метод.

PROCS

LAMBDAS

LAMBDAS

LAMBDA

LAMBDAS

Proc

▸ return прерывает выполнение метода, в котором описан proc;

▸ не требует строгого соответствия аргументов;

▸ return прерывает выполнение самой lambda, возвращаясь в метод, в котором была описана lambda;

▸ требует строгого соответствия аргументов;

Lambda

LAMBDAS

Их синтаксис, как и представление, тоже отличаются:

LAMBDAS

У lambda есть еще один дополнительный вариант записи:

Ruby style guide рекомендует такой вид записи для однострочных лямбд.

BLOCKS, PROCS AND LAMBDAS

REFERENCES

▸ http://nashbridges.me/blocks-in-ruby

▸ http://nashbridges.me/procs-and-lambdas

▸ http://www.skorks.com/2013/04/ruby-ampersand-parameter-demystified/

▸ http://awaxman11.github.io/blog/2013/08/05/what-is-the-difference-between-a-block/

THANK YOU!

Alex Mikitenko nonkor@gmail.com https://github.com/nonkor

TO BE CONTINUED…