Ruby에서 map(&:method) 구문에 인수를 제공할 수 있습니까?
당신은 아마 다음과 같은 루비 속기에 익숙할 것입니다.a
배열임):
a.map(&:method)
예를 들어 irb에서 다음을 시도합니다.
>> a=[:a, 'a', 1, 1.0]
=> [:a, "a", 1, 1.0]
>> a.map(&:class)
=> [Symbol, String, Fixnum, Float]
구문a.map(&:class)
의 줄임말입니다.a.map {|x| x.class}
.
이 구문에 대한 자세한 내용은 "Ruby에서 map(&:name)은 무엇을 의미합니까?"에서 확인하십시오.
구문을 통해&:class
당신은 메소드 콜을 하고 있습니다.class
각 배열 요소에 대해.
제 질문은: 메소드 호출에 인수를 제공할 수 있습니까?만약 그렇다면, 어떻게?
예를 들어, 다음 구문을 변환하는 방법
a = [1,3,5,7,9]
a.map {|x| x + 2}
에게&:
구문?
나는 그것을 제안하는 것이 아닙니다.&:
구문이 더 좋습니다.저는 단지 사용하는 기계에 관심이 있을 뿐입니다.&:
인수가 있는 구문입니다.
당신도 알고 있을 겁니다.+
정수 클래스의 메서드입니다.irb에서 다음을 시도할 수 있습니다.
>> a=1
=> 1
>> a+(1)
=> 2
>> a.send(:+, 1)
=> 2
다음에 간단한 패치를 생성할 수 있습니다.Symbol
다음과 같이:
class Symbol
def with(*args, &block)
->(caller, *rest) { caller.send(self, *rest, *args, &block) }
end
end
이를 통해 다음과 같은 작업을 수행할 수 있습니다.
a = [1,3,5,7,9]
a.map(&:+.with(2))
# => [3, 5, 7, 9, 11]
하지만 여러 매개 변수를 전달하는 것과 같은 다른 멋진 일들도 많이 있습니다.
arr = ["abc", "babc", "great", "fruit"]
arr.map(&:center.with(20, '*'))
# => ["********abc*********", "********babc********", "*******great********", "*******fruit********"]
arr.map(&:[].with(1, 3))
# => ["bc", "abc", "rea", "rui"]
arr.map(&:[].with(/a(.*)/))
# => ["abc", "abc", "at", nil]
arr.map(&:[].with(/a(.*)/, 1))
# => ["bc", "bc", "t", nil]
그리고 함께 작업하기도 합니다.inject
두 개의 인수를 블록에 전달합니다.
%w(abecd ab cd).inject(&:gsub.with('cde'))
# => "cdeeecde"
또는 [짧은 손] 블록을 속기 블록으로 전달하는 것과 같은 매우 멋진 것:
[['0', '1'], ['2', '3']].map(&:map.with(&:to_i))
# => [[0, 1], [2, 3]]
[%w(a b), %w(c d)].map(&:inject.with(&:+))
# => ["ab", "cd"]
[(1..5), (6..10)].map(&:map.with(&:*.with(2)))
# => [[2, 4, 6, 8, 10], [12, 14, 16, 18, 20]]
@Arup Rakshit과 나눈 대화는 다음과 같습니다. 자세한 설명은 다음과 같습니다.
Ruby에서 map(&:method) 구문에 인수를 제공할 수 있습니까?
아래 의견에서 @amcaplan이 제안한 것처럼, 만약 당신이 이름을 바꾼다면, 당신은 더 짧은 구문을 만들 수 있습니다.with
하는 방법.call
이 경우 루비에는 이 특수 메서드에 대한 바로 가기가 내장되어 있습니다..()
.
따라서 위의 내용을 다음과 같이 사용할 수 있습니다.
class Symbol
def call(*args, &block)
->(caller, *rest) { caller.send(self, *rest, *args, &block) }
end
end
a = [1,3,5,7,9]
a.map(&:+.(2))
# => [3, 5, 7, 9, 11]
[(1..5), (6..10)].map(&:map.(&:*.(2)))
# => [[2, 4, 6, 8, 10], [12, 14, 16, 18, 20]]
여기 정교함을 사용하는 버전이 있습니다(글로벌 원숭이 패치보다 덜 촌스럽습니다).Symbol
):
module AmpWithArguments
refine Symbol do
def call(*args, &block)
->(caller, *rest) { caller.send(self, *rest, *args, &block) }
end
end
end
using AmpWithArguments
a = [1,3,5,7,9]
a.map(&:+.(2))
# => [3, 5, 7, 9, 11]
[(1..5), (6..10)].map(&:map.(&:*.(2)))
# => [[2, 4, 6, 8, 10], [12, 14, 16, 18, 20]]
당신의 예는 할 수 있습니다.a.map(&2.method(:+))
.
Arup-iMac:$ pry
[1] pry(main)> a = [1,3,5,7,9]
=> [1, 3, 5, 7, 9]
[2] pry(main)> a.map(&2.method(:+))
=> [3, 5, 7, 9, 11]
[3] pry(main)>
작동 방식은 다음과 같습니다.
[3] pry(main)> 2.method(:+)
=> #<Method: Fixnum#+>
[4] pry(main)> 2.method(:+).to_proc
=> #<Proc:0x000001030cb990 (lambda)>
[5] pry(main)> 2.method(:+).to_proc.call(1)
=> 3
2.method(:+)
개체를 제공합니다.그리고나서&
에2.method(:+)
실제로 통화 방법, 그것을 만드는 것.Proc
물건.그런 다음 Ruby에서 &: 연산자를 뭐라고 부릅니까?
당신이 링크한 게시물이 확인하듯이,a.map(&:class)
의 줄임말이 아닙니다.a.map {|x| x.class}
을 제외하고는a.map(&:class.to_proc)
.
즉,to_proc
다음에 오는 것은 무엇이든 호출됩니다.&
교환입니다.
그래서 당신은 그것을 직접 줄 수 있습니다.Proc
대신:
a.map(&(Proc.new {|x| x+2}))
나는 이것이 아마도 당신의 질문의 목적을 좌절시킬 것이라는 것을 알지만, 나는 그것을 우회할 다른 방법을 볼 수 없습니다. 당신이 어떤 방법을 부를 것인지를 지정하는 것이 아니라, 당신은 그것에 응답하는 것을 전달할 뿐입니다.to_proc
.
제 생각에는 두 가지 주장에만 적합한 열거형에 대한 다른 네이티브 옵션이 있습니다.학급.Enumerable
는 메서드 " 이법있습다니방다니▁method있▁the"를 사용합니다.with_object
그리고 나서 다른 것을 반환합니다.Enumerable
.
그래서 당신은 전화할 수 있습니다.&
각 항목과 개체를 인수로 사용하는 메서드에 대한 연산자입니다.
예:
a = [1,3,5,7,9]
a.to_enum.with_object(2).map(&:+) # => [3, 5, 7, 9, 11]
더 많은 논쟁을 원한다면 성공을 반복해야 하지만 제 생각에는 추악합니다.
a = [1,3,5,7,9]
a.to_enum.with_object(2).map(&:+).to_enum.with_object(5).map(&:+) # => [8, 10, 12, 14, 16]
단답: 아니요.
@rkon의 답변에 따라 다음과 같은 작업을 수행할 수도 있습니다.
a = [1,3,5,7,9]
a.map &->(_) { _ + 2 } # => [3, 5, 7, 9, 11]
인수로 필요한 모든 메서드가 배열의 요소인 경우 이 방법이 가장 간단한 방법일 수 있습니다.
def double(x)
x * 2
end
[1, 2, 3].map(&method(:double))
=> [2, 4, 6]
수용된 답변처럼 핵심 클래스를 직접 패치하는 대신 패싯 보석의 기능을 사용하는 것이 더 짧고 깨끗합니다.
require 'facets'
a = [1,3,5,7,9]
a.map &:+.(2)
아무도 사용에 대해 언급하지 않은 것이 놀랍습니다.curry
하지만, 이것은 루비 2.2.9 이후로 루비에 있었습니다.표준 Ruby 라이브러리를 사용하여 OP가 원하는 방식으로 수행할 수 있는 방법은 다음과 같습니다.
[1,3,5,7,9].map(&:+.to_proc.curry(2).call(11))
# => [12, 14, 16, 18, 20]
다에대배제합야니다해공열을음한에 .curry
통화 내용과 일치합니다. 통역사는 때문입니다.+
방법은 아직 참조합니다.이는 또한 의 모든 개체가 다음에 있을 때만 사용할 수 있음을 의미합니다.map
같은 성질을 가지런티를 가지다하지만 이런 식으로 사용하려고 한다면 문제가 되지 않을 것입니다.
잘모어요겠에 잘 모르겠습니다.Symbol#with
이미 게시되었으며, 상당히 단순화되었으며 잘 작동합니다.
class Symbol
def with(*args, &block)
lambda { |object| object.public_send(self, *args, &block) }
end
end
(으)로 사용)public_send
에 send
비공개 메소드 호출을 방지하기 위해서도caller
루비가 이미 사용하고 있어서 혼란스러웠습니다.)
언급URL : https://stackoverflow.com/questions/23695653/can-you-supply-arguments-to-the-mapmethod-syntax-in-ruby
'programing' 카테고리의 다른 글
텍스트 편집을 위한 첫 글자 대문자화 (0) | 2023.05.31 |
---|---|
루비의 "or"와 ||의 차이는 무엇입니까? (0) | 2023.05.31 |
레일에서의 OOO 설계:물건을 두는 곳 (0) | 2023.05.31 |
번들러로 보석 하나만 업데이트 (0) | 2023.05.31 |
Visual Studio 코드 cmd 오류: 이 시스템에서 실행 중인 스크립트가 사용되지 않도록 설정되었기 때문에 로드할 수 없습니다. (0) | 2023.05.31 |