রুবি কি রেফারেন্স বা মান দ্বারা পাস?


248
@user.update_languages(params[:language][:language1], 
                       params[:language][:language2], 
                       params[:language][:language3])
lang_errors = @user.errors
logger.debug "--------------------LANG_ERRORS----------101-------------" 
                + lang_errors.full_messages.inspect

if params[:user]
  @user.state = params[:user][:state]
  success = success & @user.save
end
logger.debug "--------------------LANG_ERRORS-------------102----------" 
                + lang_errors.full_messages.inspect

if lang_errors.full_messages.empty?

@userঅবজেক্ট পদ্ধতিতে lang_errorsভেরিয়েবলটিতে ত্রুটি যুক্ত করে update_lanugages। আমি যখন @userবস্তুটিতে একটি সংরক্ষণ সম্পাদন করি তখন আমি lang_errorsভেরিয়েবলটিতে প্রাথমিকভাবে সঞ্চিত ত্রুটিগুলি হারাব ।

যদিও আমি যা করার চেষ্টা করছি তা হ্যাকের বেশি হবে (যা কাজ করছে বলে মনে হয় না)। আমি বুঝতে চাই কেন ভেরিয়েবলের মানগুলি ধুয়ে যায়। আমি রেফারেন্স দ্বারা পাস বুঝতে পারি তাই আমি জানতে চাই যে কীভাবে ধোয়া না হয়ে সেই পরিবর্তনশীলটিতে মান রাখা যায়।


আমি আরও লক্ষ্য করেছি যে আমি একটি ক্লোনযুক্ত বস্তুর মধ্যে সেই মানটি ধরে রাখতে সক্ষম হয়েছি
সিড

1
আপনার আবে ভোকারের উত্তরটি দেখতে হবে। তবে এটির উপরে ব্লকটি চালানোর পরে, আমি এটি কীভাবে বলব। আপনি যখন কোনও প্রক্রিয়াতে কোনও বস্তুকে পাস করেন, তখন অবজেক্টের রেফারেন্সের একটি অনুলিপি পাস হয়, বার, মান অনুসারে পাস করুন। Foo যে বিষয়টিকে নির্দেশ করে সেটিকে আপনি পরিবর্তন করতে পারবেন না, তবে আপনি যে অবজেক্টের দিকে ইঙ্গিত করেছেন সেটির সামগ্রী পরিবর্তন করতে পারবেন। সুতরাং আপনি যদি একটি অ্যারে পাস করেন তবে অ্যারের সামগ্রীগুলি পরিবর্তন করা যেতে পারে, তবে অ্যারেটি যা উল্লেখ করা হচ্ছে তা আপনি পরিবর্তন করতে পারবেন না। Foo- র অন্যান্য নির্ভরতা বিভ্রান্ত করার বিষয়ে চিন্তা না করেই ফু এর পদ্ধতিগুলি ব্যবহার করতে সক্ষম হওয়ায় খুব ভাল।
ববডডসল

উত্তর:


244

Traditionalতিহ্যবাহী পরিভাষায় রুবি কঠোরভাবে পাস-বাই-ভ্যালু । আপনি এখানে যা জিজ্ঞাসা করছেন তা আসলে এটি নয়।

রুবির খাঁটি, অ-রেফারেন্স মানের কোনও ধারণা নেই, সুতরাং আপনি অবশ্যই কোনও পদ্ধতিতে পাস করতে পারবেন না। চলকগুলি সর্বদা অবজেক্টগুলির উল্লেখ to কোনও জিনিস যা আপনার অধীনে থেকে পরিবর্তিত হবে না তা পেতে, আপনাকে যে জিনিসটি পাস করেছেন সেটিকে ডুপ বা ক্লোন করতে হবে, সুতরাং এমন একটি অবজেক্ট দেয় যা অন্য কারও কাছে উল্লেখ করা যায় না। (এমনকি এটি বুলেটপ্রুফ নয়, যদিও - স্ট্যান্ডার্ড ক্লোনিং পদ্ধতি উভয়ই অগভীর অনুলিপি করে, তাই ক্লোনটির উদাহরণের পরিবর্তনশীলগুলি এখনও একই জিনিসগুলিকে নির্দেশ করে যা মূলগুলি করেছিল। এখনও অনুলিপিতে প্রদর্শিত হবে, যেহেতু এটি একই জিনিসগুলি উল্লেখ করে))


88
রুবি পাস-বাই-ভ্যালু । যদি না হয়। কোন কিন্তু নাই. কোন আশা নাই. আপনাকে জানতে হবে কিনা রুবি (অথবা অন্য কোন ভাষা) হল চান পাস-বাই-রেফারেন্স বা পাস-বাই-মান , শুধু এটা চেষ্টা: def foo(bar) bar = 'reference' end; baz = 'value'; foo(baz); puts "Ruby is pass-by-#{baz}"
জার্গ ডব্লু মিটাগ

95
@ জার্গডব্লিউমিত্যাগ: হ্যাঁ, তবে ওপি'র বিভ্রান্তি আসলে শব্দগুলির কঠোর সিএস অর্থে পাস-বাই-ভ্যালু বা পাস-বাই-রেফারেন্স নয়। তিনি যে অনুপস্থিত ছিলেন তা হ'ল আপনি যে "মানগুলি" পাশ করছেন তা হল উল্লেখ are আমি অনুভব করেছি যে কেবল "এটি পাস-বাই-ভ্যালু" বলতে প্যাডেন্টিক হবে এবং ওপিকে একটি বিচ্ছিন্নতা দেওয়া হবে, কারণ এটি আসলে তার অর্থ নয়। তবে স্পষ্টতার জন্য ধন্যবাদ, কারণ এটি ভবিষ্যতের পাঠকদের জন্য গুরুত্বপূর্ণ এবং আমার এটি অন্তর্ভুক্ত করা উচিত ছিল। (আমি সবসময় আরও তথ্যের সাথে মানুষকে বিভ্রান্ত না করেই ছিঁড়ে ফেলি))
চক

16
@ জর্জের সাথে একমত নন রুবি রেফারেন্স দ্বারা পাস হয়, সে কেবল রেফারেন্স পরিবর্তন করে। পরিবর্তে এটি চেষ্টা করুন: Def foo (বার) বার.রেপস 'রেফারেন্স' শেষ; baz = 'মান'; foo বিন্যাস (বায); "রুবি পাস-বাই - #
az

15
@ পিগার্ডিরিও: আমি মনে করি এটি সত্যই সংজ্ঞাগুলির একটি প্রশ্ন। আপনি "পাস-বাই-রেফারেন্স" এর একটি সংজ্ঞা ব্যবহার করছেন যা আপনি ব্যক্তিগতভাবে নিয়ে এসেছেন, যখন জার্জ প্রচলিত কম্পিউটার বিজ্ঞানের সংজ্ঞা ব্যবহার করছেন। অবশ্যই, শব্দগুলি কীভাবে ব্যবহার করতে হয় সে সম্পর্কে আপনাকে জানানো আমার ব্যবসায়ের কোনওটিই নয় - আমি কেবল এই শব্দটির সাধারণ অর্থ কী তা ব্যাখ্যা করা গুরুত্বপূর্ণ বলে মনে করি । Traditionalতিহ্যবাহী পরিভাষায় রুবি হ'ল পাস বাই মান, তবে মানগুলি সেগুলি উল্লেখ। আমি এবং সম্পূর্ণরূপে বুঝতে পারি যে আপনি এবং ওপি কেন এটিকে পাস-বাই-রেফারেন্স হিসাবে ভাবতে পছন্দ করেন - এটি কেবল এই শব্দটির theতিহ্যগত অর্থ নয়।
চাক

7
রুবির প্রতিটি জিনিসই একটি বস্তু, সুতরাং রুবি কোনও মান দ্বারা পাস হয় না বা রেফারেন্স দ্বারা পাস হয় না, অন্তত অর্থে এই পদগুলি সি ++ এ ব্যবহৃত হয়। "অবজেক্ট রেফারেন্স দ্বারা পাস" রুবি কী করে তা বর্ণনা করার আরও ভাল উপায় হতে পারে। যদিও শেষ পর্যন্ত, সর্বোত্তম বাজি হতে পারে এই শর্তগুলির কোনওটির জন্য খুব বেশি অর্থ না দেওয়া এবং প্রকৃতপক্ষে ঘটে যাওয়া আচরণ সম্পর্কে কেবল ভাল ধারণা পাওয়া।
ডেভিড উইনিস্কি

424

অন্যান্য উত্তরদাতারা সমস্ত সঠিক, তবে একটি বন্ধু আমাকে তার কাছে এটি ব্যাখ্যা করতে বলেছিল এবং এটি কীভাবে ফুটে উঠেছে তা হ'ল রুবি কীভাবে চলকগুলি পরিচালনা করে, তাই আমি ভেবেছিলাম যে আমি তার জন্য লিখে কিছু সাধারণ ছবি / ব্যাখ্যা ভাগ করব (দৈর্ঘ্যের জন্য ক্ষমা চাই) এবং সম্ভবত কিছুটা ওভারসিম্প্লিফিকেশন):


প্রশ্ন 1: আপনি যখন strএকটি মানকে নতুন ভেরিয়েবল বরাদ্দ করেন তখন কী ঘটে 'foo'?

str = 'foo'
str.object_id # => 2000

এখানে চিত্র বর্ণনা লিখুন

উত্তর: নামক একটি লেবেল তৈরি করা strহয় 'foo'যা বস্তুটিতে পয়েন্ট করে , যা এই রুবি ইন্টারপ্রেটারের অবস্থার জন্য মেমরির স্থানে থাকে 2000


প্রশ্ন 2: আপনি যখন strনতুন ভিজিট ব্যবহার করে নতুন ভেরিয়েবল ব্যবহার =করবেন তখন কী হবে ?

str = 'bar'.tap{|b| puts "bar: #{b.object_id}"} # bar: 2002
str.object_id # => 2002

এখানে চিত্র বর্ণনা লিখুন

উত্তর: লেবেলটি strএখন অন্য কোনও অবজেক্টের দিকে নির্দেশ করে।


চতুর্থাংশ 3: যখন আপনি একটি নতুন পরিবর্তনশীল বরাদ্দ কি হবে =থেকে str?

str2 = str
str2.object_id # => 2002

এখানে চিত্র বর্ণনা লিখুন

উত্তর: একটি নতুন লেবেল নামক str2তৈরি করা হয় যে পয়েন্ট একই বস্তুর যেমন str


প্রশ্ন 4: যদি বস্তুটি রেফারেন্স করে strএবং str2পরিবর্তিত হয় তবে কী হবে ?

str2.replace 'baz'
str2 # => 'baz'
str  # => 'baz'
str.object_id # => 2002
str2.object_id # => 2002

এখানে চিত্র বর্ণনা লিখুন

উত্তর: উভয় লেবেল এখনও একই বস্তুটির দিকে ইঙ্গিত করে তবে সেই বস্তুটি নিজেই পরিবর্তিত হয়েছিল (এর বিষয়বস্তু অন্য কিছুতে পরিবর্তিত হয়েছে)।


এটি কীভাবে মূল প্রশ্নের সাথে সম্পর্কিত?

এটি মূলত Q3 / Q4 এ যা ঘটে তা একই; পদ্ধতিটি ভেরিয়েবল / লেবেলের ( str2) এর নিজস্ব ব্যক্তিগত কপি পায় যা এতে প্রবেশ করে ( str)। কোন লেবেলটি اعتراض করে তা পরিবর্তন করতে পারে নাstr নির্দেশ , তবে এটি যে উভয়কেই অন্য কোনও বিষয়কে বোঝায় সেই সামগ্রীর সামগ্রীর পরিবর্তন করতে পারে:

str = 'foo'

def mutate(str2)
  puts "str2: #{str2.object_id}"
  str2.replace 'bar'
  str2 = 'baz'
  puts "str2: #{str2.object_id}"
end

str.object_id # => 2004
mutate(str) # str2: 2004, str2: 2006
str # => "bar"
str.object_id # => 2004

1
রবার্ট হিটন ইদানীং এ সম্পর্কে ব্লগ করেছেন: robertheaton.com/2014/07/22/…
মাইকেল রেনার

48

রুবি "অবজেক্ট রেফারেন্স দ্বারা পাস" ব্যবহার করে

(পাইথনের পরিভাষা ব্যবহার করে))

রুবি "মান দ্বারা পাস" বা "রেফারেন্স দ্বারা পাস" ব্যবহার করে বলে সাহায্যকারী হওয়ার পক্ষে এটি যথেষ্ট বর্ণনামূলক নয়। আমি মনে করি যেহেতু বেশিরভাগ লোকেরা এটি জানেন, সেই পরিভাষা ("মান" বনাম "রেফারেন্স") সি ++ থেকে এসেছে।

সি ++ এ, "মান দ্বারা পাস" এর অর্থ ফাংশনটি ভেরিয়েবলের একটি অনুলিপি পায় এবং অনুলিপিতে যে কোনও পরিবর্তন আসল পরিবর্তন করে না। বস্তুর ক্ষেত্রেও এটি সত্য। যদি আপনি কোনও মান ভেরিয়েবলকে মান দ্বারা পাস করেন তবে পুরো বস্তুটি (এর সমস্ত সদস্য সহ) অনুলিপি পেতে থাকে এবং সদস্যদের যে কোনও পরিবর্তন আসল বস্তুতে সেই সদস্যগুলিকে পরিবর্তন করে না। (যদি আপনি মান অনুসারে কোনও পয়েন্টার পাস করেন তবে এটি আলাদা তবে রুবির কোনও পয়েন্টার নেই, এএফএআইকি।)

class A {
  public:
    int x;
};

void inc(A arg) {
  arg.x++;
  printf("in inc: %d\n", arg.x); // => 6
}

void inc(A* arg) {
  arg->x++;
  printf("in inc: %d\n", arg->x); // => 1
}

int main() {
  A a;
  a.x = 5;
  inc(a);
  printf("in main: %d\n", a.x); // => 5

  A* b = new A;
  b->x = 0;
  inc(b);
  printf("in main: %d\n", b->x); // => 1

  return 0;
}

আউটপুট:

in inc: 6
in main: 5
in inc: 1
in main: 1

সি ++ এ, "রেফারেন্স দ্বারা পাস" এর অর্থ ফাংশনটি আসল ভেরিয়েবলের অ্যাক্সেস পায়। এটি সম্পূর্ণ নতুন আক্ষরিক পূর্ণসংখ্যাকে বরাদ্দ করতে পারে এবং আসল ভেরিয়েবলেরও তখন এর মানটি থাকে।

void replace(A &arg) {
  A newA;
  newA.x = 10;
  arg = newA;
  printf("in replace: %d\n", arg.x);
}

int main() {
  A a;
  a.x = 5;
  replace(a);
  printf("in main: %d\n", a.x);

  return 0;
}

আউটপুট:

in replace: 10
in main: 10

যুক্তি যদি কোনও বস্তু না হয় তবে রুবি মান দ্বারা পাস (সি ++ অর্থে) ব্যবহার করে। তবে রুবিতে সবকিছুই একটি অবজেক্ট, সুতরাং রুবিতে সি ++ অর্থে সত্যিকার অর্থে কোনও পাস নেই।

রুবিতে, "অবজেক্ট রেফারেন্স দিয়ে পাস করুন" (পাইথনের পরিভাষা ব্যবহার করতে) ব্যবহৃত হয়:

  • ফাংশনের অভ্যন্তরে, অবজেক্টের যে কোনও সদস্যের কাছে নতুন মান নির্ধারিত থাকতে পারে এবং ফাংশনটি ফিরে আসার পরে এই পরিবর্তনগুলি বহাল থাকবে *
  • ফাংশনের অভ্যন্তরে, ভেরিয়েবলকে সম্পূর্ণ নতুন অবজেক্ট বরাদ্দকরণের ফলে ভেরিয়েবল পুরানো অবজেক্টটি উল্লেখ করা বন্ধ করে দেয়। তবে ফাংশনটি ফিরে আসার পরে, মূল পরিবর্তনশীলটি এখনও পুরানো অবজেক্টটি উল্লেখ করবে reference

সুতরাং রুবি সি ++ অর্থে "পাস বাই রেফারেন্স" ব্যবহার করেন না। যদি এটি হয়ে থাকে তবে কোনও ফাংশনের অভ্যন্তরে কোনও ভেরিয়েবলে একটি নতুন অবজেক্ট বরাদ্দকরণের ফলে ফাংশনটি ফিরে আসার পরে পুরানো অবজেক্টটি ভুলে যেতে পারে।

class A
  attr_accessor :x
end

def inc(arg)
  arg.x += 1
  puts arg.x
end

def replace(arg)
  arg = A.new
  arg.x = 3
  puts arg.x
end

a = A.new
a.x = 1
puts a.x  # 1

inc a     # 2
puts a.x  # 2

replace a # 3
puts a.x  # 2

puts ''

def inc_var(arg)
  arg += 1
  puts arg
end

b = 1     # Even integers are objects in Ruby
puts b    # 1
inc_var b # 2
puts b    # 1

আউটপুট:

1
2
2
3
2

1
2
1

* এই কারণেই, রুবিতে, আপনি যদি কোনও ফাংশনের অভ্যন্তরে কোনও অবজেক্ট পরিবর্তন করতে চান তবে ফাংশনটি ফিরে আসার পরে সেই পরিবর্তনগুলি ভুলে যেতে পারেন, তবে অনুলিপিটি অনুলিপি করে নিজের অস্থায়ী পরিবর্তন করার আগে আপনাকে অবশ্যই স্পষ্টভাবে অবজেক্টের একটি অনুলিপি তৈরি করতে হবে।


আপনার উত্তরটি সেরা। আমিও একটি সহজ উদাহরণ পোষ্ট ওয়ানা def ch(str) str.reverse! end; str="abc"; ch(str); puts str #=> "cba"
fangxing

এটা সঠিক উত্তর! এটি এখানে খুব ভালভাবে ব্যাখ্যা করা হয়েছে: robertheaton.com/2014/07/22/… । কিন্তু আমি এখনও বুঝতে পারছি না, তা হল: def foo(bar) bar = 'reference' end; baz = 'value'; foo(baz); puts "Ruby is pass-by-#{baz}"। এই মুদ্রণটি "রুবি পাস-বাই-মান"। তবে ভেরিয়েবলের ভিতরে fooপুনরায় নিয়োগ দেওয়া হয়। যদি barএকটি অ্যারের হবে অতীতকে ফিরিয়ে কার্যকর would baz। কেন?
হাফলা

আমি আপনার প্রশ্ন বুঝতে পারি না। আমি মনে করি আপনার এখানে মন্তব্যগুলিতে জিজ্ঞাসা না করে সম্পূর্ণ নতুন প্রশ্ন করা উচিত।
ডেভিড উইনিস্কি

42

রুবি কি রেফারেন্স বা মান দ্বারা পাস?

রুবি পাস-বাই-ভ্যালু। সর্বদা. কোন আশা নাই. যদি না হয়। কোন কিন্তু নাই.

এখানে একটি সাধারণ প্রোগ্রাম যা এই সত্যটি দেখায়:

def foo(bar)
  bar = 'reference'
end

baz = 'value'

foo(baz)

puts "Ruby is pass-by-#{baz}"
# Ruby is pass-by-value

15
এটা একটা ভুল, যে নয় - @DavidJ .: "ভুল এখানে যে স্থানীয় পরামিতি পুনরায় নির্ধারণ করা হয় (মেমরি নতুন জায়গায় তীক্ষ্ন) হল" সংজ্ঞা এর পাস-বাই-মান । রুবি যদি পাস-বাই-রেফারেন্স হয়ে থাকে, তবে কলিতে অন্তর্ভুক্ত স্থানীয় পদ্ধতি আর্গুমেন্টকে পুনর্নির্দিষ্ট করাও কলারের মধ্যে স্থানীয় ভেরিয়েবল বন্ডিংকে পুনরায় স্বাক্ষর করতে পারত। যা তা হয়নি। এরগো, রুবি পাস-বাই-ভ্যালু। সত্য যে আপনি যদি কোনও পরিবর্তনীয় মান পরিবর্তন করেন তবে মান পরিবর্তন সম্পূর্ণ অপ্রাসঙ্গিক, ঠিক তেমনই পরিবর্তনীয় রাষ্ট্র কীভাবে কাজ করে। রুবি একটি খাঁটি কার্যকরী ভাষা নয়।
জার্গ ডব্লু মিট্টাগ

5
"পাস-বাই-মান" এর সত্যিকারের সংজ্ঞাটি রক্ষার জন্য জার্গকে ধন্যবাদ। এটি প্রকৃতপক্ষে আমাদের মস্তিষ্ককে গলিয়ে দেয় যখন মানটি প্রকৃতপক্ষে একটি রেফারেন্স হয়, যদিও রুবি সর্বদা মান দ্বারা পাস করে।
ডগলাস

9
এটি সুশীলতা। "মান দ্বারা পাস" এবং "রেফারেন্স দ্বারা পাস" এর মধ্যে ব্যবহারিক পার্থক্যটি একটি সিনট্যাক্ট, সিনট্যাকটিক নয়। আপনি কি বলতে পারবেন যে সি অ্যারেগুলি পাস-বাই-মান হয়? অবশ্যই নয়, আপনি যখন কোনও ফাংশনে অ্যারের নামটি পাস করেন তখনও আপনি একটি অপরিবর্তনীয় পয়েন্টারটি অতিক্রম করে যাচ্ছেন এবং কেবলমাত্র সেই পয়েন্টারটিকেই বদলে ফেলা যায় mut স্পষ্টতই রুবিতে মান প্রকারগুলি মান দ্বারা পাস হয় এবং রেফারেন্সের ধরণগুলি রেফারেন্স দ্বারা পাস হয় passed
dodgethesteamroller

3
@ ডডজেটেসট্যাম্রোলার: রুবি এবং সি উভয়ই পাস-বাই-মান। সর্বদা. কোনও ব্যতিক্রম নয়, যদি কোনও বুট নেই। পাস-বাই-মান এবং পাস-বাই-রেফারেন্সের মধ্যে পার্থক্য হ'ল আপনি রেফারেন্সটির পয়েন্টটি মানটি পাস করেন বা রেফারেন্সটি পাস করেন কিনা। সি সর্বদা মান পাস করে, কখনই রেফারেন্স হয় না। মান বা একটি পয়েন্টার নাও হতে পারে হতে পারে, কিন্তু কি মান কিনা এটা প্রথম স্থানে প্রেরণ করা হচ্ছে হয় অপ্রাসঙ্গিক। রুবি সর্বদা মানটি পাস করে, কখনই রেফারেন্স হয় না। এই মানটি সর্বদা একটি পয়েন্টার, তবে আবার এটি অপ্রাসঙ্গিক।
Jörg ডব্লু মিটাগ

44
এই উত্তর, কঠোরভাবে সত্য বলার সময় , খুব কার্যকর নয় । মানটি পাস করার বিষয়টি সর্বদা পয়েন্টার অপ্রাসঙ্গিক নয় । এটি শিখার চেষ্টা করা লোকদের জন্য এটি বিভ্রান্তির উত্স এবং আপনার উত্তরটি এই বিভ্রান্তিতে সহায়তা করার জন্য একেবারে কিছুই করে না।

20

রুবি একটি কঠোর অর্থে পাস-বাই-মান, তবে মানগুলি হল উল্লেখ।

এটিকে " পাস-রেফারেন্স-বাই-মান " বলা যেতে পারে । এই নিবন্ধটি আমি পড়ে সবচেয়ে ভাল ব্যাখ্যা আছে: http://robertheaton.com/2014/07/22/is-ruby-pass-by-references-or-pass-by-value/

পাস-রেফারেন্স বাই মানটি সংক্ষেপে নীচে ব্যাখ্যা করা যেতে পারে:

একটি ফাংশন কলার দ্বারা ব্যবহৃত মেমরিতে একই অবজেক্টের (এবং অ্যাক্সেস করবে) একটি রেফারেন্স পায়। যাইহোক, কলারটি এই বস্তুটি স্টোর করছে এমন বক্সটি গ্রহণ করে না; পাস-মান-বাই-ভ্যালু হিসাবে, ফাংশনটি তার নিজস্ব বাক্স সরবরাহ করে এবং নিজের জন্য একটি নতুন পরিবর্তনশীল তৈরি করে।

ফলস্বরূপ আচরণটি আসলে পাস-বাই-রেফারেন্স এবং পাস-বাই-মানের শাস্ত্রীয় সংজ্ঞাগুলির সংমিশ্রণ।


"মান অনুসারে পাস রেফারেন্স" হ'ল রুবীর যুক্তি উত্তীর্ণের বর্ণনা দিতে আমি একই বাক্যটি ব্যবহার করি। আমি মনে করি এটি সবচেয়ে সঠিক এবং সংক্ষিপ্ত বাক্যাংশ।
ওয়েইন কনরাড

16

ইতিমধ্যে কয়েকটি দুর্দান্ত উত্তর রয়েছে, তবে আমি এই বিষয়টিতে একজোড়া কর্তৃপক্ষের সংজ্ঞা পোস্ট করতে চাই, তবে আশা করি যে কেউ হয়তো ব্যাখ্যা করতে পারে যে কর্তৃপক্ষের ম্যাজ (রুবির স্রষ্টা) এবং ডেভিড ফ্লানাগান তাদের চমৎকার ও'রিলি বইটিতে কী বোঝাতে চেয়েছিল, রুবি প্রোগ্রামিং ভাষা

[৩.৮.১ থেকে: অবজেক্ট রেফারেন্স]

আপনি যখন রুবিতে কোনও পদ্ধতিতে কোনও বস্তু পাস করেন, এটি একটি অবজেক্ট রেফারেন্স যা পদ্ধতিতে পাস হয়। এটি নিজেই অবজেক্ট নয় এবং এটি কোনও বস্তুর রেফারেন্সের কোনও রেফারেন্স নয়। এটি বলার আরেকটি উপায় হ'ল পদ্ধতি আর্গুমেন্টগুলি রেফারেন্সের পরিবর্তে মান দ্বারা পাস হয় তবে পাস করা মানগুলি অবজেক্ট রেফারেন্স।

যেহেতু অবজেক্টের রেফারেন্সগুলি পদ্ধতিগুলিতে পাস করা হয়, পদ্ধতিগুলি অন্তর্নিহিত অবজেক্টটি সংশোধন করতে সেই তথ্যগুলি ব্যবহার করতে পারে। পদ্ধতিটি ফিরে আসার পরে এই পরিবর্তনগুলি দৃশ্যমান হয়।

এই শেষ অনুচ্ছেদটি এবং বিশেষত শেষ বাক্যটি না হওয়া অবধি আমার কাছে তা বোঝা যায় । এটি সর্বোত্তম বিভ্রান্তিকর এবং আরও বিভ্রান্তিকর। কীভাবে, কোনও উপায়ে, সেই পাস-বাই-মান রেফারেন্সের পরিবর্তনগুলি অন্তর্নিহিত অবজেক্টটি পরিবর্তন করতে পারে?


1
কারণ রেফারেন্সটি সংশোধিত হচ্ছে না; অন্তর্নিহিত বস্তু হয়।
dodgethesteamroller

1
কারণ বস্তুটি পরিবর্তনযোগ্য। রুবি সম্পূর্ণরূপে কার্যকরী ভাষা নয়। পাস-বাই-রেফারেন্স বনাম পাস-বাই-ভ্যালুতে এটি সম্পূর্ণ orthogonal (খাঁটি কার্যকরী ভাষায়, পাস-বাই-ভ্যালু এবং পাস-বাই-রেফারেন্স সবসময় একই ফলাফল দেয়, তাই ভাষাটি পারে কখনও না জেনে উভয়ই ব্যবহার করুন)।
জার্গ ডব্লু মিট্টাগ

একটি ভাল উদাহরণটি হ'ল যদি কোনও ফাংশনে পরিবর্তনশীল অ্যাসাইনমেন্টের পরিবর্তে আপনি কোনও ফাংশনে একটি হ্যাশ পাস করার এবং মার্জ করার ক্ষেত্রে তাকান! পাস হ্যাশ উপর। আসল হ্যাশটি সংশোধিত শেষ হয়।
এলসি

16

রুবি কি রেফারেন্স বা মান দ্বারা পাস?

রুবি পাস-রেফারেন্স। সর্বদা. কোন আশা নাই. যদি না হয়। কোন কিন্তু নাই.

এখানে একটি সাধারণ প্রোগ্রাম যা এই সত্যটি দেখায়:

def foo(bar)
  bar.object_id
end

baz = 'value'

puts "#{baz.object_id} Ruby is pass-by-reference #{foo(baz)} because object_id's (memory addresses) are always the same ;)"

=> 2279146940 রুবি পাস-বাই-রেফারেন্স 2279146940 কারণ অবজেক্ট_আইডির (মেমরি ঠিকানা) সর্বদা একই থাকে;)

def bar(babar)
  babar.replace("reference")
end

bar(baz)

puts "some people don't realize it's reference because local assignment can take precedence, but it's clearly pass-by-#{baz}"

=> কিছু লোকেরা এর রেফারেন্স বুঝতে পারে না কারণ স্থানীয় কার্যনির্বাহীকরণ অগ্রাধিকার নিতে পারে, তবে এটি স্পষ্টতই বাই-রেফারেন্স হয়


এটিই একমাত্র সঠিক উত্তর এবং কিছু চমৎকার গোটচগুলি উপস্থাপন করছে: চেষ্টা করুন একটি = 'ফুবার'; খ = ক; b [5] = 'z', a এবং b উভয়ই সংশোধিত হবে।
মার্টিজন

2
@ মার্তিজন: আপনার যুক্তি পুরোপুরি বৈধ নয়। স্টেটমেন্ট দিয়ে আপনার কোড স্টেটমেন্ট মাধ্যমে চলুন। a = 'ফুবার' একটি নতুন রেফারেন্স তৈরি করে যা 'ফুবার' -কে নির্দেশ করে। খ = একটি একই ডেটার জন্য দ্বিতীয় রেফারেন্স তৈরি করে। b [5] = 'z' b দ্বারা রেফারেন্স হওয়া মানটির ষষ্ঠ অক্ষরকে 'z' এ পরিবর্তিত করে (মানটি যা কাকতালীয়ভাবে একটি রেফারেন্স দ্বারা রেফারেন্সও হয়)। এজন্য আপনার পদগুলিতে "উভয়ই সংশোধিত হন" বা আরও স্পষ্টভাবে, কেন "উভয় ভেরিয়েবলের দ্বারা বর্ণিত মানটি পরিবর্তিত হয়"।
Lukas_Skywalker

2
আপনি আপনার barপদ্ধতিতে রেফারেন্স দিয়ে কিছু করছেন না । আপনি কেবল সেই অবজেক্টটিই সংশোধন করছেন যা রেফারেন্সটি নির্দেশ করে তবে রেফারেন্সটি নিজেই নয়। তারা কেবল রুবিতে রেফারেন্স সংশোধন করার উপায় হ'ল অ্যাসাইনমেন্ট দ্বারা। আপনি রুবিতে পদ্ধতি কল করে রেফারেন্সগুলি সংশোধন করতে পারবেন না কারণ পদ্ধতিগুলি কেবলমাত্র বস্তুগুলিতে কল করা যেতে পারে এবং উল্লেখগুলি রুবিতে অবজেক্ট নয়। আপনার কোড নমুনাটি দেখায় যে রুবি পারস্পরিক পরিবর্তন ভাগ করে নিয়েছে (যা এখানে আলোচনার অধীনে নেই) তবে পাস-বাই-মান এবং পাস-বাই-রেফারেন্সের মধ্যে পার্থক্য আলোকিত করার জন্য এটি কিছুই করে না।
জার্গ ডব্লু মিট্টাগ

1
যখন কেউ জিজ্ঞাসা করে যে কোনও ভাষা "পাস-বাই-রেফারেন্স" কিনা তারা সাধারণত জানতে চায় আপনি যখন কোনও ফাংশনে কিছু পাস করেন এবং ফাংশনটি এটি পরিবর্তন করে, তখন কি এটি ফাংশনের বাইরে পরিবর্তন করা হবে? রুবির উত্তর 'হ্যাঁ'। এই উত্তরটি প্রদর্শন করতে সহায়ক যে @ জার্গডাব্লু মিটাগের উত্তরটি অত্যন্ত অপ্রয়োজনীয়।
টবি 1 কেনোবি

@ টোবি 1 কেনোবি: আপনি অবশ্যই "পাস-বাই-ভ্যালু" শব্দটির নিজস্ব ব্যক্তিগত সংজ্ঞাটি ব্যবহার করতে পারবেন যা সাধারণ, বহুল ব্যবহৃত সংজ্ঞা থেকে পৃথক। যাইহোক, আপনি যদি এটি করেন তবে আপনার বিভ্রান্ত হওয়ার জন্য প্রস্তুত থাকতে হবে, বিশেষত আপনি যদি একেবারেই আলাদা বিষয়ে কথা বলছেন এমন সত্য প্রকাশ করতে অবহেলা করেন তবে কিছু ক্ষেত্রে এমনকি অন্য সবার মত ধারণাও নয় opposite বিশেষ করে, "পাস-বাই-রেফারেন্স" হয় না সঙ্গে সংশ্লিষ্ট থাকুক বা না থাকুক "কিছু" যে পাস করা হয়েছে পরিবর্তন করা যাবে, বরং সঙ্গে কি "কিছু" বিশেষ করে হয়, তা রেফারেন্স ... যে
Jörg ওয়াট মিট্টাগ

8

পরামিতিগুলি মূল রেফারেন্সের একটি অনুলিপি। সুতরাং, আপনি মান পরিবর্তন করতে পারেন, তবে মূল রেফারেন্স পরিবর্তন করতে পারবেন না।


2

এটা চেষ্টা কর:--

1.object_id
#=> 3

2.object_id
#=> 5

a = 1
#=> 1
a.object_id
#=> 3

b = 2
#=> 2
b.object_id
#=> 5

আইডেন্টিফায়ার একটিতে মান অবজেক্ট 1 এর জন্য অবজেক্ট_আইডি 3 এবং শনাক্তকারী বিতে মান 2 অবজেক্টের জন্য অবজেক্ট_িড 5 থাকে।

এখন এটি করুন: -

a.object_id = 5
#=> error

a = b
#value(object_id) at b copies itself as value(object_id) at a. value object 2 has object_id 5
#=> 2

a.object_id 
#=> 5

এখন, a এবং b উভয়টিতে একই অবজেক্ট_আইডি 5 রয়েছে যা মান 2 অবধি বোঝায় So সুতরাং, রুবি ভেরিয়েবেলে অবজেক্ট_আইডস মান মানকে বোঝায়।

নিম্নলিখিতগুলি করাও ত্রুটি দেয়: -

c
#=> error

তবে এটি করলে ত্রুটি হবে না: -

5.object_id
#=> 11

c = 5
#=> value object 5 provides return type for variable c and saves 5.object_id i.e. 11 at c
#=> 5
c.object_id
#=> 11 

a = c.object_id
#=> object_id of c as a value object changes value at a
#=> 11
11.object_id
#=> 23
a.object_id == 11.object_id
#=> true

a
#=> Value at a
#=> 11

এখানে আইডেন্টিফায়ার একটি রিটার্ন ভ্যালু অবজেক্ট 11 যার অবজেক্ট আইডি 23 অর্থাৎ অবজেক্ট_আইডি 23 আইডেন্টিফায়ার এ রয়েছে, এখন আমরা পদ্ধতিটি ব্যবহার করে একটি উদাহরণ দেখতে পাই।

def foo(arg)
  p arg
  p arg.object_id
end
#=> nil
11.object_id
#=> 23
x = 11
#=> 11
x.object_id
#=> 23
foo(x)
#=> 11
#=> 23

এক্স-এর রিটার্ন মান সহ ফাঁকে ফাঁকে ফাঁকে বরাদ্দ করা হয়। এটি স্পষ্টভাবে দেখায় যে আর্গুমেন্টটি 11 টি মান দ্বারা পাস হয়ে গেছে, এবং মান 11 নিজেই একটি অবজেক্ট হিসাবে অনন্য অবজেক্ট আইডি 23 রয়েছে।

এবার এটিও দেখুন: -

def foo(arg)
  p arg
  p arg.object_id
  arg = 12
  p arg
  p arg.object_id
end

#=> nil
11.object_id
#=> 23
x = 11
#=> 11
x.object_id
#=> 23
foo(x)
#=> 11
#=> 23
#=> 12
#=> 25
x
#=> 11
x.object_id
#=> 23

এখানে, শনাক্তকারী আরগটিতে প্রথমে ১১ টি রেফারেন্স করার জন্য অবজেক্ট_আইডি 23 থাকে এবং মান 12 এর সাথে অভ্যন্তরীণ নিয়োগের পরে এতে অবজেক্ট_আইডি 25 থাকে But তবে কলিং পদ্ধতিতে ব্যবহৃত আইডেন্টিফায়ার দ্বারা রেফারেন্সকৃত মানটি পরিবর্তিত হয় না।

সুতরাং, রুবি মান দ্বারা পাস হয় এবং রুবি ভেরিয়েবলের মান থাকে না তবে মান বস্তুর উল্লেখ থাকে।


1

রুবি ব্যাখ্যা করা হয়। ভেরিয়েবলগুলি ডেটাগুলির উল্লেখ হয় তবে ডেটা নিজেই নয়। এটি বিভিন্ন ধরণের ডেটার জন্য একই ভেরিয়েবল ব্যবহার করতে সহায়তা করে।

Lhs = rhs এর বরাদ্দকরণের পরে আরএইচএসে রেফারেন্সটি অনুলিপি হয়, ডেটা নয়। এটি অন্যান্য ভাষায় যেমন সি এর ক্ষেত্রে আলাদা হয় যেখানে অ্যাসাইনমেন্টটি আরএইচএস থেকে এলএইচএসে ডেটা অনুলিপি করে।

সুতরাং ফাংশন কলের জন্য, ভেরিয়েবলটি পাস করুন, এক্স বলুন, প্রকৃতপক্ষে ফাংশনের একটি স্থানীয় ভেরিয়েবলে অনুলিপি করা হয়েছে, তবে এক্স একটি রেফারেন্স। এরপরে রেফারেন্সের দুটি অনুলিপি থাকবে, উভয়ই একই ডেটার রেফারেন্স করবে। একজন কলারে থাকবেন, একজন ফাংশনে থাকবেন।

ফাংশনে অ্যাসাইনমেন্টটি এক্স এর ফাংশনের সংস্করণে একটি নতুন রেফারেন্স অনুলিপি করবে। এর পরে x এর কলারের সংস্করণ অপরিবর্তিত রয়েছে। এটি এখনও মূল তথ্যগুলির একটি রেফারেন্স।

বিপরীতে, x এ .replace পদ্ধতি ব্যবহারের ফলে রুবি একটি ডেটা অনুলিপি করতে পারে। যদি কোনও নতুন কার্যভারের আগে প্রতিস্থাপন ব্যবহার করা হয় তবে প্রকৃতপক্ষে কলার তার সংস্করণেও ডেটা পরিবর্তন দেখতে পাবেন।

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

'= দ্বারা মান দ্বারা কল' বা 'রেফারেন্সের মাধ্যমে কল' এখানে বিভ্রান্তির কারণেই '=' সংকলিত ভাষায় '=' একটি তথ্য অনুলিপি। এখানে এই ব্যাখ্যা করা ভাষায় '=' একটি রেফারেন্স কপি। উদাহরণে আপনার রেফারেন্সটি একটি রেফারেন্স অনুলিপি দ্বারা অনুসরণ করা হয়েছে যদিও '=' যে ক্লোবারগুলি মূল রেফারেন্সে পাস করেছে, এবং তারপরে লোকেরা এটি সম্পর্কে কথা বলছে যেন '=' একটি ডেটা অনুলিপি ছিল।

সংজ্ঞাগুলির সাথে সামঞ্জস্য বজায় রাখতে আমাদের অবশ্যই '.replace' সাথে রাখতে হবে কারণ এটি একটি ডেটা অনুলিপি রয়েছে। '.Replace' এর দৃষ্টিকোণ থেকে আমরা দেখতে পাচ্ছি যে এটি প্রকৃতপক্ষে রেফারেন্স দিয়ে গেছে। তদ্ব্যতীত, আমরা যদি ডিবাগারের মধ্য দিয়ে চলে যাই তবে আমরা দেখতে পাচ্ছি যে রেফারেন্সগুলি পাস হচ্ছে, কারণ ভেরিয়েবলগুলি উল্লেখযোগ্য।

তবে আমাদের যদি অবশ্যই '=' কে রেফারেন্সের ফ্রেম হিসাবে রাখতে পারি তবে অবশ্যই আমরা একটি অ্যাসাইনমেন্ট অবধি ডেটাতে পাস হওয়া দেখতে পাব এবং তারপরে কলারের ডেটা অপরিবর্তিত থাকা অবস্থায় আমরা অ্যাসাইনমেন্টের পরে আর এটি দেখতে পাব না। আচরণগত স্তরে এটি ততক্ষণ মান দ্বারা পাস করা হয় যতক্ষণ না আমরা পাসের মানটিকে সম্মিলিত হিসাবে বিবেচনা করি না - কারণ আমরা একটি অংশে অন্য অংশটি পরিবর্তন করার সময় এর অংশটি রাখতে সক্ষম হবো না (সেই দায়িত্ব হিসাবে রেফারেন্স পরিবর্তন করে এবং আসল সুযোগের বাইরে চলে যায়)। একটি ওয়ার্টও থাকবে, সেই পরিস্থিতিতে সমস্ত ভেরিয়েবলের মতো অবজেক্টে ভেরিয়েবলের রেফারেন্স থাকবে। সুতরাং আমরা 'মান অনুসারে রেফারেন্স' পাশ করার বিষয়ে কথা বলতে বাধ্য করব এবং সম্পর্কিত লোকেশন ব্যবহার করতে হবে।


1

এটি লক্ষ করা উচিত যে মানটির মূল মান পরিবর্তন করতে আপনাকে "প্রতিস্থাপন" পদ্ধতিটি ব্যবহার করতে হবে না। যদি আপনি হ্যাশের জন্য একটি হ্যাশ মান নির্ধারণ করেন তবে আপনি আসল মানটি পরিবর্তন করছেন।

def my_foo(a_hash)
  a_hash["test"]="reference"
end;

hash = {"test"=>"value"}
my_foo(hash)
puts "Ruby is pass-by-#{hash["test"]}"

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

1
Two references refer to same object as long as there is no reassignment. 

এখনও একই মেমরির থাকার কারণে একই অবজেক্টের কোনও আপডেট নতুন মেমরির উল্লেখ করতে পারে না। এখানে কয়েকটি উদাহরণ দেওয়া হল:

    a = "first string"
    b = a



    b.upcase! 
    => FIRST STRING
    a
    => FIRST STRING

    b = "second string"


a
    => FIRST STRING
    hash = {first_sub_hash: {first_key: "first_value"}}
first_sub_hash = hash[:first_sub_hash]
first_sub_hash[:second_key] = "second_value"

    hash
    => {first_sub_hash: {first_key: "first_value", second_key: "second_value"}}

    def change(first_sub_hash)
    first_sub_hash[:third_key] = "third_value"
    end

    change(first_sub_hash)

    hash
    =>  {first_sub_hash: {first_key: "first_value", second_key: "second_value", third_key: "third_value"}}

0

হ্যাঁ কিন্তু ....

রুবি একটি বস্তুর সাথে একটি রেফারেন্স পাস করে এবং যেহেতু রুবির প্রতিটি জিনিসই একটি বস্তু, তাই আপনি বলতে পারেন এটি রেফারেন্স দ্বারা পাস হয়েছে।

আমি এখানে পোস্টিংগুলির সাথে এটি মান দিয়ে যায় বলে দাবি করে না, এটি আমার কাছে পেডেন্টিক, সিনটিক গেমগুলির মতো মনে হয়।

তবে বাস্তবে এটি আচরণটি "আড়াল করে" কারণ বেশিরভাগ অপারেশন রুবি "বাক্সের বাইরে" সরবরাহ করে - উদাহরণস্বরূপ স্ট্রিং অপারেশনগুলি, অবজেক্টের একটি অনুলিপি তৈরি করে:

> astringobject = "lowercase"

> bstringobject = astringobject.upcase
> # bstringobject is a new object created by String.upcase

> puts astringobject
lowercase

> puts bstringobject
LOWERCASE

এর অর্থ হ'ল বেশিরভাগ সময়, আসল বস্তুটি অপরিবর্তিত রেখে দেয় যে রুবিটি "মান দ্বারা পাস" হয় giving

অবশ্যই আপনার নিজের ক্লাসগুলি ডিজাইন করার সময় কার্যকরী আচরণ, স্মৃতিশক্তি দক্ষতা এবং কার্য সম্পাদন উভয়ের জন্য এই আচরণের বিশদটি বোঝা গুরুত্বপূর্ণ।

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