রুবিতে মানচিত্র (&: নাম) এর অর্থ কী?


495

আমি এই কোডটি একটি রেলকাস্টে পেয়েছি :

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

কি (&:name)মধ্যে map(&:name)অর্থ কি?


122
আমি এটিকে "প্রিটজেল কোলন" বলে শুনেছি।
জোশ লি

6
হা হা। আমি জানি এম্পারসেন্ড হিসাবে and আমি এটিকে কখনও "প্রেটজেল" বলে শুনেছি নি তবে তা উপলব্ধি করে।
ড্রাগনফ্যাক্স

74
আকর্ষণীয় হলেও এটিকে "প্রিটজেল কোলন" বলা বিভ্রান্তিকর। রুবিতে কোনও "&:" নেই। এম্পারস্যান্ড (&) হ'ল "অ্যানারি অ্যাম্পারস্যান্ড অপারেটর" যার সাথে একসাথে ঠেলাঠেলি করা হয়েছে: প্রতীক। যদি কিছু হয় তবে এটি একটি "প্রিটজেল প্রতীক"। এমনি বলছি.
ফন্টনো

3
ট্যাগস.ম্যাপ (&: নাম) ট্যাগগুলি থেকে সাজানো। ম্যাপ from | গুলি | s.name}
কাউশাল শর্মা

3
"প্রিটজেল কোলন" বেদনাদায়ক চিকিত্সার মতো অবস্থা বলে মনে হচ্ছে ... তবে আমি এই প্রতীকটির নামটি পছন্দ করি :)
zmoreris

উত্তর:


517

এটি সংক্ষিপ্ত tags.map(&:name.to_proc).join(' ')

যদি fooকোনও to_procপদ্ধতির সাথে কোনও বস্তু হয় , তবে আপনি এটিকে কোনও পদ্ধতিতে এটি পাস করতে পারেন &foo, যা কল foo.to_procকরে পদ্ধতিটির ব্লক হিসাবে ব্যবহার করবে ।

Symbol#to_procপদ্ধতি মূলত ActiveSupport দ্বারা যোগ করা হয়েছিল কিন্তু রুবি 1.8.7 একত্রিত হয়েছে। এটি এর বাস্তবায়ন:

class Symbol
  def to_proc
    Proc.new do |obj, *args|
      obj.send self, *args
    end
  end
end

41
এটি আমার চেয়ে ভাল উত্তর।
অলিভার এন।

91
ট্যাগস.ম্যাপ (: name.to_proc) নিজেই ট্যাগস.ম্যাপ for | ট্যাগ | ট্যাগ.নম}
সিমোন কার্লেটি

5
এটি বৈধ রুবি কোড নয়, আপনার এখনও দরকার &, অর্থাত্tags.map(&:name.to_proc).join(' ')
ঘোড়াচুরি

5
প্রতীক # টু_প্রোকটি সি তে প্রয়োগ করা হয়, রুবিতে নয়, তবে এটি রুবির মতো দেখতে চাই।
অ্যান্ড্রু গ্রিম

5
@ অ্যান্ড্রুগ্রিম এটি কোডটি ব্যবহার করে প্রথমে রেল অন রুবেলে যুক্ত হয়েছিল। এরপরে এটি 1.8.7 সংস্করণে নেটিভ রুবি বৈশিষ্ট্য হিসাবে যুক্ত করা হয়েছিল।
ক্যামেরন মার্টিন

174

আর একটি দুর্দান্ত শর্টহ্যান্ড, অনেকেরই অজানা is

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(:==))

পছন্দের উপায়টি সর্বাধিক পঠনযোগ্য হওয়া উচিত।


25
array.each{|e| foo(e)}এখনও ছোট :-) যাইহোক +1
জ্যারেড বেক

আপনি ব্যবহার করে অন্য শ্রেণীর একজন নির্মাতা মানচিত্র করতে পারেন &method?
হলোগ্রাফিক-নীতি

3
@ ফিনিশিংময়ে হ্যাঁ আমি অনুমান করি। এটি ব্যবহার করে দেখুন[1,2,3].map(&Array.method(:new))
গেরি


45

যদিও আমাদের আরও খেয়াল করা যাক যে অ্যাম্পারস্যান্ড #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!' ) }

এটা খাঁটি সোনার!
কুবাক

38

এটি সংক্ষিপ্ত tags.map { |tag| tag.name }.join(' ')


না, এটি রুবিতে 1.8.7 এবং তারও বেশি।
চক

এটি কি মানচিত্রের জন্য সহজ আইডিয়া বা রুবি সর্বদা একটি নির্দিষ্ট উপায়ে '&' এর ব্যাখ্যা করে?
কলিমার্কো

7
@ কলিমার্কো: জেলিদেব যেমন তার উত্তরে বলেছেন, অ্যানারি &অপারেটর to_procতার অপারেন্ডকে ডাকছে । সুতরাং এটি মানচিত্রের পদ্ধতির সাথে সুনির্দিষ্ট নয় এবং প্রকৃতপক্ষে কোনও পদ্ধতিতে কাজ করে যা একটি ব্লক নেয় এবং এক বা একাধিক তর্ককে ব্লকে পাস করে।
ছক

36
tags.map(&:name)

হিসাবে একই

tags.map{|tag| tag.name}

&:name ডাকার জন্য পদ্ধতির নাম হিসাবে কেবল প্রতীকটি ব্যবহার করে।


1
উত্তরটি আমি বিশেষত প্রক্সের পরিবর্তে চেয়েছিলাম (তবে এটি ছিল
প্রশ্নকারীদের

চমৎকার উত্তর! আমার জন্য ভাল ব্যাখ্যা।
আপাদানা

14

সমতুল্য রুবি কোডটি নীচে হওয়া উচিত ছিল ব্যতীত জোশ লির উত্তর প্রায় সঠিক।

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']1 এবং 'a' তে obj1 এবং args*'a' এ বিভক্ত করতে বিভক্ত করে কারণ ফিক্সনাম অবজেক্ট 1 এর পদ্ধতিটি স্বতঃ থাকে না (যা প্রথম:)।


কখন [[1,'a'],[2,'b'],[3,'c']].map(&:first)মৃত্যুদন্ড কার্যকর করা হয়;

  1. :firstএকটি সিম্বল অবজেক্ট, সুতরাং যখন &:firstপ্যারামিটার হিসাবে মানচিত্রের পদ্ধতিতে দেওয়া হয়, সিম্বল # টু_প্রোক চালু করা হয়।

  2. মানচিত্র কল কলটি প্রেরণ করে: প্যারামিটার সহ প্রথম. টু_প্রোক [1,'a'], :first.to_proc.call([1,'a'])যেমন কার্যকর করা হয়।

  3. সিম্বল ক্লাসে to_proc পদ্ধতি [1,'a']প্যারামিটার (: প্রথম) সহ একটি অ্যারে অবজেক্টে ( ) প্রথম বার্তা প্রেরণ করে , যেমন, [1,'a'].send(:first)কার্যকর করা হয়।

  4. [[1,'a'],[2,'b'],[3,'c']]বস্তুর বাকী উপাদানগুলির উপর পুনরাবৃত্তি হয় ।

এক্সিকিউটিং [[1,'a'],[2,'b'],[3,'c']].map(|e| e.first)এক্সপ্রেশন হিসাবে এটি একই ।


1
জোশ লির উত্তর একেবারে সঠিক, আপনি যেমনটি চিন্তা করে দেখতে পারেন [1,2,3,4,5,6].inject(&:+)- ইনজেকশন দুটি পরামিতি (মেমো এবং আইটেম) সহ একটি ল্যাম্বদা প্রত্যাশা :+.to_procকরে এবং তা সরবরাহ করে - Proc.new |obj, *args| { obj.send(self, *args) }বা{ |m, o| m.+(o) }
উরি আগাসি

11

এখানে দুটি জিনিস ঘটছে, এবং এটি উভয়ই বোঝা গুরুত্বপূর্ণ।

অন্যান্য উত্তরে বর্ণিত হিসাবে, 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একটি রূপান্তরিত পরার 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


এটি সৎভাবে দেওয়া সেরা উত্তর। আপনি অ্যাম্পারস্যান্ডের পেছনের প্রক্রিয়াটি ব্যাখ্যা করলেন এবং কেন আমরা একটি প্রোকের সাথে শেষ করব, যা আপনার উত্তর না পাওয়া পর্যন্ত আমি পাইনি। ধন্যবাদ.
ফ্রালকন

5

(&: নাম) এর জন্য সংক্ষিপ্ত (এবং: name.to_proc) এটির মতো tags.map{ |t| t.name }.join(' ')

to_proc আসলে সি তে প্রয়োগ করা হয়


5

মানচিত্র (&: নাম) একটি গণনামূলক অবজেক্ট (আপনার ক্ষেত্রে ট্যাগগুলি ) নেয় এবং পদ্ধতি থেকে প্রতিটি ফেরত মান আউটপুট করে প্রতিটি উপাদান / ট্যাগের জন্য নাম পদ্ধতি চালায়।

এটি একটি সংক্ষিপ্ত হাত

array.map { |element| element.name }

যা উপাদান (ট্যাগ) নামের অ্যারে প্রদান করে


2

যদিও আমাদের কাছে ইতিমধ্যে দুর্দান্ত উত্তর রয়েছে, তবে একটি প্রাথমিকের দৃষ্টিকোণটি দেখে আমি অতিরিক্ত তথ্য যুক্ত করতে চাই:

রুবিতে মানচিত্র (&: নাম) এর অর্থ কী?

এর অর্থ, আপনি মানচিত্রের ফাংশনে প্যারামিটার হিসাবে অন্য পদ্ধতিটি পাস করছেন। (বাস্তবে আপনি এমন একটি প্রতীক যাচ্ছেন যা একটি প্রকোপে রূপান্তরিত হয় But তবে এটি এই বিশেষ ক্ষেত্রে তেমন গুরুত্বপূর্ণ নয়)।

গুরুত্বপূর্ণটি হ'ল আপনার এমন একটি methodনাম রয়েছে nameযা মানচিত্রের পদ্ধতিতে ট্র্যাডিশনাল blockস্টাইলের পরিবর্তে একটি যুক্তি হিসাবে ব্যবহৃত হবে as


2

এটি মূলত পদ্ধতি কলটি কার্যকর করে tag.name অ্যারেতে প্রতিটি চালায়।

এটি সরলিকৃত রুবি শর্টহ্যান্ড।


1

এখানে :nameপ্রতীক যা nameট্যাগ অবজেক্টের পদ্ধতির দিকে নির্দেশ করে । যখন আমরা পাস &:nameকরি map, এটি nameএকটি প্রোক অবজেক্ট হিসাবে বিবেচনা করবে । সংক্ষেপে, এই tags.map(&:name)হিসাবে কাজ করে:

tags.map do |tag|
  tag.name
end


1

প্রথমত, এর &:nameজন্য একটি শর্টকাট &:name.to_proc, যেখানে :name.to_procকোনও Proc(যা ল্যাম্বদার মতো কিছু নয়, এমন কিছু দেয়) ফেরত দেয় যা যখন কোনও বস্তুর সাথে (প্রথম) আর্গুমেন্ট হিসাবে ডাকা হয়, ডাকেname পদ্ধতিটিকে ।

দ্বিতীয়ত, যখন &মধ্যে def foo(&block) ... endধর্মান্তরিত একটি ব্লক প্রেরণ fooএকটি থেকে Proc, এটা বিপরীত একটি প্রয়োগ করে Proc

সুতরাং, &:name.to_procএমন একটি ব্লক যা কোনও বস্তুকে আর্গুমেন্ট হিসাবে গ্রহণ করে এবং তার nameউপর পদ্ধতিটি কল করে , অর্থাৎ { |o| o.name }


আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.