Ruby에서 메서드를 매개 변수로 전달
루비랑 좀 놀리려고요.그래서 저는 "프로그래밍 집단지성" 루비라는 책의 알고리즘(파이썬에서 제공)을 구현하려고 노력합니다.
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)
블록과 Procs에 대한 언급은 루비에서 더 일반적이라는 점에서 정확합니다.하지만 당신이 원한다면 방법을 통과할 수 있습니다.이 출호에게 하세요.method
과 법과방을 .call
그것을 부르는 말:
def weightedknn( data, vec1, k = 5, weightf = method(:gaussian) )
...
weight = weightf.call( dist )
...
end
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
그런 블록 선언에서는 기본 인수를 설정할 수 없습니다.따라서 스플랫을 사용하여 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
하지만 당신은 더 많은 재사용 가능한 코드 덩어리를 원할 것으로 보입니다.
할 수 .method(:function)
방법. 아래는 매우 간단한 예입니다.
디프 더블(a)* 2를 반환합니다.끝.=> 0 def method_with_function_as_param(콜백, 번호)callback.call(번호)끝.=> 0 method_with_function_as_param(method(:double), 10 )=> 20
일반적인 Ruby 방법은 블록을 사용하는 것입니다.
그래서 다음과 같은 것이는 다음과 같습니다.
def weightedknn(data, vec1, k = 5)
foo
weight = yield(dist)
foo
end
다음과 같이 사용됩니다.
weightedknn(data, vec1) { |dist| gaussian( dist ) }
이 패턴은 루비에서 많이 사용됩니다.
당신은 할 수 .&
의 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 에서 확인하십시오.
함수 개체의 메서드를 "호출"이라고 불러야 합니다.
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
Words 후에 다음 함수를 호출할 수 있습니다.
@contests = make_select_list Contest do |contest|
logged_admin? or contest.organizer == @current_user
end
선택 항목을 필터링할 필요가 없으면 다음 블록을 생략합니다.
@categories = make_select_list( Category ) # selects all categories
루비 블록의 힘은 여기까지입니다.
Proc 또는 메서드 호출과 유사하게 람다를 다음과 같이 전달할 수도 있습니다.weightf
매개 변수:
def main
gaussian = -> (params) {
...
}
weightedknn(data, vec1, k = 5, gaussian, params)
# Use symbol :gaussian if method exists instead
end
def weightedknn(data, vec1, k = 5, weightf, params)
...
weight = weightf.call(params)
...
end
또한 "eval"을 사용하여 메소드를 문자열 인수로 전달한 다음 다른 메소드로 간단히 평가할 수 있습니다.
언급URL : https://stackoverflow.com/questions/522720/passing-a-method-as-a-parameter-in-ruby
'programing' 카테고리의 다른 글
텍스트 편집 필드의 값 가져오기 (0) | 2023.06.02 |
---|---|
비트맵 개체에 이미지를 로드하는 동안 이상한 메모리 부족 문제가 발생했습니다. (0) | 2023.06.02 |
CLI를 사용하여 구성 요소를 삭제하는 가장 좋은 방법은 무엇입니까? (0) | 2023.06.02 |
AVP Player의 재생 상태 확인 (0) | 2023.06.02 |
Xcode - 다운로드할 수 있는 dSYM이 없습니다. (0) | 2023.06.02 |