【问题标题】:ruby block/procs and method call红宝石块/过程和方法调用
【发布时间】:2014-12-05 04:32:40
【问题描述】:

我正在尝试在这里了解块 { |s| puts s } 的需求:

  def accepts_hash( var )
    print "got: ", var.inspect # will print out what it received
  end

accepts_hash( { :arg1 => 'giving arg1', :argN => 'giving argN' } )  { |s| puts s } 

当我运行这段代码时,不管有没有{ |s| puts s }

输出仍然是相同的({ :arg1 => 'giving arg1', :argN => 'giving argN' })

谁能解释块{ |s| puts s }在这里做什么?

(来源:http://en.wikibooks.org/wiki/Ruby_Programming/Syntax/Method_Calls

【问题讨论】:

    标签: ruby methods block proc


    【解决方案1】:

    在你的方法调用{ |s| puts s } 之后的块在你告诉它之前什么都不做。如果您继续阅读页面,他们会进一步解释块 - 这是一个示例:

    def accepts_hash( var )
      print "got: ", var.inspect    # will print out what it received
      yield ' jenny from the block' # pass value back to block
    end
    
    accepts_hash( { :arg1 => 'giving arg1', :argN => 'giving argN' } )  { |s| puts s }
    
    => {:arg1=>"giving arg1", :argN=>"giving argN"} jenny from the block
    

    通过让出,我们可以返回并处理块 - 在这种情况下,s 代表我们要让出的字符串,' jenny from the block' 是它的值。

    块使 ruby​​ 更加灵活和声明性,允许您编写惯用和人类可读的代码。例如:

    3.times { p 'hello' } 
    => "hello"
    => "hello"
    => "hello"
    

    ruby 是一门华丽的语言 - 有关块和实际用法的更多信息:http://www.gotealeaf.com/blog/declarative-thinking-with-higher-order-functions-and-blocks

    【讨论】:

      【解决方案2】:

      让我清除您的疑问,在您的代码中,您将 Hash 作为参数传递给方法。

      def accepts_hash( var )
          print "got: ", var.inspect # will print out what it received
      end
      
      accepts_hash( { :arg1 => 'giving arg1', :argN => 'giving argN' } ) 
      

      { |s| puts s } 这不会被视为var 中的参数。

      { |s| puts s }一般用于获取hash的所有key和value。

      例如

      ab = {:arg1 => 'giving arg1', :argN => 'giving argN'}
      
      ab.each { |s| puts s }
      #Output: 
      argN # 1st key
      giving argN  # 1st key's value
      arg1 # 2nd key
      giving arg1 # 2nd key's value
      

      如果您只需要获取keysvalues,那么它也是可能的。喜欢:

      ab.each { |key, value| puts key } 
      => argN
         arg1
      

      在您的方法中,如果您只想访问传递的 Hash 的 keys 作为参数,那么,

      def accepts_hash( var )
              puts "Keys:=> ", var.keys # will take all keys of Hash
              puts "Values:=>", var.values # will take all values of Hash
      end
      
      accepts_hash( { :arg1 => 'giving arg1', :argN => 'giving argN' } )
      

      正如@lfender6445yielding 的描述,您可以通过使用split 方法对其应用的一些修改来查看{ |s| puts s } 块的效果..

      例如

      def accepts_hash( var )
        print "got: ", var.inspect   # inspect will print the whole object the way it gets
        yield ' pass value back to block'
      end
      
      accepts_hash( { :arg1 => 'giving arg1', :argN => 'giving argN' } )  { |s| puts s.split }
      Output => got: {:argN=>"giving argN", :arg1=>"giving arg1"}pass
      value
      back
      to
      block
      

      我希望这可以让你明白。如果你有任何疑问,请随时提问。

      【讨论】:

        【解决方案3】:

        我相信您提到的示例只是说明了如何将块传递给accepts_hash。该方法没有实现对块做任何事情,因此忽略它。

        如果你有这样的定义:

        def accepts_hash (var, &block)
        ...
          block.call
        end
        

        然后它需要一个显式的块参数并对其进行评估。这应该会给出不同的输出。

        请注意,所有 ruby​​ 方法都隐式接受块,这就是为什么您可以传递一个块,即使方法签名不需要它。

        您可以更改实现以检查是否给出了块并对其进行评估。

        例子:

        def accepts_hash(var)
          ...
          yield if block_given?
        end
        

        yield 关键字计算隐式传入的块。

        【讨论】:

          【解决方案4】:

          当您定义accepts_hash 时,您没有告诉它接受块参数。所以你的块目前被忽略了。要传入一个块,您需要在变量名之前使用& 符号作为参数。

          def accepts_hash( var, &blck )
            print "got: ", var.inspect # will print out what it received
            puts
            print "block: ", blck[] # will print out what it received
          end
          
          accepts_hash( { :arg1 => 'giving arg1', :argN => 'giving argN' } )  { 123 } 
           # got: {:arg1=>"giving arg1", :argN=>"giving argN"}
           # block: 123 => nil 
          

          您也可以使用 yield 来访问一个块。

          def accepts_hash( var )
            print "got: ", var.inspect # will print out what it received
            puts
            print "block: ", yield # will print out what it received
          end
          
          accepts_hash( { :arg1 => 'giving arg1', :argN => 'giving argN' } )  { 123 } 
           # got: {:arg1=>"giving arg1", :argN=>"giving argN"}
           # block: 123 => nil 
          

          相同的结果,不同的传递块的方式。

          【讨论】:

            猜你喜欢
            • 2019-06-18
            • 1970-01-01
            • 2015-03-21
            • 1970-01-01
            • 2011-02-28
            • 2013-03-19
            • 2010-09-08
            • 2023-04-07
            • 1970-01-01
            相关资源
            最近更新 更多