Ruby 将一个函数传递给另一个函数并调用它

Ruby 将一个函数传递给另一个函数并调用它,ruby,Ruby,Ruby中的函数不是第一类对象,但我希望能够将对函数的引用传递到另一个函数中并执行它。如何做到这一点 例如: def run_a_function_twice(my_function) # Call the function once. # Call the function again. end def say_hello puts "HI!" end run_a_function_twice(say_hello) 我正在阅读文档,但不确定是否应该尝试lambda、procs

Ruby中的函数不是第一类对象,但我希望能够将对函数的引用传递到另一个函数中并执行它。如何做到这一点

例如:

def run_a_function_twice(my_function)
  # Call the function once.
  # Call the function again.
end

def say_hello
  puts "HI!"
end

run_a_function_twice(say_hello)

我正在阅读文档,但不确定是否应该尝试lambda、procs或call(我只熟悉其他语言调用的概念)

这是通过通过块传递方法来完成的。这有几个语法

第一个语法使用yield,看起来像这样

def method1
  puts "This is from method 1"
  yield
end

def method2
  puts "This is from method 2"
end

method1(){method2}
以上将输出

这来自方法1

这来自方法2


第二个选项使用以下语法

def method1(&block)
  puts "This is from method 1"
  block.call
end

def method2
  puts "This is from method 2"
end

method1(){method2}
输出结果相同。通常,首选
yield
语法,因为它更简洁,但也因为它的平均速度约为
块.call
表示法的5倍


第三个选项是使用
send
语法,如下所示

def method1(method_name_string)
  puts "This is from method 1"
  send(method_name_string, 1, 2)
end

def method2(a,b)
  puts "This is from method 2" + a.to_s + ' ' + b.to_s
end

method1("method2")

您还可以使用
lambda
Proc.new

def method1(lmb)
  puts "This is from method 1"
  block.call "A string"
end

foo = lambda do |x|
  puts x
end

method1(foo)
在这种情况下,你会看到

这来自方法1


字符串

这是通过通过块传递方法来完成的。这有几个语法

第一个语法使用yield,看起来像这样

def method1
  puts "This is from method 1"
  yield
end

def method2
  puts "This is from method 2"
end

method1(){method2}
以上将输出

这来自方法1

这来自方法2


第二个选项使用以下语法

def method1(&block)
  puts "This is from method 1"
  block.call
end

def method2
  puts "This is from method 2"
end

method1(){method2}
输出结果相同。通常,首选
yield
语法,因为它更简洁,但也因为它的平均速度约为
块.call
表示法的5倍


第三个选项是使用
send
语法,如下所示

def method1(method_name_string)
  puts "This is from method 1"
  send(method_name_string, 1, 2)
end

def method2(a,b)
  puts "This is from method 2" + a.to_s + ' ' + b.to_s
end

method1("method2")

您还可以使用
lambda
Proc.new

def method1(lmb)
  puts "This is from method 1"
  block.call "A string"
end

foo = lambda do |x|
  puts x
end

method1(foo)
在这种情况下,你会看到

这来自方法1


字符串

您可以通过两种不同的方式执行此操作:

  • 传递方法的名称(通常作为符号,但字符串也可以):

    这取决于
    say_hello
    run_a_method_两次在同一范围内可用,例如,如果它们都是同一类上的实例方法。如果在另一个对象上定义了
    say\u hello
    ,您将执行例如
    some\u obj.send(:say\u hello)

    您可以通过在方法名称后将参数指定给
    send
    ,为方法提供参数,例如
    jordan.send(:say_hello,“Donny”)

  • 使用块:

    def yield_to_a_block_twice
      yield
      yield
    end
    
    yield_to_a_block_twice { say_hello }
    
    这种语法也适用:

    def call_a_block_twice(&block)
      block.call
      block.call
    end
    
    如果可能,您应该使用
    yield
    (速度更快),但有时需要能够按名称引用块(例如,如果需要将其传递给另一个方法,或从另一个块中调用它),在这种情况下,需要将其设为命名参数(即
    def meth(arg1、arg2和block_name)

    block、Proc和lambda之间的区别对Ruby新手来说是一个挑战,关于它们的文章很多,只有谷歌的“Ruby block Proc lambda”一文


  • 您可以通过两种不同的方式执行此操作:

  • 传递方法的名称(通常作为符号,但字符串也可以):

    这取决于
    say_hello
    run_a_method_两次在同一范围内可用,例如,如果它们都是同一类上的实例方法。如果在另一个对象上定义了
    say\u hello
    ,您将执行例如
    some\u obj.send(:say\u hello)

    您可以通过在方法名称后将参数指定给
    send
    ,为方法提供参数,例如
    jordan.send(:say_hello,“Donny”)

  • 使用块:

    def yield_to_a_block_twice
      yield
      yield
    end
    
    yield_to_a_block_twice { say_hello }
    
    这种语法也适用:

    def call_a_block_twice(&block)
      block.call
      block.call
    end
    
    如果可能,您应该使用
    yield
    (速度更快),但有时需要能够按名称引用块(例如,如果需要将其传递给另一个方法,或从另一个块中调用它),在这种情况下,需要将其设为命名参数(即
    def meth(arg1、arg2和block_name)

    block、Proc和lambda之间的区别对Ruby新手来说是一个挑战,关于它们的文章很多,只有谷歌的“Ruby block Proc lambda”一文


  • 通常在ruby中有块的概念,如果愿意的话,块就是匿名方法(闭包)

    可以将块传递给任何方法。然后,该方法可以使用
    yield
    (与
    block\u给定?
    )调用该方法/块,或使用
    运算符将其引用到变量。后者可用于存储引用或将其传递给另一个方法

    def call_it_twice
      2.times {|i| yield(i) }
    end
    
    call_it_twice { puts "hello" }
    # hello
    # hello
    
    call_it_twice {|i| puts "hello #{i}" }
    # hello 0
    # hello 1
    
    def call_it_thrice &block
      call_it_twice(&block)
      block.call(2)
    end
    
    call_it_thrice {|i| puts "hello #{i}" }
    # hello 0
    # hello 1
    # hello 2
    
    您也可以传递一个literal方法,但这并不常见

    class Foo
      def hello
        puts "world"
      end
    end
    
    Foo.instance_methods(:hello)
    # #<UnboundMethod: Foo#hello>
    
    Foo.instance_method(:hello).call
    # NoMethodError: undefined method `call' for #<UnboundMethod: Foo#hello>
    
    Foo.instance_method(:hello).bind(Foo.new).call
    # world
    
    
    Foo.new.method(:hello)
    # #<Method: Foo#hello>
    
    Foo.new.method(:hello).call
    # world
    
    class-Foo
    你好
    “世界”
    结束
    结束
    实例_方法(:hello)
    # #
    实例\方法(:hello).call
    #NoMethodError:的未定义方法“调用”#
    实例\方法(:hello).bind(Foo.new).call
    #世界
    Foo.new.method(:hello)
    # #
    Foo.new.method(:hello.call)
    #世界
    
    一个常见的方法是将
    array.map{x | x.downcase}
    写成
    array.map(&:downcase)
    (这是
    到_proc
    的快捷方式,所以它是
    array.map(&:downcase.to _proc)


    相对未知的是:
    数组。每个{x | puts x}
    都与
    数组相同。每个(&method(:puts))
    通常在ruby中有块的概念,如果愿意的话,它们是匿名方法(闭包)

    可以将块传递给任何方法。然后,该方法可以使用
    yield
    (与
    block\u给定?
    )调用该方法/块,或使用
    运算符将其引用到变量。后者可用于存储引用或将其传递给另一个方法

    def call_it_twice
      2.times {|i| yield(i) }
    end
    
    call_it_twice { puts "hello" }
    # hello
    # hello
    
    call_it_twice {|i| puts "hello #{i}" }
    # hello 0
    # hello 1
    
    def call_it_thrice &block
      call_it_twice(&block)
      block.call(2)
    end
    
    call_it_thrice {|i| puts "hello #{i}" }
    # hello 0
    # hello 1
    # hello 2
    
    您也可以传递一个literal方法,但这并不常见

    class Foo
      def hello
        puts "world"
      end
    end
    
    Foo.instance_methods(:hello)
    # #<UnboundMethod: Foo#hello>
    
    Foo.instance_method(:hello).call
    # NoMethodError: undefined method `call' for #<UnboundMethod: Foo#hello>
    
    Foo.instance_method(:hello).bind(Foo.new).call
    # world
    
    
    Foo.new.method(:hello)
    # #<Method: Foo#hello>
    
    Foo.new.method(:hello).call
    # world
    
    class-Foo