রুবিতে স্ট্রিং তৈরি করার সময় কেন বেলচা অপারেটর (<<) প্লাস-সমান (+ =) এর চেয়ে বেশি পছন্দ করা হয়?


156

আমি রুবি কোয়ানসের মাধ্যমে কাজ করছি।

test_the_shovel_operator_modifies_the_original_stringমধ্যে Koan- র about_strings.rb নিম্নলিখিত মন্তব্য রয়েছে:

রুবি প্রোগ্রামাররা স্ট্রিংগুলি তৈরি করার সময় প্লাস সমান অপারেটর (+ =) এর চেয়ে বেশি বেলচা অপারেটর (<<) এর পক্ষ নেয়। কেন?

আমার ধারণা এটিতে গতি জড়িত, তবে আমি হুডের নীচে এমন ক্রিয়াটি বুঝতে পারি না যা ঝাঁকুনী অপারেটরটিকে দ্রুততর করবে।

কেউ কি এই পছন্দটির পিছনে বিশদটি ব্যাখ্যা করতে সক্ষম হবেন?


4
বেলন অপারেটর একটি নতুন স্ট্রিং অবজেক্ট (কস্টিং মেমরি) তৈরি করার পরিবর্তে স্ট্রিং অবজেক্টটি পরিবর্তন করে। সিনট্যাক্স কি সুন্দর নয়? cf. জাভা এবং .NET এর স্ট্রিংবিল্ডার ক্লাস রয়েছে
কর্নেল আতঙ্ক

উত্তর:


257

প্রমাণ:

a = 'foo'
a.object_id #=> 2154889340
a << 'bar'
a.object_id #=> 2154889340
a += 'quux'
a.object_id #=> 2154742560

সুতরাং <<একটি নতুন তৈরির পরিবর্তে মূল স্ট্রিংকে পরিবর্তন করে। এর কারণ হ'ল রুবিতে a += bসিনট্যাক্টিক শর্টহ্যান্ড a = a + b(অন্যান্য <op>=অপারেটরদের ক্ষেত্রে এটি একই রকম হয় ) যা একটি অ্যাসাইনমেন্ট। অন্যদিকে <<একটি উপনাম concat()যা এর স্থলে গ্রহণকারীকে পরিবর্তন করে।


3
ধন্যবাদ, নুডল! সুতরাং, সংক্ষেপে, << দ্রুত কারণ এটি নতুন অবজেক্ট তৈরি করে না?
ইরানব্রাউন

1
এই মানদণ্ডটি বলছে যে Array#joinএটি ব্যবহারের চেয়ে ধীর <<
অ্যান্ড্রু গ্রিম

5
এজ কেস ছেলেটির একজন পারফরম্যান্স সংখ্যার সাথে একটি ব্যাখ্যা পোস্ট করেছেন: স্ট্রিংস সম্পর্কে সামান্য আরও
সিনসিনাটি জো

8
উপরের @ সিনসিনাটি জো লিঙ্কটি নষ্ট হয়ে গেছে বলে মনে হচ্ছে, এখানে নতুন একটি রয়েছে: স্ট্রিংস সম্পর্কে সামান্য আরও
জাসোয়ারেস

জাভা ভাবেনদের জন্য: রুবিতে '+' অপারেটর স্ট্রিংবিল্ডার অবজেক্টের মাধ্যমে সংযোজনের সাথে মিল রাখে এবং '<<' স্ট্রিং অবজেক্টের
সংমিশ্রনের সাথে মিলে

79

পারফরম্যান্স প্রমাণ:

#!/usr/bin/env ruby

require 'benchmark'

Benchmark.bmbm do |x|
  x.report('+= :') do
    s = ""
    10000.times { s += "something " }
  end
  x.report('<< :') do
    s = ""
    10000.times { s << "something " }
  end
end

# Rehearsal ----------------------------------------
# += :   0.450000   0.010000   0.460000 (  0.465936)
# << :   0.010000   0.000000   0.010000 (  0.009451)
# ------------------------------- total: 0.470000sec
# 
#            user     system      total        real
# += :   0.270000   0.010000   0.280000 (  0.277945)
# << :   0.000000   0.000000   0.000000 (  0.003043)

70

রুবি কোয়ানস সিরিজের স্ট্রিংস রুবিতে যাওয়ার সময় রুবি তার প্রথম প্রোগ্রামিং ভাষা হিসাবে শিখছে এমন এক বন্ধু আমাকে একই প্রশ্ন জিজ্ঞাসা করেছিল। আমি নিম্নলিখিত উপমা ব্যবহার করে তাকে ব্যাখ্যা করেছি;

আপনার কাছে এক গ্লাস জল রয়েছে যা অর্ধেক পূর্ণ এবং আপনার নিজের গ্লাসটি পুনরায় পূরণ করতে হবে।

প্রথমবার আপনি এটি একটি নতুন গ্লাস নিয়ে, একটি ট্যাপ থেকে জল দিয়ে আধা পথ দিয়ে এবং তারপরে আপনার পানীয় গ্লাসটি পুনরায় পূরণ করার জন্য এই দ্বিতীয় অর্ধ-পূর্ণ গ্লাসটি ব্যবহার করে করেন। প্রতিবার আপনার গ্লাসটি পুনরায় পূরণ করার জন্য আপনি এটি করুন।

আপনার অর্ধেক পূর্ণ গ্লাসটি নিয়ে যাওয়ার দ্বিতীয় বার এবং এটিকে সরাসরি ট্যাপ থেকে জল দিয়ে পুনরায় পূরণ করুন।

দিনের শেষে, আপনার গ্লাসটি রিফিল করার জন্য প্রতিবার নতুন গ্লাস বেছে নেওয়া বেছে নেওয়া হলে আপনার আরও পরিষ্কার করতে হবে glasses

একই বেলচা অপারেটর এবং প্লাস সমান অপারেটরের ক্ষেত্রে প্রযোজ্য। প্লাস ইক্যুয়াল অপারেটর যখনই তার গ্লাসটি রিফিল করার প্রয়োজন হয় তখনই একটি নতুন 'গ্লাস' বাছাই করে যখন বেলচা অপারেটর কেবল একই গ্লাস নেয় এবং এটি পুনরায় পূরণ করে। দিন শেষে প্লাস সমান অপারেটরের জন্য আরও 'কাঁচ' সংগ্রহ।


2
দুর্দান্ত উপমা, এটি পছন্দ।
জিএমএ

5
দুর্দান্ত উপমা কিন্তু ভয়ানক উপসংহার। আপনাকে যুক্ত করতে হবে যে চশমা অন্য কারও দ্বারা পরিষ্কার করা হয় যাতে আপনার সেগুলির যত্ন নিতে হবে না।
ফিলিপ বার্টুজি

1
দুর্দান্ত উপমা, আমি মনে করি এটি একটি ভাল সিদ্ধান্তে আসে comes আমার মনে হয় কে কে গ্লাস পরিষ্কার করতে হবে সে সম্পর্কে কম এবং আদৌ ব্যবহৃত চশমার সংখ্যা সম্পর্কে আরও বেশি। আপনি কল্পনা করতে পারেন যে নির্দিষ্ট অ্যাপ্লিকেশনগুলি তাদের মেশিনগুলিতে মেমরির সীমাটি চাপ দিচ্ছে এবং সেই মেশিনগুলি একবারে নির্দিষ্ট সংখ্যক চশমা পরিষ্কার করতে পারে।
চার্লি এল

11

এটি একটি পুরানো প্রশ্ন, তবে আমি কেবল এটি পেরেছি এবং বিদ্যমান উত্তরগুলি নিয়ে আমি সম্পূর্ণ সন্তুষ্ট নই। বেলচা << সংক্ষিপ্তকরণের চেয়ে দ্রুত হওয়া ++ সম্পর্কে প্রচুর ভাল পয়েন্ট রয়েছে তবে এর অর্থগত বিবেচনাও রয়েছে।

@ নুডলের গৃহীত উত্তরটি দেখায় যে << বিদ্যমান বস্তুটি স্থানে পরিবর্তন করে, যেখানে + = একটি নতুন অবজেক্ট তৈরি করে। সুতরাং আপনি যদি স্ট্রিংয়ের সমস্ত রেফারেন্সগুলি নতুন মান প্রতিবিম্বিত করতে চান তবে আপনাকে বিবেচনা করা উচিত বা আপনি বিদ্যমান রেফারেন্সগুলি একা রেখে স্থানীয়ভাবে ব্যবহারের জন্য একটি নতুন স্ট্রিং মান তৈরি করতে চান। আপডেট মানটি প্রতিবিম্বিত করতে আপনার যদি সমস্ত রেফারেন্সের প্রয়োজন হয় তবে আপনাকে << ব্যবহার করতে হবে। আপনি যদি অন্য রেফারেন্সগুলি একা ছেড়ে যেতে চান তবে আপনাকে + = ব্যবহার করতে হবে।

একটি খুব সাধারণ ক্ষেত্রে স্ট্রিং শুধুমাত্র একটি রেফারেন্স আছে। এই ক্ষেত্রে, অর্থগত পার্থক্য কোনও বিষয় নয় এবং << এর গতির কারণে এটি পছন্দ করা স্বাভাবিক।


10

কারণ এটি দ্রুত / স্ট্রিংয়ের একটি অনুলিপি তৈরি করে না <-> আবর্জনা সংগ্রহকারী চালানোর দরকার নেই।


উপরের উত্তরগুলি আরও বিশদ দেয় যদিও এটিই একমাত্র সম্পূর্ণ উত্তরের জন্য তাদের একত্রিত করে। এখানে কীটি আপনার "স্ট্রিংগুলি বাড়ানোর" শব্দটির অর্থে মনে হচ্ছে এটি বোঝায় যে আপনি মূল স্ট্রিংগুলি চান না বা প্রয়োজন নেই need
ড্র্রু ভার্লি

এই উত্তরটি একটি মিথ্যা ভিত্তির উপর ভিত্তি করে: স্বল্প-স্থায়ী বস্তু বরাদ্দকরণ এবং মুক্ত করা উভয়ই মূলত যে কোনও অর্ধেক শালীন আধুনিক জিসিতে বিনামূল্যে। এটি কমপক্ষে সিতে স্ট্যাক বরাদ্দ হিসাবে তত দ্রুত এবং malloc/ এর চেয়ে উল্লেখযোগ্যভাবে দ্রুত free। এছাড়াও, আরও কিছু আধুনিক রুবি বাস্তবায়ন অবজেক্ট বরাদ্দ এবং স্ট্রিং কনটেনটেশন সম্পূর্ণরূপে অপ্টিমাইজ করবে। OTOH, রূপান্তরকারী বস্তুগুলি GC এর কার্য সম্পাদনের জন্য ভয়ঙ্কর।
Jörg ডব্লু মিটাগ

4

উত্তরগুলির বেশিরভাগ কভারটি +=ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে উত্তর উত্তরগুলি কপি করে তোলে এটি একটি নতুন অনুলিপি তৈরি করে, এটি মনে রাখা গুরুত্বপূর্ণ +=এবং << তা নয় বিনিমেয়! আপনি প্রতিটি বিভিন্ন ক্ষেত্রে ব্যবহার করতে চান।

ব্যবহারের <<দ্বারা চিহ্নিত যে কোনও ভেরিয়েবলকেও পরিবর্তন করা হবে b। আমরা aযখন চাই না তখন এখানেও পরিবর্তন করি।

2.3.1 :001 > a = "hello"
 => "hello"
2.3.1 :002 > b = a
 => "hello"
2.3.1 :003 > b << " world"
 => "hello world"
2.3.1 :004 > a
 => "hello world"

যেহেতু +=একটি নতুন অনুলিপি তৈরি করে, এটি কোনও পরিবর্তনশীলকেও এটি অপরিবর্তিত রাখার জন্য ছেড়ে দেয়।

2.3.1 :001 > a = "hello"
 => "hello"
2.3.1 :002 > b = a
 => "hello"
2.3.1 :003 > b += " world"
 => "hello world"
2.3.1 :004 > a
 => "hello"

আপনি যখন লুপগুলি নিয়ে কাজ করছেন তখন এই পার্থক্যটি বোঝা আপনাকে অনেক মাথাব্যথা বাঁচাতে পারে!


2

আপনার প্রশ্নের সরাসরি উত্তর না হয়েও , কেন সম্পূর্ণ আপ্টার্ডেড বিন সর্বদা আমার প্রিয় রুবি নিবন্ধগুলির একটি হয়ে থাকে। এতে আবর্জনা সংগ্রহের ক্ষেত্রে স্ট্রিং সম্পর্কিত কিছু তথ্য রয়েছে।


টিপটির জন্য আপনাকে ধন্যবাদ, মাইকেল! আমি এখনও রুবিতে এখনও এটি অর্জন করতে পারি নি, তবে ভবিষ্যতে এটি অবশ্যই কার্যকর হবে।
ইরানব্রাউন
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.