当前位置:  开发笔记 > 编程语言 > 正文

将方法作为参数传递给Ruby

如何解决《将方法作为参数传递给Ruby》经验,为你挑选了5个好方法。

我试图用Ruby搞得一团糟.因此,我尝试从"Programming Collective Intelligence"Ruby书中实现算法(在Python中给出).

在第8章中,作者将方法a作为参数传递.这似乎适用于Python,但不适用于Ruby.

我有这个方法

def gaussian(dist, sigma=10.0)
  foo
end

并希望用另一种方法调用它

def weightedknn(data, vec1, k = 5, weightf = gaussian)
  foo
  weight = weightf(dist)
  foo
end

我得到的只是一个错误

ArgumentError: wrong number of arguments (0 for 1)

Daniel Lucra.. 97

关于块和过程的注释是正确的,因为它们在Ruby中更常见.但是如果你愿意,你可以传递一个方法.你打电话method来获取方法并.call调用它:

def weightedknn( data, vec1, k = 5, weightf = method(:gaussian) )
  ...
  weight = weightf.call( dist )
  ...
end

这是有趣的.值得注意的是,在将方法名称转换为可调用符号时,只需调用一次`method(:)`.您可以将结果存储在变量或参数中,并将其传递给子函数,就像之后的任何其他变量一样... (3认同)

为了完成此操作,如果要传递在其他地方定义的方法,请执行“ SomewhereElse.method(:method_name)”。太酷了! (2认同)


Alex Wayne.. 91

你想要一个proc对象:

gaussian = Proc.new do |dist, *args|
  sigma = args.first || 10.0
  ...
end

def weightedknn(data, vec1, k = 5, weightf = gaussian)
  ...
  weight = weightf.call(dist)
  ...
end

请注意,您不能像这样在块声明中设置默认参数.因此,您需要使用splat并在proc代码中设置默认值.


或者,根据您所有这些的范围,可能更容易传递方法名称.

def weightedknn(data, vec1, k = 5, weightf = :gaussian)
  ...
  weight = self.send(weightf)
  ...
end

在这种情况下,您只是调用在对象上定义的方法,而不是传递完整的代码块.这取决于你如何组织这个你可能需要更换self.sendobject_that_has_the_these_math_methods.send


最后但并非最不重要的,你可以挂掉方法的块.

def weightedknn(data, vec1, k = 5)
  ...
  weight = 
    if block_given?
      yield(dist)
    else
      gaussian.call(dist)
    end
  end
  ...
end

weightedknn(foo, bar) do |dist|
  # square the dist
  dist * dist
end

但听起来你想要更多可重复使用的代码块.



1> Daniel Lucra..:

关于块和过程的注释是正确的,因为它们在Ruby中更常见.但是如果你愿意,你可以传递一个方法.你打电话method来获取方法并.call调用它:

def weightedknn( data, vec1, k = 5, weightf = method(:gaussian) )
  ...
  weight = weightf.call( dist )
  ...
end


这是有趣的.值得注意的是,在将方法名称转换为可调用符号时,只需调用一次`method(:)`.您可以将结果存储在变量或参数中,并将其传递给子函数,就像之后的任何其他变量一样...
为了完成此操作,如果要传递在其他地方定义的方法,请执行“ SomewhereElse.method(:method_name)”。太酷了!

2> Alex Wayne..:

你想要一个proc对象:

gaussian = Proc.new do |dist, *args|
  sigma = args.first || 10.0
  ...
end

def weightedknn(data, vec1, k = 5, weightf = gaussian)
  ...
  weight = weightf.call(dist)
  ...
end

请注意,您不能像这样在块声明中设置默认参数.因此,您需要使用splat并在proc代码中设置默认值.


或者,根据您所有这些的范围,可能更容易传递方法名称.

def weightedknn(data, vec1, k = 5, weightf = :gaussian)
  ...
  weight = self.send(weightf)
  ...
end

在这种情况下,您只是调用在对象上定义的方法,而不是传递完整的代码块.这取决于你如何组织这个你可能需要更换self.sendobject_that_has_the_these_math_methods.send


最后但并非最不重要的,你可以挂掉方法的块.

def weightedknn(data, vec1, k = 5)
  ...
  weight = 
    if block_given?
      yield(dist)
    else
      gaussian.call(dist)
    end
  end
  ...
end

weightedknn(foo, bar) do |dist|
  # square the dist
  dist * dist
end

但听起来你想要更多可重复使用的代码块.


另外,如果你想用send执行`foo.bar(a,b)`,那就是`foo.send(:bar,a,b)`.splat(*)运算符允许你执行`foo.send(:bar,*[a,b])`如果你发现你想要一个任意长度的参数数组 - 假设bar方法可以吸收它们

3> 小智..:

您可以通过方式将方法作为参数传递method(:function).贝娄一个非常简单的例子:

def double(a)
  return a * 2 
end
=> nil

def method_with_function_as_param( callback, number) 
  callback.call(number) 
end 
=> nil

method_with_function_as_param( method(:double) , 10 ) 
=> 20


我遇到了一个问题,一个范围更复杂的方法,最后想出怎么做,希望这可以帮助别人:如果你的方法是例如在另一个类中,你应该调用最后一行代码,如`method_with_function_as_param(Class .method(:method_name),...)`而不是`method(:Class.method_name)`

4> Chuck..:

正常的Ruby方法是使用块.

所以它会是这样的:

def weightedknn( data, vec1, k = 5 )
  foo
  weight = yield( dist )
  foo
end

使用如下:

weightenknn( data, vec1 ) { |dist| gaussian( dist ) }

这种模式在Ruby中广泛使用.



5> Giovanni Cap..:

您可以&Method方法实例上使用运算符将方法转换为块.

例:

def foo(arg)
  p arg
end

def bar(&block)
  p 'bar'
  block.call('foo')
end

bar(&method(:foo))

更多详情,请访问http://weblog.raganwald.com/2008/06/what-does-do-when-used-as-unary.html

推荐阅读
殉情放开那只小兔子
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有