Как воссоздать любое? метод в Ruby

Я пытаюсь воссоздать перечислимый модуль в Ruby. Я готов к любому? метод и не могу вернуть истину или ложь. Вместо этого каждый элемент массива возвращается 1 к 1 .. Вот мой код:

def my_any?
  return self.to enum unless block_given?
  self.each do |i|
    return true if i == yield(i)
  end
end

nums = [3,5,7,3,6,10,20,16]

puts nums.my_any?{|x|x==6}

Есть идеи, где я ошибаюсь?

Пошаговое руководство по созданию собственного Slackbot: От установки до развертывания
Пошаговое руководство по созданию собственного Slackbot: От установки до развертывания
Шаг 1: Создание приложения Slack Чтобы создать Slackbot, вам необходимо создать приложение Slack. Войдите в свою учетную запись Slack и перейдите на...
1
0
163
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

У вас есть две проблемы:

  1. Вам не хватает return false, если цикл не может найти совпадение. В настоящее время, когда он не соответствует, он будет возвращать значение из each, что вы и видите.
  2. В настоящее время он всегда терпит неудачу, потому что, хотя ваша конструкция return true if cond верна, условное выражение any? не является i == yield(i): у вас слишком много сравнений. Вам нужен только yield(i).

(Бит to enum тоже звучит не так, но это не связано с вашим вопросом.)

Внесение этих изменений в ваш код:

def my_any?
  # FIXME: return self.to enum unless block_given?
  self.each do |i|
    return true if yield i
  end
  false
end

Нет необходимости в self

Stefan 10.08.2018 15:24

@Stefan, в нашей скромной жизни всегда есть потребность в self :)

Aleksei Matiushkin 10.08.2018 20:54

У вас есть три проблемы с вашим кодом: вы должны вернуть перечислитель для этого метода при вызове без блока, вы должны проверить, что именно возвращает yield, и вы должны явно вернуть false в случае неудачи:

def my_any?
  return to_enum(:my_any?) unless block_given?
  each { |i| return true if yield(i) }
  false
end

nums = [3,5,7,3,6,10,20,16]

puts nums.my_any? { |x| x == 6 }
#⇒ true
lazy = nums.my_any?
lazy.each { |x| x == 6 }
#⇒ true

Или лучше использовать break:

def my_any?
  return to_enum(:my_any?) unless block_given?

  each { |i| break true if yield(i) } == true
end

Я не могу сосчитать, когда спрашивающий хотел воссоздать метод Enumerable, а ответы не учитывались для случая, когда метод не имеет блока и возвращается перечислитель. Приятно видеть, что вы рассмотрели этот очень важный аспект вопроса.

Cary Swoveland 10.08.2018 20:05

Ой! Enumerable # любой? возвращает только true или false, но не перечислитель. Странный. Думаю, можно пожелать написать, например, nums.any?.with_index { |x,i| x <= 6 && i >2 }.

Cary Swoveland 10.08.2018 20:13

@CarySwoveland Enumerable#any? относительно молод, сейчас люди не такие разборчивые :)

Aleksei Matiushkin 10.08.2018 20:49

Другие вопросы по теме