def tag_names
@tag_names || tags.map(&:name).join(' ')
end
무엇은하지 (&:name)
에 map(&:name)
평균?
def tag_names
@tag_names || tags.map(&:name).join(' ')
end
무엇은하지 (&:name)
에 map(&:name)
평균?
답변:
속기입니다 tags.map(&:name.to_proc).join(' ')
경우 foo
A의 객체 인 to_proc
방법은, 당신은 같은 방법으로 전달할 수 있습니다 &foo
호출, foo.to_proc
및 방법의 블록으로 사용하는 것이.
이 Symbol#to_proc
메소드는 원래 ActiveSupport에 의해 추가되었지만 Ruby 1.8.7에 통합되었습니다. 이것이 그 구현입니다.
class Symbol
def to_proc
Proc.new do |obj, *args|
obj.send self, *args
end
end
end
&
, 즉tags.map(&:name.to_proc).join(' ')
많은 사람들에게 알려지지 않은 또 다른 멋진 속기는
array.each(&method(:foo))
이것은 속기입니다
array.each { |element| foo(element) }
호출 하여 메소드 를 나타내는 객체를 method(:foo)
가져 와서 Method
객체 를로 변환 하는 메소드 가 있음을 나타냅니다 .self
foo
&
to_proc
Proc
포인트없는 스타일 로 작업 할 때 매우 유용합니다 . 예를 들어 배열에 문자열과 같은 문자열이 있는지 확인하는 것입니다 "foo"
. 일반적인 방법이 있습니다.
["bar", "baz", "foo"].any? { |str| str == "foo" }
그리고 포인트없는 방법이 있습니다.
["bar", "baz", "foo"].any?(&"foo".method(:==))
가장 좋은 방법은 가장 읽기 쉬운 방법이어야합니다.
array.each{|e| foo(e)}
어쨌든 :-) +1 어쨌든
&method
?를 사용하여 다른 클래스의 생성자를 매핑 할 수 있습니까?
[1,2,3].map(&Array.method(:new))
앰퍼샌드와 #to_proc
매직은 Symbol뿐만 아니라 모든 클래스에서 작동 할 수 있습니다. 많은 Rubyist #to_proc
가 Array 클래스 에서 정의하기로 선택합니다 .
class Array
def to_proc
proc { |receiver| receiver.send *self }
end
end
# And then...
[ 'Hello', 'Goodbye' ].map &[ :+, ' world!' ]
#=> ["Hello world!", "Goodbye world!"]
앰퍼샌드 &
는 to_proc
위 코드에서 Array 클래스의 피연산자에 메시지를 보내서 작동합니다 . 그리고 #to_proc
배열에서 메소드를 정의 했으므로 줄은 다음과 같습니다.
[ 'Hello', 'Goodbye' ].map { |receiver| receiver.send( :+, ' world!' ) }
속기입니다 tags.map { |tag| tag.name }.join(' ')
&
연산자 to_proc
는 피연산자를 호출 합니다. 따라서 map 메소드에만 국한되지 않으며 실제로 블록을 가져 와서 하나 이상의 인수를 블록에 전달하는 메소드에서 작동합니다.
Josh Lee의 대답은 동등한 Ruby 코드가 다음과 같아야한다는 점을 제외하면 거의 정확합니다.
class Symbol
def to_proc
Proc.new do |receiver|
receiver.send self
end
end
end
아니
class Symbol
def to_proc
Proc.new do |obj, *args|
obj.send self, *args
end
end
end
이 코드 때 print [[1,'a'],[2,'b'],[3,'c']].map(&:first)
실행되고, 루비 제의 입력을 분리 [1,'a']
한 내로 'A'에 환원 obj
1 args*
'A'(입니다 제)에있어서 자기가없는 Fixnum이라는 오브젝트 1과 같은 에러를 야기.
[[1,'a'],[2,'b'],[3,'c']].map(&:first)
실행될 때 ;
:first
는 Symbol 객체이므로 &:first
map 메소드에 매개 변수로 제공되면 Symbol # to_proc이 호출됩니다.
map은 매개 변수를 사용하여 호출 메시지를 : first.to_proc로 보냅니다 . [1,'a']
예를 들어, :first.to_proc.call([1,'a'])
실행됩니다.
Symbol 클래스의 to_proc 프로시 저는 [1,'a']
매개 변수 (: first) 를 사용하여 전송 메시지를 배열 객체 ( )로 보냅니다 [1,'a'].send(:first)
.
[[1,'a'],[2,'b'],[3,'c']]
객체 의 나머지 요소를 반복 합니다.
이는 [[1,'a'],[2,'b'],[3,'c']].map(|e| e.first)
표현식 실행과 동일 합니다.
[1,2,3,4,5,6].inject(&:+)
분사는 두 개의 매개 변수 (메모 및 항목)와 람다 기대하고 - :+.to_proc
을 제공 - Proc.new |obj, *args| { obj.send(self, *args) }
또는{ |m, o| m.+(o) }
여기서 두 가지 일이 일어나고 있으며 두 가지를 모두 이해하는 것이 중요합니다.
다른 답변에서 설명한 것처럼 Symbol#to_proc
메소드가 호출됩니다.
그러나 to_proc
심볼에 대한 이유 는 map
블록 인수로 전달되기 때문 입니다. &
메소드 호출에서 인수 앞에 배치 하면 이러한 방식으로 전달됩니다. 이것은 map
심볼 뿐만 아니라 모든 Ruby 메소드에도 적용 됩니다.
def some_method(*args, &block)
puts "args: #{args.inspect}"
puts "block: #{block.inspect}"
end
some_method(:whatever)
# args: [:whatever]
# block: nil
some_method(&:whatever)
# args: []
# block: #<Proc:0x007fd23d010da8>
some_method(&"whatever")
# TypeError: wrong argument type String (expected Proc)
# (String doesn't respond to #to_proc)
는 Symbol
A를 변환됩니다 Proc
이 블록으로 전달 있기 때문에. .map
앰퍼샌드없이 proc을 전달하여이를 표시 할 수 있습니다 .
arr = %w(apple banana)
reverse_upcase = proc { |i| i.reverse.upcase }
reverse_upcase.is_a?(Proc)
=> true
arr.map(reverse_upcase)
# ArgumentError: wrong number of arguments (1 for 0)
# (map expects 0 positional arguments and one block argument)
arr.map(&reverse_upcase)
=> ["ELPPA", "ANANAB"]
변환 할 필요는 없지만 블록 인수가 필요하기 때문에 사용 방법을 알 수 없습니다. 함께 전달하면 예상되는 블록 이 &
제공 .map
됩니다.
기본적으로 tag.name
배열의 각 태그에서 메소드 호출 을 실행합니다 .
단순화 된 루비 속기입니다.