I'm practicing for an internship interview at a ruby shop. One of the job questions I'm expecting is to reimplement an enumerable method.
I'm trying to implement map right now and I'm having trouble figuring out how to implement the case where a block is not given.
class Array
def mapp()
out = []
if block_given?
self.each { |e| out << yield(e) }
else
<-- what goes here? -->
end
out
end
end
Using my current implementation. If I run:
[1,2,3,4,5,6].mapp{|each| each+1} #returns => [2,3,4,5,6,7]
However, I'm not sure how to get cases where a block isn't passed in:
[1,2,3,4].mapp("cat") # should return => ["cat", "cat", "cat", "cat"]
If someone could point me in the right direction. I'd really appreciate it. I tried looking through the source code but it seems to do things very differently than what i'm used to.
static VALUE
enum_flat_map(VALUE obj)
{
VALUE ary;
RETURN_SIZED_ENUMERATOR(obj, 0, 0, enum_size);
ary = rb_ary_new();
rb_block_call(obj, id_each, 0, 0, flat_map_i, ary);
return ary;
}
The way the map method works in Ruby is, it takes an enumerable object, (i.e. the object you call it on), and a block. Then, for each of the elements in the enumerable, it executes the block, passing it the current element as an argument. The result of evaluating the block is then used to construct the resulting array.
In Ruby, we call an object enumerable when it describes a set of items and a method to loop over each of them. The built-in enumerables get their enumeration features by including the Enumerable module, which provides methods like #include? , #count , #map , #select and #uniq , amongst others.
What you are seeing is the & operator applied to a :symbol . In a method argument list, the & operator takes its operand, converts it to a Proc object if it isn't already (by calling to_proc on it) and passes it to the method as if a block had been used.
Ruby Map SyntaxFirst, you have an array, but it could also be a hash, or a range. Then you call map with a block. The block is this thing between brackets { ... } . Inside the block you say HOW you want to transform every element in the array.
I suppose that by [1,2,3,4].mapp("cat")
you mean [1,2,3,4].mapp{"cat"}
.
That said, map without a block returns an enumerator:
[1,2,3,4].map
=> #<Enumerator: [1, 2, 3, 4]:map>
That is the same output of to_enum
[1,2,3,4].to_enum
=> #<Enumerator: [1, 2, 3, 4]:each>
So in your code, you just want to call to_enum:
class Array
def mapp()
out = []
if block_given?
self.each { |e| out << yield(e) }
else
out = to_enum :mapp
end
out
end
end
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With