Ruby에서 매개 변수로 메소드 전달
루비를 조금 엉망으로 만들려고합니다. 그래서 나는 책 "Programming Collective Intelligence"Ruby의 알고리즘 (Python으로 제공)을 구현합니다.
8 장에서 저자는 메소드를 전달합니다. 이것은 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)
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.send
를object_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
그러나 여기에 더 많은 가능한 코드 덩어리를 원하시는 것입니다.
블록과 Procs를 언급하는 주석은 Ruby에서 더 일반적이라는 점에서 언급합니다. 그러나 원하는 경우 메소드를 사용할 수 있습니다. 당신은 전화 method
방법을 찾고 .call
그것을 전화 :
def weightedknn( data, vec1, k = 5, weightf = method(:gaussian) )
...
weight = weightf.call( dist )
...
end
방법으로 매개 변수로 메소드를 방법으로 사용할 수 있습니다 method(:function)
. 다음은 매우 간단한 예입니다.
데프 더블 (a) * 2 반환 종료 => 없음 def method_with_function_as_param (콜백, 번호) callback.call (번호) 종료 => 없음 method_with_function_as_param (방법 (: double), 10) => 20
이를 수행하는 일반적인 Ruby 방법은 블록을 사용하는 것입니다.
따라서 다음과 같습니다.
def weightedknn( data, vec1, k = 5 )
foo
weight = yield( dist )
foo
end
그리고 다음과 같이 사용됩니다.
weightenknn( data, vec1 ) { |dist| gaussian( dist ) }
이 패턴은 Ruby에서 광범위하게 사용됩니다.
메서드 인스턴스 에서 &
연산자를 사용하여 메서드를 블록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에서
함수 객체의 "call"메소드를 호출해야합니다.
weight = weightf.call( dist )
편집 : 의견에 설명 된대로이 접근 방식은 잘못되었습니다. 정상적인 기능 대신 Procs를 사용하는 경우 작동합니다.
함수 내에서 명명 된 블록에 액세스하려면 앰퍼샌드를 사용하는 것이 좋습니다. 이 기사에 제공된 권장 사항에 따라 다음 과 같이 작성할 수 있습니다 (이것은 내 작업 프로그램의 실제 스크랩입니다).
# Returns a valid hash for html form select element, combined of all entities
# for the given +model+, where only id and name attributes are taken as
# values and keys correspondingly. Provide block returning boolean if you
# need to select only specific entities.
#
# * *Args* :
# - +model+ -> ORM interface for specific entities'
# - +&cond+ -> block {|x| boolean}, filtering entities upon iterations
# * *Returns* :
# - hash of {entity.id => entity.name}
#
def make_select_list( model, &cond )
cond ||= proc { true } # cond defaults to proc { true }
# Entities filtered by cond, followed by filtration by (id, name)
model.all.map do |x|
cond.( x ) ? { x.id => x.name } : {}
end.reduce Hash.new do |memo, e| memo.merge( e ) end
end
Afterwerds, 다음과 같이이 함수를 호출 할 수 있습니다.
@contests = make_select_list Contest do |contest|
logged_admin? or contest.organizer == @current_user
end
선택 항목을 필터링 할 필요가 없으면 블록을 생략하면됩니다.
@categories = make_select_list( Category ) # selects all categories
Ruby 블록의 힘을 위해 너무나 많이.
"eval"을 사용하고 메서드를 문자열 인수로 전달한 다음 다른 메서드에서 간단히 평가할 수도 있습니다.
참고 URL : https://stackoverflow.com/questions/522720/passing-a-method-as-a-parameter-in-ruby
'IT' 카테고리의 다른 글
한 축을 따라 numpy 배열에서 최대 요소의 보장을 얻는 방법 (0) | 2020.08.07 |
---|---|
.NET의 MemoryStream이 닫히지 메모리 누수가 발생하고 있습니까? (0) | 2020.08.07 |
파선 길이 획 길이 및 획 사이의 거리 제어 (0) | 2020.08.07 |
Sublime Text의 기본 글꼴은 무엇입니까? (0) | 2020.08.07 |
안드로이드 레이아웃 :이 태그와 그 하나는 대체 될 수 있습니다. (0) | 2020.08.07 |