在 Class 中的方法中调用 Proc 时遇到问题

Having trouble calling a Proc within a Method within a Class

我正在努力调试我的问题;我正在尝试在方法中使用 Proc,所有方法都在 class 中。当我不输入 "class" 细节时,我的程序编译正常;但是,当我指定 class 名称时,会出现各种不同的错误。

注意:我在 CodeReview.StackExchange.com 上发布了这个问题,但那里是题外话; mods(?)建议我在这里问这个问题。

背景。 这是给我的提示,直接取自 pine.fm

Grandfather Clock. Write a method which takes a block and calls it once for each hour that has passed today. That way, if I were to pass in the block do puts 'DING!' end, it would chime (sort of) like a grandfather clock. Test your method out with a few different blocks (including the one I just gave you). Hint: You can use Time.now.hour to get the current hour. However, this returns a number between 0 and 23, so you will have to alter those numbers in order to get ordinary clock-face numbers (1 to 12).

有效代码:

def hourlyRing ring
    time = Time.now.hour%12;
    hour_set =[12, 1, 2, 3, 4, 5, 6, 7, 8 , 9 , 10, 11];
    (hour_set[time].to_i).times do 
        ring.call
    end
end

ring = Proc.new do 
    puts 'DING!'
end 

hourlyRing ring

它产生以下(正确,因为它是 4 p.m。这里)输出:

~$ ruby GrandfatherClock.rb
DING!
DING!
DING!
DING!

无效的代码:

class GrandfatherClock  

    def hourlyRing ring
        time = Time.now.hour%12;
        hour_set =[12, 1, 2, 3, 4, 5, 6, 7, 8 , 9 , 10, 11];
        (hour_set[time].to_i).times do 
            ring.call
        end
    end

    ring = Proc.new do 
        puts 'DING!'
    end 
end

# Here's where I try to call it:
ringtime = GrandfatherClock.new
ringtime.hourlyRing ring

谁能看到我的代码中的错误?以我的拙见,这是一个足够短的代码,但我不明白为什么它不能编译。也许我从根本上误解了 Procs 的某些内容,但我不明白到底是什么。提前谢谢你。

这是关于上下文的。
在第二个示例中,您将 ring proc 放在 class 内,因此当您实际调用 ringtime.hourlyRing ring 时,ring 未在该范围内定义。

您可以将代码更改为:

class GrandfatherClock  

    def hourlyRing ring
        time = Time.now.hour%12;
        hour_set =[12, 1, 2, 3, 4, 5, 6, 7, 8 , 9 , 10, 11];
        (hour_set[time].to_i).times do 
            ring.call
        end
    end
end

ring = Proc.new do 
   puts 'DING!'
end 

# Here's where I try to call it:
ringtime = GrandfatherClock.new
ringtime.hourlyRing ring

此外,问题陈述明确询问您有关块的问题, 所以 hourlyRing 应该是这样的:

def hourlyRing
    time = Time.now.hour%12;
    hour_set =[12, 1, 2, 3, 4, 5, 6, 7, 8 , 9 , 10, 11];
    (hour_set[time].to_i).times do 
        yield
    end
end

你可以这样称呼它:

hourlyRing { puts 'RING'}

 hourlyRing do
    puts 'RING'
 end

在第一个示例中,您已将 proc 分配给 class 之外的变量 ring,因此当您引用它时,变量 ring 在范围内(即可见) .

在第二个示例中,虽然您仍然将 proc 分配给名为 ring 的变量,但该变量现在已在 GrandfatherClock class 中声明,因此不再在 class.

之外可见

您可以创建一个 returns 过程的函数,而不是将过程分配给变量:

class GrandfatherClock
    def hourlyRing ring
        time = Time.now.hour % 12
        hour_set = [12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
        (hour_set[time].to_i).times do
            ring.call
        end
    end

    def ring
        Proc.new do
            puts 'DING!'
        end
    end
end

# Here's where I try to call it:
ringtime = GrandfatherClock.new
ringtime.hourlyRing ringtime.ring

请注意,您现在必须通过 class 的 ringtime 实例引用 ring

然而,这并不是问题描述真正要求的(我只是用它来说明发生了什么)。为了更符合问题描述,您需要在 hourlyRing 函数中使用 yield 代替 ring.call,然后在方法调用中传递一个块:

ringtime.hourlyRing do
    puts 'DING!'
end