আমি এই কোডটি একটি রেলকাস্টে পেয়েছি :
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' তে obj
1 এবং 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