Ruby: methods as array elements - how do they work?

前端 未结 6 1762
一向
一向 2021-02-19 05:58

This probably isn\'t something you should try at home, but for some reason or another I tried to create an array of methods in Ruby.

I started by defining two methods.

相关标签:
6条回答
  • 2021-02-19 06:39

    What you're storing in your array is the result of calling your methods, not the methods themselves.

    def test1
      puts "foo!"
    end
    
    def test2
      puts "bar!"
    end
    

    You can store references to the actual methods like this:

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

    Later, you can call the referenced methods like this:

    > arr.each {|m| m.call }
    foo!
    bar!
    
    0 讨论(0)
  • 2021-02-19 06:41

    @alestanis explained the reason well. If you were trying to store the methods, then you can do what Lars Haugseth says or you could do the folllowing:

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

    This may make your code much more readable.

    Here is an irb run.

    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>] 
    
    0 讨论(0)
  • 2021-02-19 06:41

    Your array never contains anything else than two nil values. I tricks you by putting the strings when evaluating. But the return value of each function still is nil.

    0 讨论(0)
  • 2021-02-19 06:44

    Here's my two-pennies worth. Building on the solutions already posted, this is an example of a working example. What might be handy for some here is that it includes method arguments and the use of self (which refers to the instance of the PromotionalRules class when it is instantiated) and the array of symbols, which is neat - I got that from the Ruby docs on the #send method here. Hope this helps someone!

    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
    

    Thanks to everyone for their help. I love the open-source nature of coding - threads just get better and better as people iterate over each other's solutions!

    0 讨论(0)
  • 2021-02-19 06:58

    If you had a square method and wanted to create an array with the square values of 2 and 4, you would write

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

    Here you are doing exactly the same thing, except that your test methods don't return anything and that's why your final array seems empty (actually, it contains [nil, nil]).

    0 讨论(0)
  • 2021-02-19 07:02

    Your code runs the two methods because you're actually calling the methods when you say "test1" and "test2" - parentheses are optional for ruby method calls.

    Since both of your methods just contain a "puts", which returns nil, your resulting array is just an array of two nils.

    0 讨论(0)
提交回复
热议问题