質問

RailsCast でこのコードを見つけました:

def tag_names
  @tag_names || tags.map(&:name).join(' ')
end

map(&:name)(&:name)はどういう意味ですか?

役に立ちましたか?

解決

tags.map(&:name.to_proc).join( '')

の省略形です

foo 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

他のヒント

多くの人には知られていないもう1つのクールな速記は

array.each(&method(:foo))

の短縮形です

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

method(:foo)を呼び出すことで、 foo メソッドを表す self から Method オブジェクトを取得しました、および& を使用して、 to_proc 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 マジックは、Symbolだけでなく、どのクラスでも機能することに注意してください。多くのRubyistは、Arrayクラスで #to_proc を定義することを選択します。

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

# And then...

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

Ampersand & は、上記のコードではArrayクラスのオペランドで to_proc メッセージを送信することで機能します。そして、Arrayで #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の答えはほぼ同等です。ただし、同等の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)がRubyを実行すると、最初の入力 [1、 'a'] が1と 'a'に分割され、 obj 1と args * 'aが得られます'Fixnumオブジェクト1にはメソッドself(:first)がないため、エラーが発生します。


[[1、 'a']、[2、 'b']、[3、 'c']]。map(&:first)が実行されたとき;

>
  1. :first はSymbolオブジェクトなので、&:first がパラメーターとしてマップメソッドに渡されると、Symbol#to_procが呼び出されます。

  2. mapは、パラメーター [1、 'a'] で呼び出しメッセージを:first.to_procに送信します(例::first.to_proc.call([1、 'a' ])が実行されます。

  3. Symbolクラスの
  4. to_procプロシージャは、パラメータ(:first)を持つ配列オブジェクト( [1、 'a'] )に送信メッセージを送信します(例: [1、 'a']。send(:first)が実行されます。

  5. [[1、 'a']、[2、 'b']、[3、 'c']] オブジェクトの残りの要素について繰り返します。 p>

これは、 [[1、 'a']、[2、 'b']、[3、 'c']]。map(| e | e.first)式。

ここでは2つのことが起こっています。両方を理解することが重要です。

他の回答で説明したように、 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 は、ブロックとして渡されるため、 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"]

変換する必要はありませんが、ブロック引数を想定しているため、メソッドはその使用方法を知りません。それを&amp; で渡すと、 .map が期待するブロックを提供します。

(&amp;:name)は(&amp;:name.to_proc)の略で、 tags.map {と同じです| t | t.name} .join( '')

to_procは実際にはCで実装されています

すでに素晴らしい回答がありますが、初心者の視点から見て、追加情報を追加したいと思います:

  

map(&amp;:name)はRubyで何を意味しますか?

これは、別のメソッドをパラメーターとしてマップ関数に渡すことを意味します。 (実際には、procに変換されるシンボルを渡します。しかし、これはこの特定のケースではそれほど重要ではありません。)

重要なことは、 name という名前の method があり、これは従来の block スタイル。

map(&amp;:name)は列挙可能なオブジェクト(あなたの場合はタグ)を受け取り、各要素/タグに対してnameメソッドを実行し、メソッドから各戻り値を出力します。

これは略記です

array.map { |element| element.name }

要素(タグ)名の配列を返します

ここで:name は、タグオブジェクトのメソッド name を指すシンボルです。 &amp;:name map に渡すと、 name をprocオブジェクトとして扱います。 要するに、 tags.map(&amp;: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