I was implementing my own enumerable method using Ruby when I reach my_any? method. It doesn't pass some cases
my_any? works for some of the cases but others don't work
module Enumerable
def my_each
i = 0
while i < size
yield self[i]
i += 1
end
end
def my_any?
if block_given?
my_each {|item| return true if yield item}
end
false
end
end
The below test cases are the require output
Test case 1
[4,8,true,18].my_any? # => true
test case 2
[2,nil,5,true].my_any? # => true
test case 3
[nil,nil,nil,false].my_any? # => false
test case 4
[nil,nil,nil].my_any? # => false # But my_any? fails this condition
Any Idea please
def my_any?
if block_given?
my_each {|item| return true if yield item}
end
false
end
This method is immediately checking if it was called with a block and, if not, returns false. For example, [].my_any? will return false for block_given? while [].my_any? { true } will return true. None of your examples are passing a block, so they will always skip the if and return false.
The correct behavior of any? should be this: if a block is given, yield the value to it to determine if it satisfies the condition; if a block is not given, just check if the value is truthy.
def my_any?
my_each do |item|
if block_given?
return true if yield item
else
return true if item
end
end
false
end
or more succinctly
def my_any?
my_each {|item| return true if block_given? ? yield(item) : item }
false
end
Related
Here's my code:
class Dictionary
def entries
#entries ||= {}
end
def add(hash)
if hash.class == Hash
hash.each_pair do |k, v|
entries[k] = v
end
else
makehash = {hash => nil}
self.add(makehash)
end
#entries = entries
end
def keywords
#entries.keys
end
def include?(k)
if #entries == nil
false
elsif self.keywords.include?(k)
true
else
false
end
end
end
And here's the test I'm running it against:
require 'dictionary'
describe Dictionary do
before do
#d = Dictionary.new
end
it 'can check whether a given keyword exists' do
#d.include?('fish').should be_false
end
Now, that test will fail. However, if I change it to
it 'can check whether a given keyword exists' do
#d.include?('fish').should == false
end
then it passes.
How can I change my code so that should be_false passes instead of should == false? Thanks.
be_false matches falsey values (nil and false) and
be_true matches truthy values (other than nil or false)
From Rspec > 3.0,
be_false is renamed to be_falsey and
be_true is renamed to be_truthy
If you want to exactly match false, you should use
obj.should eq false
See the Documentation for more info about 'be' matchers
This question already has answers here:
expected true to respond to true?
(2 answers)
Closed 8 years ago.
Here's the spec:
it 'can check whether a given keyword exists' do
#d.include?('fish').should be_false
end
Here's my method:
def include?(k)
#entries.each_key do |n|
if (n==k)
return true
end
end
return false
end
If I do, say:
puts myd.include?('fish')
console prints false (correctly)
But the spec fails with:
Failure/Error: #d.include?('fish').should be_false
expected false to respond to `false?`
And I do not know why. Been working on this for a day now and completely stumped...
Here's the whole thing:
class Dictionary
attr_accessor :entries, :keywords
def initialize
#entries={}
end
def add(entry)
if entry.class==Hash
#entries.merge!(entry)
elsif entry.class==String
h={entry => nil}
#entries.merge!(h)
end
end
def keywords
#entries.keys.sort
end
def include?(k)
#entries.each_key do |n|
if (n==k)
return true
end
end
return false
end
def find(term)
results={}
#entries.each_key do |n|
if (n.include? term)
results.merge!(n => #entries[n])
end
end
if (results.length)
return results
end
return false
end
def printable
str=""
sortedentries = #entries.sort_by { |k, v| k}
str=sortedentries.map{ |k, v| "[#{k}] \"#{v}\"\n" }.join
return str
end
end
Rspec's magic method is biting you here. The hint is in the error:
expected false to respond to `false?
If the thing you are testing does not have a method false? you cannot run be_false. e.g. nil.nil? can be ran, so then nil.should be_nil is a valid test. But nil.admin? is not runnable, hence nil.should be_admin is not a valid test.
Instead of should be_false consider using should equal false.
I have a method that accepts a method as an argument:
def acceptor_method(received_method)
an_arry.each do |attr|
received_method if some_condition
end
end
This works well if all the received_method does is run through some code:
def some_method
do_something
end
Which is the equivalent of:
def acceptor_method(received_method)
an_arry.each do |attr|
do_something if some_condition
end
end
But what if I want the received_method to break the loop and return a value, as with:
def acceptor_method(received_method)
an_arry.each do |attr|
return true if some_condition
end
end
Unfortunately, this doesn't work:
def some_method
return true
end
As it only returns true for some method, not for acceptor_method--which continues to play through the loop.
So is there a way to send a method that when run is the equivalent of return true?
def acceptor_method
[1, 2, 3, 4].each do |attr|
ret = yield attr
puts attr
end
end
test = acceptor_method do |attr|
break 'test' if attr == 3
end
puts test
outputs:
1
2
test
You can do this using blocks rather than methods. See How can I return something early from a block?
Basically if you have a block with break value and yield to it, the function will return value. Unfortunately I don't see a way to do this using methods, since Ruby really doesn't like having break outside of a block or loop.
I have code like the following (truncated/paraphrased for readability)
def board_check?
#board.each {|row| check_row_for_truth_conditions(row)}
end
def check_row_for_truth_conditions(row)
return true if row.include("foo")
false
end
Right now the implicit return of that each iterator is always the collection it is iterating over. ie; I get the array back, not true or false. If I don't refactor and do something like the following, it works as expected. However I use the check_row_for_truth_conditions in many places (and it is much longer), so would like to refactor it out
def board_check?
#board.each do |row|
return true if row.include("foo")
false
end
end
The return value of the block passed to each (false) is thrown away. The explicit return works because that returns from the method, not the block. You instead want:
def board_check?
#board.each do |row|
return true if row.include("foo")
end
return false
end
But really you want to use any?:
def board_check?
#board.any? do |row|
row.include("foo") # or perhaps check_row_for_truth_conditions(row)
end
end
Also, your check_row_for_truth_conditions can be simplified to just this:
def check_row_for_truth_conditions(row)
row.include("foo")
end
No need for the explicit return true/false.
One option is:
def board_check?
#board.any? {|row| row.include("foo") }
end
I want this code to define two methods, nilguard and falseguard, which guard against nil and false values.
Object.class_eval do
#list = [false, nil]
#list.each do |i|
define_method :"#{i}guard" do |other|
if self == i
return other
else
return self
end
end
end
end
For some reason, it only defines falseguard, which works fine. Why is this, why isn't it defining the other method?
nil.to_s == '', so your second method will just be called guard. You might want to use something like this instead:
#list = { false: false, nil: nil }
#list.each do |s, i|
define_method "#{s}guard" do |other|
# ...