Написать в Ruby функцию, которая принимает блок, не так страшно, как может показаться на первый взгляд. В самом простом случае нужно знать про одно ключевое слово – yield
. Именно с его помощью происходит вызов блока:
def foo()
yield
end
# Передача блока, который не принимает аргументов
foo { puts 'code-basics for the brave' }
# => "code-basics for the brave"
# Или так
foo do
puts 'code-basics for the brave'
end
# => "code-basics for the brave"
Как видно из примера выше, мы не управляем блоком явно. yield
автоматически получает доступ к блоку и вызывает его. Количество вызовов yield
может быть любым. Каждый вызов работает, как независимый вызов блока:
def foo()
yield
yield
end
foo { puts 'Hello Hexlet' }
# => "Hello Hexlet"
# => "Hello Hexlet"
yield
можно воспринимать как вызов блока, который во многом ведет себя как обычная функция. Например, если блок возвращает результат, то его же вернет и yield
.
def foo()
yield
end
# Передача блока, который не принимает аргументов
# Блок возвращает строку
result = foo { 'code-basics for the brave' }
puts result
# => "code-basics for the brave"
Если блок содержит параметры, то они передаются в блок через yield
, как через вызов функции:
def foo(value)
yield(value)
end
# Параметр из определения функции переходит в блок через yield
foo('Hexlet') { |v| puts v }
# => "Hexlet"
И, собирая все вместе, так выглядит реализация map()
внутри:
// В виде функции, а не метода
def my_map(coll)
result = []
coll.each do |elem|
result << yield(elem)
end
result
end
my_map([1, 2, 3]) { |v| v * 2 }
# [2, 4, 6]
Реализуйте функцию my_filter()
, которая умеет фильтровать переданную на вход коллекцию по условию в блоке:
coll = [1, 2, 3]
my_filter(coll) { |v| v.even? } # [2]
my_filter(coll) { |v| v.odd? } # [1, 3]
# Примеры выше можно записать и так
# & – преобразует символ в блок и передаст его как блок
my_filter(coll, &:even?)
my_filter(coll, &:odd?)
Если вы зашли в тупик, то самое время задать вопрос в «Обсуждениях». Как правильно задать вопрос:
Тесты устроены таким образом, что они проверяют решение разными способами и на разных данных. Часто решение работает с одними входными данными, но не работает с другими. Чтобы разобраться с этим моментом, изучите вкладку «Тесты» и внимательно посмотрите на вывод ошибок, в котором есть подсказки.
Это нормально 🙆, в программировании одну задачу можно выполнить множеством способов. Если ваш код прошел проверку, то он соответствует условиям задачи.
В редких случаях бывает, что решение подогнано под тесты, но это видно сразу.
Создавать обучающие материалы, понятные для всех без исключения, довольно сложно. Мы очень стараемся, но всегда есть что улучшать. Если вы встретили материал, который вам непонятен, опишите проблему в «Обсуждениях». Идеально, если вы сформулируете непонятные моменты в виде вопросов. Обычно нам нужно несколько дней для внесения правок.
Кстати, вы тоже можете участвовать в улучшении курсов: внизу есть ссылка на исходный код уроков, который можно править прямо из браузера.
Привет! Я Тота и моя задача помочь в обучении. Чтобы активировать меня, нужно зарегистрироваться или залогиниться, если у вас уже есть аккаунт
Ваше упражнение проверяется по этим тестам
1# frozen_string_literal: true
2
3require 'test_helper'
4require_relative 'index'
5
6describe 'function' do
7 it 'should works' do
8 assert { my_filter([1, 2], &:even?) == [2] }
9 assert { my_filter([1, 2, 3, 4], &:even?) == [2, 4] }
10 assert { my_filter([1, 2, 3, 4], &:odd?) == [1, 3] }
11 end
12end
13
Решение учителя откроется через: