问题如下:
在类Range中写入todown的行为如下(使用block_given?和yield函数):
(3..5).todown {| i |打印“hi#{i}”} #prints hi5 hi4 hi3
(2 ... 7).todown #prints 65432
经过至少一个小时的谷歌搜索,我仍然无法解决这个问题。我已经达到了这个目的:
class Range
def todown
to_a.reverse.each do |i|
yield(i)
end
end
end
我不知道在哪里添加(2..7).todown
行来获取所需的结果。
答案 0 :(得分:2)
你有没有试过像:
(3..5).reverse_each { |i| print "hi#{i} " }
你也可以用以下方法修补Range:
class Range
def todown
reverse_each do |i|
if block_given?
yield i
else
print i
end
end
end
end
这样就可以了:
(3..5).todown { |i| print "hi#{i} " }
答案 1 :(得分:1)
你可以使用这样的东西,通过利用to_a
将范围变成数组,然后使用reverse_each
来产生是否给出了块。
否则,我们会打印出来。
class Range
def todown
reverse_each do |v|
yield v if block_given?
print v unless block_given?
end
end
end
答案 2 :(得分:0)
修改强>
我意识到问题只是一个练习,但是在修改Ruby的核心类时应该非常小心。 Here是讨论“货币修补”危险的许多文章之一,以及可能采取的措施,以最大限度地降低风险,或在核心类修补程序爆炸时使调试更容易。
我们现在有一个(有点争议的)替代品叫做“Refinements”。 Refinements是v2.0的实验性补充。它随后被修改并在v2.1中成为永久性的。这是它在这里的工作方式。
首先,我们refine
模块中的一个类:
module M
refine Range do
def todown
reverse_each do |i|
case block_given?
when true then yield(i)
else print i
end
end
puts
end
end
end
我们试一试:
(2...7).todown
#-> NoMethodError: undefined method `todown' for 2...7:Range
糟糕!我们已经创建了细化,但还没有激活它。为此,我们使用关键字using
:
using M
(2...7).todown
#-> 65432
(3..5).todown { |i| print "hi#{i} " }
#-> hi5 hi4 hi3
我在细化中添加了一个方法,但您可以添加,修改,重命名或删除现有的实例或类方法,添加常量等等。
最后一件事:改进在IRB中似乎不起作用。 的:潮] 强>
你可以这样做:
class Range
def todown
f,l = first,last
l -= 1 if exclude_end?
if block_given?
while l >= f
yield(l)
l -= 1
end
else
s = ''
while l >= f
s << l.to_s
l -= 1
end
puts(s)
end
end
end
(2...7).todown
#-> 65432
(3..5).todown { |i| print "hi#{i} " }
#-> hi5 hi4 hi3
虽然有点长,但你会发现Ruby的大多数内置方法(用Ruby编写,而不是用C语言编写)都以类似的方式构造,以尽可能减少对其他类中方法的依赖。