我正在红宝石店练习实习。我期待的一个工作问题是重新实现一个可枚举的方法。
我正在尝试立即实现地图,我无法弄清楚如何实现没有给出块的情况。
class Array
def mapp()
out = []
if block_given?
self.each { |e| out << yield(e) }
else
<-- what goes here? -->
end
out
end
end
使用我当前的实现。如果我跑:
[1,2,3,4,5,6].mapp{|each| each+1} #returns => [2,3,4,5,6,7]
但是,我不确定如何获取未传入块的情况:
[1,2,3,4].mapp("cat") # should return => ["cat", "cat", "cat", "cat"]
如果有人能指出我正确的方向。我真的很感激。我尝试查看源代码,但似乎做的事情与我以前的做法截然不同。
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;
}
答案 0 :(得分:7)
我认为[1,2,3,4].mapp("cat")
代表[1,2,3,4].mapp{"cat"}
。
也就是说,没有块的map返回一个枚举器:
[1,2,3,4].map
=> #<Enumerator: [1, 2, 3, 4]:map>
这与to_enum
[1,2,3,4].to_enum
=> #<Enumerator: [1, 2, 3, 4]:each>
所以在你的代码中,你只想调用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
答案 1 :(得分:1)
return to_enum :mapp unless block_given?
应该足够了。
请参阅完全使用Ruby的Rubinius实现的地图实现:
https://github.com/rubinius/rubinius/blob/master/kernel/bootstrap/array19.rb
# -*- encoding: us-ascii -*-
class Array
# Creates a new Array from the return values of passing
# each element in self to the supplied block.
def map
return to_enum :map unless block_given?
out = Array.new size
i = @start
total = i + @total
tuple = @tuple
out_tuple = out.tuple
j = 0
while i < total
out_tuple[j] = yield tuple.at(i)
i += 1
j += 1
end
out
end
end
答案 2 :(得分:1)
使用rubinius,有一个ruby实现,尽可能用ruby编写。您可以查看可枚举的代码。#collect
有趣的是
之间的区别答案 3 :(得分:1)
class Array
def map!
return to_enum :map! unless block_given?
self.each_with_index { |e, index| self[index] = yield(e) }
end
end
答案 4 :(得分:-1)