আমি এই কোডটি একটি রেলকাস্টে পেয়েছি :
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কোনও 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
&, অর্থাত্tags.map(&:name.to_proc).join(' ')
আর একটি দুর্দান্ত শর্টহ্যান্ড, অনেকেরই অজানা 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(:==))
পছন্দের উপায়টি সর্বাধিক পঠনযোগ্য হওয়া উচিত।
array.each{|e| foo(e)}এখনও ছোট :-) যাইহোক +1
&method?
[1,2,3].map(&Array.method(:new))
এর সমতুল্য
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(' ')
&অপারেটর to_procতার অপারেন্ডকে ডাকছে । সুতরাং এটি মানচিত্রের পদ্ধতির সাথে সুনির্দিষ্ট নয় এবং প্রকৃতপক্ষে কোনও পদ্ধতিতে কাজ করে যা একটি ব্লক নেয় এবং এক বা একাধিক তর্ককে ব্লকে পাস করে।
tags.map(&:name)
হিসাবে একই
tags.map{|tag| tag.name}
&:name ডাকার জন্য পদ্ধতির নাম হিসাবে কেবল প্রতীকটি ব্যবহার করে।
সমতুল্য রুবি কোডটি নীচে হওয়া উচিত ছিল ব্যতীত জোশ লির উত্তর প্রায় সঠিক।
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)মৃত্যুদন্ড কার্যকর করা হয়;
:firstএকটি সিম্বল অবজেক্ট, সুতরাং যখন &:firstপ্যারামিটার হিসাবে মানচিত্রের পদ্ধতিতে দেওয়া হয়, সিম্বল # টু_প্রোক চালু করা হয়।
মানচিত্র কল কলটি প্রেরণ করে: প্যারামিটার সহ প্রথম. টু_প্রোক [1,'a'], :first.to_proc.call([1,'a'])যেমন কার্যকর করা হয়।
সিম্বল ক্লাসে to_proc পদ্ধতি [1,'a']প্যারামিটার (: প্রথম) সহ একটি অ্যারে অবজেক্টে ( ) প্রথম বার্তা প্রেরণ করে , যেমন, [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প্রতীক সহ নয়, কোনও রুবি পদ্ধতির ক্ষেত্রে সত্য ।
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।
যদিও আমাদের কাছে ইতিমধ্যে দুর্দান্ত উত্তর রয়েছে, তবে একটি প্রাথমিকের দৃষ্টিকোণটি দেখে আমি অতিরিক্ত তথ্য যুক্ত করতে চাই:
রুবিতে মানচিত্র (&: নাম) এর অর্থ কী?
এর অর্থ, আপনি মানচিত্রের ফাংশনে প্যারামিটার হিসাবে অন্য পদ্ধতিটি পাস করছেন। (বাস্তবে আপনি এমন একটি প্রতীক যাচ্ছেন যা একটি প্রকোপে রূপান্তরিত হয় But তবে এটি এই বিশেষ ক্ষেত্রে তেমন গুরুত্বপূর্ণ নয়)।
গুরুত্বপূর্ণটি হ'ল আপনার এমন একটি methodনাম রয়েছে nameযা মানচিত্রের পদ্ধতিতে ট্র্যাডিশনাল blockস্টাইলের পরিবর্তে একটি যুক্তি হিসাবে ব্যবহৃত হবে as
এটি মূলত পদ্ধতি কলটি কার্যকর করে tag.name অ্যারেতে প্রতিটি চালায়।
এটি সরলিকৃত রুবি শর্টহ্যান্ড।
প্রথমত, এর &:nameজন্য একটি শর্টকাট &:name.to_proc, যেখানে :name.to_procকোনও Proc(যা ল্যাম্বদার মতো কিছু নয়, এমন কিছু দেয়) ফেরত দেয় যা যখন কোনও বস্তুর সাথে (প্রথম) আর্গুমেন্ট হিসাবে ডাকা হয়, ডাকেname পদ্ধতিটিকে ।
দ্বিতীয়ত, যখন &মধ্যে def foo(&block) ... endধর্মান্তরিত একটি ব্লক প্রেরণ fooএকটি থেকে Proc, এটা বিপরীত একটি প্রয়োগ করে Proc।
সুতরাং, &:name.to_procএমন একটি ব্লক যা কোনও বস্তুকে আর্গুমেন্ট হিসাবে গ্রহণ করে এবং তার nameউপর পদ্ধতিটি কল করে , অর্থাৎ { |o| o.name }।
এটি নীচের মতই:
def tag_names
if @tag_names
@tag_names
else
tags.map{ |t| t.name }.join(' ')
end