所以我在一个网站上发现了这个测验,我很高兴用我新获得的Ruby技能解决这个问题(CodeAcademy,尚未完成)。
我想要做的是创建一个包含100个条目的数组,所有条目都设置为“打开”。然后,我计划创建一个包含for循环的方法,该循环遍历数组的每个第n个条目,并根据之前的内容将其更改为“open”或“closed”。在for循环中,n应该从1增加到100。
到目前为止我所拥有的是:
change_state = Proc.new { |element| element == "open" ? element = "closed" : element = "open" }
def janitor(array,n)
for i in 1..n
array.each { |element| if array.index(element) % i == 0 then element.change_state end }
end
end
lockers = [*1..100]
lockers = lockers.map{ |element| element = "closed" }
result = janitor(lockers,100)
尝试执行时收到错误消息:
undefined method `change_state' for "closed":String (NoMethodError)
有人知道这里有什么问题吗?我觉得我在当前数组元素上错误地调用了“change_state”过程。
如果你知道测验,请不要剧透!
答案 0 :(得分:3)
当您实现change_state
时,它不是任何类的方法,并且绝对不会附加到数组的任何单个元素,尽管您使用相同的变量名element
。因此,您无法将其称为element.change_state
。
相反,它是一个指向Proc
对象的变量。
要调用Proc
对象中的代码,您可以使用call
方法和proc_obj.call( params )
之类的语法 - 在您的情况下change_state.call( element )
如果您刚刚接受该更改,则错误消息将更改为:
NameError: undefined local variable or method `change_state' for main:Object
那是因为change_state
变量不在方法范围内,以便被调用。有很多方法可以使它可用。一种选择是将其作为参数传递,因此您对janitor的定义变为
def janitor(array,n,state_proc)
(在您的例程中使用变量名state_proc
而不是change_state
- 我建议您更改名称以避免让自己感到困惑)
然后您可以这样称呼它:
result = janitor(lockers,100,change_state)
尽管您的示例并不真正需要这种结构,但这是Ruby代码可以提供通用“外部”功能的一种方式 - 比如说,通过数组的元素 - 并让该代码的用户提供一个小的内部自定义部分。实现与示例相同结果的更常见方法是使用Ruby块和yield
方法,但Proc
也有其用途,因为您可以将它们视为数据和代码 - 所以你可以传递它们,将它们放入哈希或数组中以决定调用哪一个等。
您的代码中可能还有其他问题需要解决,但这是问题中错误消息的原因。