আপনি কীভাবে আর <<< - "(স্কোপিং অ্যাসাইনমেন্ট) ব্যবহার করবেন?


140

আমি আর আর ইন্ট্রোতে স্কোপিং সম্পর্কে পড়া শেষ করেছি , এবং <<-অ্যাসাইনমেন্টটি সম্পর্কে খুব কৌতূহলী ।

ম্যানুয়ালটিতে একটি (খুব আকর্ষণীয়) উদাহরণ দেখানো হয়েছে <<-, যা আমি বুঝতে পেরেছি। আমি এখনও যা অনুপস্থিত তা হ'ল এটি কখন কার্যকর হতে পারে সে প্রসঙ্গে।

সুতরাং আমি আপনার কাছ থেকে যা পড়তে চাই তা হ'ল উদাহরণগুলি (বা উদাহরণগুলির লিঙ্কগুলি) কখন ব্যবহার <<-আকর্ষণীয় / কার্যকর হতে পারে। এটি ব্যবহারের কী কী বিপদ হতে পারে (এটি সহজেই বোঝা যায়) এবং যে কোনও টিপস যা আপনি ভাগ করে নিতে চান feel

উত্তর:


196

<<-রাষ্ট্র বজায় রাখতে ক্লোজারগুলির সাথে একত্রে সবচেয়ে কার্যকর। এখানে আমার একটি সাম্প্রতিক কাগজ থেকে একটি বিভাগ:

ক্লোজার হ'ল অন্য ফাংশন দ্বারা লিখিত একটি ফাংশন। বন্ধগুলি তাই বলা হয় কারণ তারা পিতামাতার ফাংশনের পরিবেশকে আবদ্ধ করে এবং সেই ফাংশনে সমস্ত ভেরিয়েবল এবং প্যারামিটার অ্যাক্সেস করতে পারে। এটি দরকারী কারণ এটি আমাদের দুটি স্তরের পরামিতি রাখতে দেয়। প্যারামিটারগুলির একটি স্তর (পিতামাতারা) কীভাবে ফাংশনটি কাজ করে তা নিয়ন্ত্রণ করে। অন্য স্তরের (শিশু) কাজটি করে। নিম্নলিখিত উদাহরণটি দেখায় যে কীভাবে এই ধারণাটি শক্তি কার্যকারিতার পরিবার তৈরি করতে পারে। প্যারেন্ট ফাংশন ( power) শিশু ফাংশন তৈরি করে ( squareএবং cube) যা আসলে কঠোর পরিশ্রম করে।

power <- function(exponent) {
  function(x) x ^ exponent
}

square <- power(2)
square(2) # -> [1] 4
square(4) # -> [1] 16

cube <- power(3)
cube(2) # -> [1] 8
cube(4) # -> [1] 64

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

নীচের উদাহরণটি দেখায় যে কোনও ফাংশনটি কতবার ডাকা হয়েছে তা রেকর্ড করে এমন একটি কাউন্টার বজায় রাখা এটি সম্ভব করে তোলে। প্রতিটি সময় new_counterচালানো হয়, এটি একটি পরিবেশ তৈরি করে, iএই পরিবেশে কাউন্টারটি শুরু করে এবং তারপরে একটি নতুন ফাংশন তৈরি করে।

new_counter <- function() {
  i <- 0
  function() {
    # do something useful, then ...
    i <<- i + 1
    i
  }
}

নতুন ফাংশনটি একটি বন্ধ, এবং এর পরিবেশটি আবদ্ধ পরিবেশ। যখন ক্লোজারগুলি counter_oneএবং counter_twoচালানো হয় তখন প্রত্যেকে তার সংলগ্ন পরিবেশে কাউন্টারকে পরিবর্তন করে এবং তারপরে বর্তমান গণনাটি প্রদান করে।

counter_one <- new_counter()
counter_two <- new_counter()

counter_one() # -> [1] 1
counter_one() # -> [1] 2
counter_two() # -> [1] 1

4
আরে এটি রোজটাকোডে একটি সমাধান না হওয়া আর টাস্ক ( রোসেটাকোড.অর্গ / উইকি / অ্যাকিউমুলেটর_ফ্যাক্টরি #আর ) আচ্ছা, এটি ছিল ...
কার্স্টেন ডব্লিউ

1
একটি প্যারেন্ট ফাংশনে 1 টির বেশি ক্লোজার বন্ধ করার কোনও দরকার আছে কি? আমি কেবল একটি স্নিপেট চেষ্টা করেছি, মনে হচ্ছে কেবল শেষ
বন্ধটি

"<< -" চিহ্নটির সমান চিহ্নের বিকল্প আছে কি?
জিনোম

38

এটি <<-সমতুল্য হিসাবে ভাবতে সহায়তা করে assign(যদি আপনি inheritsসেই ফাংশনে প্যারামিটারটি সেট করেন TRUE)। এর সুবিধাটি assignহ'ল এটি আপনাকে আরও প্যারামিটারগুলি নির্দিষ্ট করতে দেয় (যেমন পরিবেশ), তাই বেশিরভাগ ক্ষেত্রে আমি assignবেশি ব্যবহার করতে পছন্দ করি <<-

ব্যবহার <<-এবং এর assign(x, value, inherits=TRUE)অর্থ হল "সরবরাহযোগ্য পরিবেশের ঘেরযুক্ত পরিবেশগুলি 'x' পরিবর্তনশীল না হওয়া পর্যন্ত অনুসন্ধান করা হবে।" অন্য কথায়, এটি পরিবেশের মধ্য দিয়ে যেতে থাকবে যতক্ষণ না এটি নামের সাথে কোনও ভেরিয়েবল সন্ধান করে এবং এটি এটিকে নির্ধারণ করবে। এটি কোনও ফাংশনের ক্ষেত্রের মধ্যে বা বৈশ্বিক পরিবেশে থাকতে পারে।

এই ফাংশনগুলি কী করে তা বোঝার জন্য আপনাকে আর পরিবেশগুলিও বুঝতে হবে (যেমন ব্যবহার করা search)।

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

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


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

2
একজন জ্ঞানী ব্যক্তি একবার আমাকে বলেছিলেন যে এটি নিখুঁত হওয়া গুরুত্বপূর্ণ নয় - কেবল দাঁড়িয়ে থাকা - যা আপনি রয়েছেন এবং আপনার পোস্টগুলিও তাই হবে। এছাড়াও - কখনও কখনও পাঠক মন্তব্যগুলির সাহায্যে পাঠ্য উন্নত করতে সহায়তা করে (আমার ব্লগের সাথে এটিই ঘটে)। আমি আশা করি একদিন আপনি পুনর্বিবেচনা করবেন :)
তাল গ্যালিলি

9

আমি যেখানে ব্যবহার করেছি <<-তার একটি জায়গা টিসিএল / টিকে ব্যবহার করে সাধারণ জিইউআইতে ছিল। প্রাথমিক উদাহরণগুলির কয়েকটি এর মধ্যে রয়েছে - যেমন আপনাকে রাষ্ট্রীয়তার জন্য স্থানীয় এবং বৈশ্বিক পরিবর্তনশীলগুলির মধ্যে পার্থক্য তৈরি করতে হবে। উদাহরণস্বরূপ দেখুন

 library(tcltk)
 demo(tkdensity)

যা ব্যবহার করে <<-। অন্যথায় আমি মারেক :) এর সাথে সম্মতি দিয়েছি - একটি গুগল অনুসন্ধান সহায়তা করতে পারে।


আকর্ষণীয়, আমি কোনওভাবে tkdensityআর 3.6.0 এ খুঁজে পাচ্ছি না।
নেলসনগন


5
f <- function(n, x0) {x <- x0; replicate(n, (function(){x <<- x+rnorm(1)})())}
plot(f(1000,0),typ="l")

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

4

এই বিষয়টিতে আমি উল্লেখ করতে চাই যে <<-অপারেটরটি লুপের জন্য (ভুলভাবে) প্রয়োগ করার সময় অদ্ভুত আচরণ করবে (অন্যান্য ক্ষেত্রেও হতে পারে)। নিম্নলিখিত কোড দেওয়া:

fortest <- function() {
    mySum <- 0
    for (i in c(1, 2, 3)) {
        mySum <<- mySum + i
    }
    mySum
}

আপনি আশা করতে পারেন যে ফাংশনটি প্রত্যাশিত পরিমাণ, 6 ফেরত দেবে, তবে পরিবর্তে এটি 0 প্রদান করে, একটি বৈশ্বিক ভেরিয়েবল mySumতৈরি করা হবে এবং মান নির্ধারণ করা হয়েছে I আমি এখানে কী চলছে তা সম্পূর্ণরূপে ব্যাখ্যা করতে পারব না তবে অবশ্যই একটির জন্য লুপ না একটি নতুন সুযোগ 'স্তর'। পরিবর্তে, দেখে মনে হচ্ছে যে আর fortestফাংশনটির বাইরে mySumদেখেছে, বরাদ্দ করার জন্য কোনও ভেরিয়েবল খুঁজে পাচ্ছে না, সুতরাং একটি তৈরি করে এবং প্রথমবার লুপটির মাধ্যমে মান 1 নির্ধারণ করে। পরবর্তী পুনরাবৃত্তির উপর, অ্যাসাইনমেন্টের আরএইচএস অবশ্যই অবশ্যই (অপরিবর্তিত) অভ্যন্তরীণ mySumভেরিয়েবলের উল্লেখ করছে যেখানে এলএইচএস বিশ্বব্যাপী পরিবর্তনশীলকে বোঝায়। সুতরাং প্রতিটি পুনরাবৃত্তি গ্লোবাল ভেরিয়েবলের মানটিকে সেই পুনরাবৃত্তির মানকে ওভাররাইট করে i, সুতরাং এটি ফাংশন থেকে প্রস্থান করার সময় 3 এর মান থাকে।

আশা করি এটি কাউকে সাহায্য করবে - এটি আমাকে আজ কয়েক ঘন্টা ধরে থামিয়ে দিয়েছে! (বিটিডাব্লু, কেবল সাথে প্রতিস্থাপন করুন এবং ফাংশনটি প্রত্যাশার <<-সাথে <-কাজ করে)।


2
আপনার উদাহরণে, স্থানীয় mySumকখনও বাড়ানো হয় না তবে কেবল বিশ্বব্যাপী mySum। সুতরাং লুপটির প্রতিটি পুনরাবৃত্তিতে, গ্লোবাল mySumমান পেতে পারে 0 + i। আপনি এটি দিয়ে অনুসরণ করতে পারেন debug(fortest)
ক্লেমেন্টওয়াল্টার

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

অথবা << - সর্বত্র @ এসএমসি ব্যবহার করুন। যদিও গ্লোবাল এড়ানো ভাল best
পরিসংখ্যানগুলি শিখুন উদাহরণস্বরূপ

3

<<-অপারেটর এছাড়াও উপযোগী হতে পারে যখন রেফারেন্স পদ্ধতি লেখার রেফারেন্স ক্লাস । উদাহরণ স্বরূপ:

myRFclass <- setRefClass(Class = "RF",
                         fields = list(A = "numeric",
                                       B = "numeric",
                                       C = function() A + B))
myRFclass$methods(show = function() cat("A =", A, "B =", B, "C =",C))
myRFclass$methods(changeA = function() A <<- A*B) # note the <<-
obj1 <- myRFclass(A = 2, B = 3)
obj1
# A = 2 B = 3 C = 5
obj1$changeA()
obj1
# A = 6 B = 3 C = 9
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.