16

这可能不是您应该在家尝试的东西,但出于某种原因,我尝试在 Ruby 中创建一组方法。

我首先定义了两种方法。

irb(main):001:0> def test1
irb(main):002:1>   puts "test!"
irb(main):003:1> end
=> nil
irb(main):004:0> def test2
irb(main):005:1>   puts "test2!"
irb(main):006:1> end
=> nil

当您尝试将其放入实际数组时,会发生奇怪的事情。它似乎运行这两种方法。

irb(main):007:0> array = [test1, test2]
test!
test2!
=> [nil, nil]

之后,数组为空。

irb(main):008:0> puts array


=> nil

有人可以向我解释为什么它运行这些方法吗?除此之外,整个练习真的需要驱魔人吗?

4

6 回答 6

26

您存储在数组中的是调用方法的结果,而不是方法本身。

def test1
  puts "foo!"
end

def test2
  puts "bar!"
end

您可以像这样存储对实际方法的引用:

> arr = [method(:test1), method(:test2)]
# => [#<Method: Object#test1>, #<Method: Object#test2>] 

稍后,您可以像这样调用引用的方法:

> arr.each {|m| m.call }
foo!
bar!
于 2012-12-19T10:11:12.807 回答
9

@alestanis 很好地解释了原因。如果您尝试存储方法,那么您可以按照 Lars Haugseth 所说的进行,或者您可以执行以下操作:

test1 = Proc.new { puts "test!" }
test2 = Proc.new { puts "test2!" }
a = [test1, test2]

这可能会使您的代码更具可读性。

这是一个irb运行。

1.9.3p194 :009 > test1 = Proc.new { puts "test!" }
 => #<Proc:0x00000002798a90@(irb):9> 
1.9.3p194 :010 > test2 = Proc.new { puts "test2!" }
 => #<Proc:0x00000002792988@(irb):10> 
1.9.3p194 :011 > a = [test1, test2]
 => [#<Proc:0x00000002798a90@(irb):9>, #<Proc:0x00000002792988@(irb):10>] 
于 2012-12-19T10:21:29.147 回答
1

如果你有一个square方法并且想要创建一个平方值为 2 和 4 的数组,你会写

array = [square(2), square(4)]

在这里,您正在做完全相同的事情,只是您的测试方法不返回任何内容,这就是为什么您的 finalarray看起来是空的(实际上,它包含[nil, nil])。

于 2012-12-19T09:16:16.217 回答
1

您的数组只包含两个 nil 值。我在评估时通过放置字符串来欺骗你。但是每个函数的返回值仍然是 nil。

于 2012-12-19T09:16:54.557 回答
1

您的代码运行这两种方法,因为当您说“test1”和“test2”时,您实际上是在调用这些方法——括号对于 ruby​​ 方法调用是可选的。

由于您的两个方法都只包含一个返回 nil 的“puts”,因此您的结果数组只是一个包含两个 nil 的数组。

于 2012-12-19T09:17:48.890 回答
-1

这是我的两便士的价值。在已经发布的解决方案的基础上,这是一个工作示例。对某些人来说可能很方便的是它包括方法参数和使用self(在实例化时指的是 PromotionalRules 类的实例)和符号数组,这很整洁 - 我从 Ruby docs on #send 方法在这里。希望这对某人有帮助!

class PromotionalRules
  PROMOTIONS = [:lavender_heart_promotion, :ten_percent_discount]

  def apply_promotions total, basket
    @total = total

    if PROMOTIONS.count > 0
      PROMOTIONS.each { |promotion| @total = self.send promotion, @total, basket }
    end

    @total.round(2)
  end

  def lavender_heart_promotion total, basket
    if two_or_more_lavender_hearts? basket
      basket.map { |item| total -= 0.75 if item == 001 }
    end
    total
  end

  def two_or_more_lavender_hearts? basket
    n = 0
    basket.each do |item|
      n += 1 if item == 001
    end
    n >= 2
  end

  def ten_percent_discount total, *arg
    if total > 60.00
      total = total - total/10
    end
    total
  end
end

感谢大家的帮助。我喜欢编码的开源性质——随着人们迭代彼此的解决方案,线程会变得越来越好!

于 2015-12-28T22:53:10.747 回答