Использование метода, который принимает блоки и может возвращать истинные или ложные значения - PullRequest
3 голосов
/ 01 июля 2019

Итак, я вернулся с другим вопросом!Я научился принимать аргументы с блоками, но теперь мне нужно разместить блок в моем методе (я думаю).

Вот что мне нужно сделать, это обобщенный метод reduce, в котором проходят следующие тесты:

describe 'my own reduce' do
  it "returns a running total when not given a starting point" do
    source_array = [1,2,3]
    expect(reduce(source_array){|memo, n| memo + n}).to eq(6)
  end

  it "returns a running total when given a starting point" do
    source_array = [1,2,3]
    starting_point = 100
    expect(reduce(source_array, starting_point){|memo, n| memo + n}).to eq(106)
  end

  it "returns true when all values are truthy" do
    source_array = [1, 2, true, "razmatazz"]
    expect(reduce(source_array){|memo, n| memo && n}).to be_truthy
  end

  it "returns false when any value is false" do
    source_array = [1, 2, true, "razmatazz", false]
    expect(reduce(source_array){|memo, n| memo && n}).to be_falsy
  end

  it "returns true when a truthy value is present" do
    source_array = [ false, nil, nil, nil, true]
    expect(reduce(source_array){|memo, n| memo || n}).to eq(true)
  end

  it "returns false when no truthy value is present" do
    source_array = [ false, nil, nil, nil]
    expect(reduce(source_array){|memo, n| memo && n}).to eq(false)
  end
end

Вот мой код:

def reduce(element1, starting_point = 0, &block)
  element1.reduce(starting_point, &block)
end

, который проходит 4 из 6 тестов.Но последняя часть требует проверки значений в source_array, и если они верны, верните истину или, если они верны, верните ложь.Я попытался вставить следующий блок вместе с методом reduce:

def reduce(element1, starting_point = 0, &block)
  element1.reduce(starting_point, &block){ |x, y| if x || y = true; p true; else p false; end}
end

Если вы посмотрите на тесты, вы увидите, что он пропустит один массив с 'true' и один с 'false' иМне нужно, чтобы он работал для всех 6 тестов.

Пожалуйста, любые объяснения мне очень помогли.

Ответы [ 3 ]

5 голосов
/ 01 июля 2019
  1. Если ваша задача - написать собственный reduce, не используйте Enumerable#reduce внутри. Вы можете использовать Enumerable#each или for / while loop
  2. Вы можете передать блок другому методу, как вы делаете это с method(arg1, arg2, &block).
  3. Вы можете позвонить в свой блок с помощью #call, например, block.call(arg1, arg2)
3 голосов
/ 01 июля 2019

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

Если вы не укажете starting_point, reduceбудет просто использовать первый элемент в качестве начального_точки :

def reduce(elements, starting_point = nil, &block)
  if starting_point.nil?
    elements.reduce(&block)
  else
    elements.reduce(starting_point, &block)
  end
end
2 голосов
/ 01 июля 2019

Я думаю, что при неудачном тесте должно быть указано starting_point.

  it "returns true when a truthy value is present" do
    source_array = [ false, nil, nil, nil, true]
    - expect(reduce(source_array){|memo, n| memo || n}).to eq(true)
    + expect(reduce(source_array, false){|memo, n| memo || n}).to eq(true)
  end

Значение || зависит от левой стороны. Integer#|| отличается от, например. FalseClass#||. Это разные методы.

...