문제

이 코드를 찾았습니다 Railscast:

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

다른 팁

많은 사람들에게 알려지지 않은 또 다른 시원한 속기입니다

array.each(&method(:foo))

그것은 속기입니다

array.each { |element| foo(element) }

전화로 method(:foo) 우리는 Method 객체 self 그것은 그것의 것을 나타냅니다 foo 방법을 사용했습니다 & 그것이 있다는 것을 의미합니다 to_proc 방법 그것은 그것을 a로 변환합니다 Proc.

이것은 당신이 일을하고 싶을 때 매우 유용합니다. 포인트 프리 스타일. 예를 들어 배열에 문자열이 있는지 확인하는 것이 있습니다. "foo". 기존의 방법이 있습니다.

["bar", "baz", "foo"].any? { |str| str == "foo" }

그리고 점이없는 방법이 있습니다.

["bar", "baz", "foo"].any?(&"foo".method(:==))

선호하는 방법은 가장 읽기 쉬운 방법이어야합니다.

그것은 동일합니다

def tag_names
  @tag_names || tags.map { |tag| tag.name }.join(' ')
end

앰퍼 랜드도 주목하겠습니다 #to_proc 마술은 상징뿐만 아니라 모든 수업과 함께 작동 할 수 있습니다. 많은 루비스트들이 정의하기로 선택합니다 #to_proc 배열 클래스 :

class Array
  def to_proc
    proc { |receiver| receiver.send *self }
  end
end

# And then...

[ 'Hello', 'Goodbye' ].map &[ :+, ' world!' ]
#=> ["Hello world!", "Goodbye world!"]

앰퍼 랜드 & 전송하여 작동합니다 to_proc 위 코드에서 배열 클래스 인 오페라의 메시지. 그리고 내가 정의한 이후 #to_proc 배열의 메소드 라인은 다음과 같습니다.

[ 'Hello', 'Goodbye' ].map { |receiver| receiver.send( :+, ' world!' ) }

속기입니다 tags.map { |tag| tag.name }.join(' ')

tags.map(&:name)

와 같다

tags.map{|tag| tag.name}

&:name 기호를 호출 할 메소드 이름으로 사용합니다.

Josh Lee의 답변은 동등한 루비 코드가 다음과 같아야한다는 점을 제외하고는 거의 정확합니다.

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) Ruby는 실행됩니다. Ruby는 첫 번째 입력을 분할합니다 [1,'a'] 1과 'a'로 줄 수 있습니다 obj 1과 args* 'a'는 fixnum 객체 1으로 오류를 일으키기 위해 메소드 자체가 없다 (첫째 : 첫 번째).


언제 [[1,'a'],[2,'b'],[3,'c']].map(&:first) 실행됩니다.

  1. :first 기호 객체입니다 &:first 매개 변수로 맵 메소드에 제공되며 기호#to_proc이 호출됩니다.

  2. 맵은 다음에 호출 메시지를 보냅니다 : first.to_proc 매개 변수로 [1,'a'], 예 : :first.to_proc.call([1,'a']) 실행됩니다.

  3. 기호 클래스의 TO_PROC 절차는 배열 객체에 보내는 메시지를 보냅니다 ([1,'a']) PARAMETER (: 첫 번째), 예를 들어, [1,'a'].send(:first) 실행됩니다.

  4. 나머지 요소들에 반복됩니다 [[1,'a'],[2,'b'],[3,'c']] 물체.

이것은 실행과 동일합니다 [[1,'a'],[2,'b'],[3,'c']].map(|e| e.first) 표현.

여기서 두 가지 일이 일어나고 있으며 둘 다 이해하는 것이 중요합니다.

다른 답변에 설명 된 바와 같이 Symbol#to_proc 방법이 호출되고 있습니다.

그러나 이유 to_proc 상징에 부름이 있습니다. map 블록 인수로. 자본 매출 & 메소드 호출의 인수 앞에서이 방식으로 통과됩니다. 이것은 단지 루비 방법에 해당됩니다. map 기호로.

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 블록으로 전달되기 때문입니다. 우리는 Proc를 전달하려고 노력함으로써 이것을 보여줄 수 있습니다. .map 앰퍼 랜드없이 :

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 그것이 기대하는 블록.

(& : name)은 짧습니다 (& : name.to_proc) tags.map{ |t| t.name }.join(' ')

TO_PROC는 실제로 c에서 구현됩니다

우리는 이미 훌륭한 답을 가지고 있지만 초보자의 관점을 살펴보면 추가 정보를 추가하고 싶습니다.

Ruby에서 Map (& : name)은 무엇을 의미합니까?

즉, 맵 함수에 다른 방법을 매개 변수로 전달하고 있음을 의미합니다. (실제로 당신은 Proc로 변환되는 상징을 전달하지만 이것은이 특정한 경우에는 중요하지 않습니다).

중요한 것은 당신이 있다는 것입니다 method 명명 된 name 그것은지도 메소드에 의해 전통적인 대신 인수로 사용됩니다. block 스타일.

지도 (& : 이름) 열거 가능한 객체 (케이스의 태그)를 취하고 각 요소/태그의 이름 메소드를 실행하여 메소드에서 리턴 된 각 값을 출력합니다.

그것은 속기입니다

array.map { |element| element.name }

요소 배열 (TAG) 이름을 반환합니다.

여기 :name 메소드를 가리키는 기호입니다 name 태그 객체의. 우리가 지나갈 때 &:name 에게 map, 그것은 치료할 것입니다 name Proc 객체로. 간단히 tags.map(&:name) 처럼 연기하다:

tags.map do |tag|
  tag.name
end

그 뜻은

array.each(&:to_sym.to_proc)

기본적으로 메소드 호출을 실행합니다 tag.name 배열의 각 태그에서.

단순화 된 루비 속기입니다.

아래와 동일합니다.

def tag_names
  if @tag_names
    @tag_names
  else
    tags.map{ |t| t.name }.join(' ')
end
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top