উত্তর:
"গোটো" বিবৃতিটি ব্যবহার করার কয়েকটি কারণ রয়েছে যা সম্পর্কে আমি অবগত রয়েছি (কেউ কেউ এর সাথে ইতিমধ্যে কথা বলেছেন):
পরিষ্কারভাবে একটি ফাংশন থেকে প্রস্থান করা
প্রায়শই কোনও কার্যক্রমে, আপনি সংস্থানগুলি বরাদ্দ করতে পারেন এবং একাধিক জায়গায় প্রস্থান করতে হবে। প্রোগ্রামাররা ফাংশন শেষে রিসোর্স ক্লিনআপ কোডটি রেখে তাদের কোডটি সরল করতে পারে এবং ফাংশনের সমস্ত "প্রস্থানস্থান" ক্লিনআপ লেবেলটিতে যাবে। এইভাবে, আপনাকে ফাংশনের প্রতিটি "প্রস্থানস্থান" এ ক্লিনআপ কোড লিখতে হবে না।
নেস্টেড লুপগুলি প্রস্থান করা হচ্ছে
যদি আপনি কোনও নেস্টেড লুপে থাকেন এবং সমস্ত লুপগুলি ভেঙে ফেলার প্রয়োজন হয় তবে একটি গোটো ব্রেক স্টেটমেন্ট এবং যদি-চেকের চেয়ে এটিকে আরও পরিষ্কার এবং সহজ করে তুলতে পারে।
নিম্ন-স্তরের কর্মক্ষমতা উন্নতি
এটি কেবল পারফ-ক্রিটিকাল কোডে বৈধ, তবে গোটো স্টেটমেন্টগুলি খুব দ্রুত কার্যকর হয় এবং কোনও ফাংশনের মধ্য দিয়ে যাওয়ার সময় আপনাকে উত্সাহ দিতে পারে। এটি অবশ্য একটি দ্বি-তরোয়াল তরোয়াল, কারণ একটি সংকলক সাধারণত গোটোসযুক্ত কোডটিকে অনুকূল করতে পারে না।
নোট করুন যে এই সমস্ত উদাহরণে, গোটোসগুলি একটি ফাংশনের সুযোগের মধ্যে সীমাবদ্ধ।
goto
with return
is just silly. It's not "refactoring" anything, it's just "renaming" so that people who grew up in a goto
-suppressed environment (i.e. all of us) feel better about using what morally amounts to a goto
. I much prefer to see the loop where I use it and see a little goto
, which by itself is just a tool, than see someone having moved the loop somewhere unrelated just to avoid a goto
.
break
,continue
,return
are basically goto
, just in nice packaging.
do{....}while(0)
এটি জাভাতে কাজ করে না, বাদে গোটোর চেয়ে কীভাবে ভাল ধারণা হওয়ার কথা তা আমি দেখতে পাচ্ছি না ।
goto
প্রত্যক্ষ বা অপ্রত্যক্ষভাবে এডিজার ডিজকস্ট্রার গো টোকে ক্ষতিকারক নিবন্ধটি বিবেচনা করে তাদের অবস্থানকে দৃ .় করার জন্য বিরোধী- প্রত্যঙ্গ প্রত্যেকেই । খুব খারাপ খারাপ ডিজকাস্ত্রের নিবন্ধটির কার্যত এই দিনগুলিতে যেভাবে বিবৃতি ব্যবহৃত হচ্ছে তার সাথে কিছুই করার নেইgoto
এবং এইভাবে নিবন্ধ যা বলেছে তা আধুনিক প্রোগ্রামিং দৃশ্যে প্রয়োগযোগ্য নয় to goto
এখন একটি ধর্ম অ মেমে Verges, তার ধর্মগ্রন্থ করার অধিকার নিচে উচ্চ উচ্চ পুরোহিত এবং হৃদয়ঙ্গম ধর্মদ্রোহীতা পরিহার (বা তার থেকেও খারাপ) থেকে dictated।
বিষয়টিতে কিছুটা আলোকপাত করার জন্য ডিজকস্ট্রার কাগজ প্রসঙ্গে রাখি।
ডিজকસ્ત્રা যখন তাঁর কাগজটি লিখেছিলেন তখনকার জনপ্রিয় ভাষাগুলি ছিল বেসিক, ফোরট্রান (পূর্বের উপভাষা) এবং বিভিন্ন সমাবেশের ভাষাগুলির মতো অ-কাঠামোগত পদ্ধতিগত ভাষা। উচ্চ স্তরের ভাষাগুলি ব্যবহার করা লোকেরা তাদের কোড ভিত্তিতে সমস্ত বাঁকানো, সম্পাদিত থ্রোয়েড কোডগুলিতে ঝাঁপিয়ে পড়েছিল যা "স্প্যাগেটি কোড" শব্দটির জন্ম দেয়। আপনি মাইক মেফিল্ড দ্বারা রচিত ক্লাসিক ট্রেক গেমটি প্রত্যাখ্যান করে এবং জিনিসগুলি কীভাবে কাজ করে তা নির্ধারণের চেষ্টা করে এটি দেখতে পাবে। এটি দেখতে কয়েক মুহুর্ত নিন।
এই যে Dijkstra 1968 সালে তাঁর কাগজে বিরুদ্ধে রেলিং হয়েছিল "বিবৃতিতে যান এর লাগামহীন ব্যবহারের" হয় এই হয় পরিবেশ তিনি বসবাস করতেন যে তাকে কাগজে লিখতে নেতৃত্বে। আপনার কোডটিতে আপনার পছন্দ মতো যে কোনও জায়গায় আপনার পছন্দ মতো যে কোনও মুহুর্তে তিনি যা পছন্দ করেছিলেন তা হ'ল তিনি সমালোচনা করছেন এবং থামানোর দাবি করছেন। রক্তাল্পতার সাথে এর তুলনা করাgoto
in C or other such more modern languages is simply risible.
আমি ইতিমধ্যে ধর্মাবলম্বীদের মুখোমুখি হওয়ার সাথে সাথে সংস্কৃতিবিদদের উত্থিত মন্ত্রগুলি শুনতে পাচ্ছি। "তবে," তারা উচ্চারণ করবে, "আপনি কোড দিয়ে goto
সি তে খুব কঠিন পড়াতে পারেন " " ও আচ্ছা? আপনি কোড খুব goto
ভাল পড়া ছাড়া করতে পারবেন । এটার মত:
#define _ -F<00||--F-OO--;
int F=00,OO=00;main(){F_OO();printf("%1.3f\n",4.*-F/OO/OO);}F_OO()
{
_-_-_-_
_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_
_-_-_-_
}
নেই একটি goto
দৃষ্টিতে, তাই এটি হতে হবে সহজ, পড়তে ডান? বা এটি সম্পর্কে কীভাবে:
a[900]; b;c;d=1 ;e=1;f; g;h;O; main(k,
l)char* *l;{g= atoi(* ++l); for(k=
0;k*k< g;b=k ++>>1) ;for(h= 0;h*h<=
g;++h); --h;c=( (h+=g>h *(h+1)) -1)>>1;
while(d <=g){ ++O;for (f=0;f< O&&d<=g
;++f)a[ b<<5|c] =d++,b+= e;for( f=0;f<O
&&d<=g; ++f)a[b <<5|c]= d++,c+= e;e= -e
;}for(c =0;c<h; ++c){ for(b=0 ;b<k;++
b){if(b <k/2)a[ b<<5|c] ^=a[(k -(b+1))
<<5|c]^= a[b<<5 |c]^=a[ (k-(b+1 ))<<5|c]
;printf( a[b<<5|c ]?"%-4d" :" " ,a[b<<5
|c]);} putchar( '\n');}} /*Mike Laman*/
না goto
হয় নেই। সুতরাং এটি অবশ্যই পঠনযোগ্য।
এই উদাহরণগুলির সাথে আমার বক্তব্য কী? এটি এমন ভাষা বৈশিষ্ট্য নয় যা অপঠনযোগ্য, অনিবার্য কোড করে। এটি সিনট্যাক্স নয় যা এটি করে। এটি খারাপ প্রোগ্রামার যা এর কারণ। এবং খারাপ প্রোগ্রামারস, যেমন আপনি উপরের আইটেমটিতে দেখতে পাচ্ছেন যে কোনও ভাষার বৈশিষ্ট্য অপঠনযোগ্য এবং অযোগ্য। for
সেখানে লুপগুলি পছন্দ করুন । (আপনি এগুলি দেখতে পারেন, তাই না?)
এখন ন্যায়সঙ্গত হওয়ার জন্য, কিছু ভাষার গঠন অন্যের চেয়ে অপব্যবহার করা সহজ। আপনি যদি একজন সি প্রোগ্রামার হন তবে, আমি এর #define
বিরুদ্ধে ক্রুসেডে যাওয়ার আগে দীর্ঘ প্রায় 50% ব্যবহারের চেয়ে আরও ঘনিষ্ঠভাবে তাকাতে চাই goto
!
সুতরাং, যারা এই পর্যন্ত পড়তে বিরক্ত করেছেন তাদের জন্য কয়েকটি বিষয় উল্লেখযোগ্য।
goto
বিবৃতি একটি প্রোগ্রামিং পরিবেশ যেখানে জন্য লেখা হয়েছিল goto
একটি ছিল অনেক
বেশি সম্ভাব্য ক্ষতিকর তুলনায় এটি সবচেয়ে আধুনিক ভাষা একটি প্রতীকী ভাষান্তর নয় এমন নয়।goto
এটির কারণ হিসাবে সমস্ত ব্যবহার স্বয়ংক্রিয়ভাবে ছুঁড়ে ফেলা হচ্ছে "এটি একবার মজা করার চেষ্টা করেছি তবে এটি পছন্দ হয়নি তাই এখন আমি এর বিপক্ষে" sayinggoto
কোডে আধুনিক (অ্যানিমিক) স্টেটমেন্টের বৈধ ব্যবহার রয়েছে যা অন্য নির্মাণগুলি দ্বারা যথাযথভাবে প্রতিস্থাপন করা যায় না।godo
" ঘৃণার মতো অবৈধ ব্যবহার রয়েছে যেখানে " " এর জায়গায় do
ব্যবহার করে সর্বদা মিথ্যা লুপটি ভেঙে দেওয়া হয় । এগুলি প্রায়শই ন্যায়বিচারের ব্যবহারের চেয়ে খারাপ হয় ।break
goto
goto
goto
actually are (which is the question posted)
অন্ধভাবে সর্বোত্তম অনুশীলন মানা একটি সেরা অভ্যাস নয়। goto
প্রবাহ নিয়ন্ত্রণের কারও কারও প্রাথমিক রূপ হিসাবে বিবৃতি এড়িয়ে যাওয়ার ধারণাটি অপঠনযোগ্য স্প্যাগেটি কোড উত্পাদন করা এড়ানো। যদি সঠিক জায়গায় অল্প পরিমাণে ব্যবহার করা হয় তবে এগুলি কখনও কখনও কোনও ধারণা প্রকাশের সহজতম এবং সুস্পষ্ট উপায় হতে পারে। জোরটেক সি ++ সংকলক এবং ডি প্রোগ্রামিং ভাষার স্রষ্টা ওয়াল্টার ব্রাইট এগুলি প্রায়শই ব্যবহার করেন তবে ন্যায়বিচারের সাথে। এমনকি goto
বিবৃতি সহ, তার কোড এখনও নিখুঁতভাবে পঠনযোগ্য।
নীচের লাইন: goto
এড়ানোর খাতিরে এড়ানো goto
অর্থহীন। আপনি যা সত্যিই এড়াতে চান তা অপঠনযোগ্য কোড তৈরি করা। যদি আপনার- goto
বর্ধিত কোডটি পঠনযোগ্য হয়, তবে এতে কোনও ভুল নেই।
Since goto
makes reasoning about program flow hard1 (aka. “spaghetti code”), goto
is generally only used to compensate for missing features: The use of goto
may actually be acceptable, but only if the language doesn't offer a more structured variant to obtain the same goal. Take Doubt's example:
The rule with goto that we use is that goto is okay to for jumping forward to a single exit cleanup point in a function.
This is true – but only if the language doesn't allow structured exception handling with cleanup code (such as RAII or finally
), which does the same job better (as it is specially built for doing it), or when there's a good reason not to employ structured exception handling (but you will never have this case except at a very low level).
In most other languages, the only acceptable use of goto
is to exit nested loops. And even there it is almost always better to lift the outer loop into an own method and use return
instead.
Other than that, goto
is a sign that not enough thought has gone into the particular piece of code.
1 Modern languages which support goto
implement some restrictions (e.g. goto
may not jump into or out of functions) but the problem fundamentally remains the same.
Incidentally, the same is of course also true for other language features, most notably exceptions. And there are usually strict rules in place to only use these features where indicated, such as the rule not to use exceptions to control non-exceptional program flow.
finally
? So using exceptions for things other than error handling is good but using goto
is bad? I think exceptions are quite aptly named.
ঠিক আছে, একটি জিনিস যা সবসময় চেয়ে খারাপ হয় goto's
; গোটো এড়াতে অন্যান্য প্রোগ্রামফ্লো অপারেটরগুলির অদ্ভুত ব্যবহার:
উদাহরণ:
// 1
try{
...
throw NoErrorException;
...
} catch (const NoErrorException& noe){
// This is the worst
}
// 2
do {
...break;
...break;
} while (false);
// 3
for(int i = 0;...) {
bool restartOuter = false;
for (int j = 0;...) {
if (...)
restartOuter = true;
if (restartOuter) {
i = -1;
}
}
etc
etc
do{}while(false)
আমি মনে করি idiomatic হিসাবে বিবেচনা করা যেতে পারে। আপনার সাথে দ্বিমত পোষণ করার অনুমতি নেই: ডি
goto after_do_block;
এটি আসলে এটি না বলেই বলার এক উপায় । নাহলে ... এমন "লুপ" যা ঠিক একবারে চলে? আমি নিয়ন্ত্রণ কাঠামোর অপব্যবহার কল করব।
#define
কতগুলি goto
একবার, একবারে একবার ব্যবহার করার চেয়ে অনেক বেশি খারাপ : ডি
ইন সি # সুইচ বিবৃতি করছ অনুমতি দেয় না পড়ে-থ্রু । সুতরাং গেটো নির্দিষ্ট স্যুইচ-কেস লেবেল বা ডিফল্ট লেবেলে নিয়ন্ত্রণ স্থানান্তর করতে ব্যবহৃত হয় ।
উদাহরণ স্বরূপ:
switch(value)
{
case 0:
Console.Writeln("In case 0");
goto case 1;
case 1:
Console.Writeln("In case 1");
goto case 2;
case 2:
Console.Writeln("In case 2");
goto default;
default:
Console.Writeln("In default");
break;
}
সম্পাদনা: "কোনও পতনের মধ্য দিয়ে নেই" বিধিটিতে একটি ব্যতিক্রম রয়েছে। যদি কোনও কেস স্টেটমেন্টের কোনও কোড না থাকে তবে ফলস-থ্রো করার অনুমতি দেওয়া হয়।
goto case 5:
যখন 1 ক্ষেত্রে আছেন তখনই আপনি বলতে পারেন )। দেখে মনে হচ্ছে কনরাদ রুডল্ফের উত্তরটি এখানে সঠিক: goto
নিখোঁজ হওয়া বৈশিষ্ট্যের জন্য ক্ষতিপূরণ দিচ্ছে (এবং আসল বৈশিষ্ট্যটির চেয়ে কম পরিষ্কার)। আমরা আসলে যা চাই তা যদি পতিত হয় তবে সম্ভবত সেরা ডিফল্ট কোনও ফল-থ্রো নয়, তবে continue
স্পষ্টভাবে এটির জন্য অনুরোধ করতে চাই something
#ifdef TONGUE_IN_CHEEK
পার্লের একটি রয়েছে goto
যা আপনাকে দরিদ্র লোকের লেজ কলগুলি প্রয়োগ করতে দেয়। :-P
sub factorial {
my ($n, $acc) = (@_, 1);
return $acc if $n < 1;
@_ = ($n - 1, $acc * $n);
goto &factorial;
}
#endif
ঠিক আছে, সুতরাং সি এর সাথে এর কোন যোগসূত্র নেই goto
। আরও গুরুতরভাবে, আমি goto
ক্লিনআপগুলি ব্যবহার করার জন্য, বা ডাফের ডিভাইস প্রয়োগ করার জন্য বা অন্যান্য মতামত সম্পর্কে অন্যান্য মন্তব্যের সাথে একমত । এগুলি সবই ব্যবহার সম্পর্কে, গালি দেওয়া নয়।
(একই মন্তব্যটি প্রয়োগ করতে পারে longjmp
, ব্যতিক্রম call/cc
এবং এর মতো --- এর বৈধ ব্যবহার রয়েছে তবে সহজেই তাদের অপব্যবহার করা যেতে পারে example উদাহরণস্বরূপ, সম্পূর্ণ অ-ব্যতিক্রমী পরিস্থিতিতে গভীরভাবে বাসকারী নিয়ন্ত্রণ কাঠামোটি থেকে বাঁচার জন্য খাঁটিভাবে ব্যতিক্রম নিক্ষেপ করা ।)
আমি কয়েক বছর ধরে সমাবেশ ভাষা কয়েক লাইনের চেয়ে বেশি লিখেছি। শেষ পর্যন্ত, প্রতিটি উচ্চ স্তরের ভাষা গোটোতে সংকলিত হয়। ঠিক আছে, তাদের "শাখা" বা "লাফিয়ে" বা অন্য যাই হোক না কেন, তবে তারা গোটস। কেউ কি গোটো-অ্যাসেমব্লার লিখতে পারে?
এখন নিশ্চিত, আপনি কোনও ফোর্টরান, সি বা বেসিক প্রোগ্রামারকে নির্দেশ করতে পারেন যে গোটোসের সাথে দাঙ্গা চালানো স্প্যাগেটি বোলোগনাইজের একটি রেসিপি। উত্তরটি এগুলি এড়ানো নয়, সাবধানে সেগুলি ব্যবহার করা।
ছুরি খাবার তৈরি করতে, কাউকে মুক্ত করতে বা কাউকে হত্যা করার জন্য ব্যবহার করা যেতে পারে। আমরা কি পরের ভয়ে ছুরি ছাড়াই করি? একইভাবে গোটো: অযত্নে এটি বাধা দেয়, সতর্কতার সাথে ব্যবহৃত হয় এটি সহায়তা করে।
সি তে প্রোগ্রামিং করার সময় কখন গোটো ব্যবহার করতে হবে তা একবার দেখুন :
যদিও গোটোর ব্যবহার প্রায়শই খারাপ প্রোগ্রামিং অনুশীলন হয় (অবশ্যই আপনি এক্সওয়াইজেড করার আরও ভাল উপায় খুঁজে পেতে পারেন), এমন সময় রয়েছে যখন এটি সত্যই কোনও খারাপ পছন্দ নয়। কেউ কেউ এমনকি যুক্তিও দিতে পারে যে, যখন এটি কার্যকর হয়, এটি সেরা পছন্দ।
গোটো সম্পর্কে আমার যা বলতে হবে তা বেশিরভাগ ক্ষেত্রে কেবলমাত্র সি এর জন্য প্রযোজ্য আপনি যদি সি ++ ব্যবহার করেন তবে ব্যতিক্রমের জায়গায় গোটো ব্যবহার করার কোনও উপযুক্ত কারণ নেই। সি তে তবে আপনার একটি ব্যতিক্রম হ্যান্ডলিং মেকানিজমের ক্ষমতা নেই, সুতরাং আপনি যদি আপনার বাকি প্রোগ্রামের যুক্তি থেকে ত্রুটি হ্যান্ডলিং আলাদা করতে চান এবং আপনি আপনার কোড জুড়ে একাধিকবার সাফ কোড পুনরায় লেখা এড়াতে চান, তাহলে গেটো একটি ভাল পছন্দ হতে পারে।
আমার মানে কী? আপনার কাছে এমন কিছু কোড থাকতে পারে যা দেখতে এরকম দেখাচ্ছে:
int big_function()
{
/* do some work */
if([error])
{
/* clean up*/
return [error];
}
/* do some more work */
if([error])
{
/* clean up*/
return [error];
}
/* do some more work */
if([error])
{
/* clean up*/
return [error];
}
/* do some more work */
if([error])
{
/* clean up*/
return [error];
}
/* clean up*/
return [success];
}
এটি ঠিক আছে যতক্ষণ না আপনি বুঝতে পারবেন যে আপনার ক্লিনআপ কোডটি পরিবর্তন করা দরকার। তারপরে আপনাকে যেতে হবে এবং 4 টি পরিবর্তন করতে হবে। এখন, আপনি সিদ্ধান্ত নিতে পারেন যে আপনি কেবলমাত্র সমস্ত ক্লিনআপকে একটি একক ফাংশনে আবদ্ধ করতে পারেন; এটি একটি খারাপ ধারণা নয়। তবে এর অর্থ এই নয় যে আপনাকে পয়েন্টারগুলি সম্পর্কে সতর্কতা অবলম্বন করা উচিত - আপনি যদি আপনার ক্লিনআপ ফাংশনে কোনও পয়েন্টার মুক্ত করার পরিকল্পনা করেন তবে আপনি কোনও পয়েন্টারে একটি পয়েন্টারে না গিয়ে NULL এ সেট করার কোনও উপায় নেই। অনেক ক্ষেত্রে, আপনি আর যাইহোক সেই পয়েন্টারটি ব্যবহার করবেন না, যাতে এটি কোনও বড় উদ্বেগ নাও হতে পারে। অন্যদিকে, আপনি যদি কোনও নতুন পয়েন্টার, ফাইল হ্যান্ডেল বা অন্য কোনও জিনিস যা ক্লিনআপের জন্য যুক্ত করে থাকেন তবে আপনাকে আবার আপনার ক্লিনআপ ফাংশনটি পরিবর্তন করতে হবে; এবং তারপরে আপনাকে সেই ফাংশনে আর্গুমেন্টগুলি পরিবর্তন করতে হবে।
ব্যবহার করে goto
, এটি হবে
int big_function()
{
int ret_val = [success];
/* do some work */
if([error])
{
ret_val = [error];
goto end;
}
/* do some more work */
if([error])
{
ret_val = [error];
goto end;
}
/* do some more work */
if([error])
{
ret_val = [error];
goto end;
}
/* do some more work */
if([error])
{
ret_val = [error];
goto end;
}
end:
/* clean up*/
return ret_val;
}
এখানে সুবিধাটি হ'ল আপনার কোড অনুসরণের কোডটি পরিস্কার করার জন্য প্রয়োজনীয় সমস্ত কিছুতে অ্যাক্সেস রয়েছে এবং আপনি পরিবর্তন পয়েন্টের সংখ্যাটি যথেষ্ট পরিমাণে হ্রাস করতে সক্ষম হয়েছেন। আরেকটি সুবিধা হ'ল আপনি নিজের ফাংশনটির একাধিক প্রস্থান পয়েন্ট থেকে কেবল একটিতে চলে গেছেন; পরিষ্কার না করে আপনি ভুল করে ফাংশন থেকে ফিরে আসার কোনও সম্ভাবনা নেই।
এছাড়াও, যেহেতু গোটো কেবলমাত্র একটি বিন্দুতে লাফানোর জন্য ব্যবহৃত হচ্ছে, তাই আপনি ফাংশন কলগুলি অনুকরণ করার প্রয়াসে পিছনে পিছনে ঝাঁপিয়ে পড়া স্প্যাগেটি কোডের একটি ভর তৈরি করছেন বলে মনে হচ্ছে না। বরং, আসলে আরও কাঠামোগত কোড লিখতে সহায়তা করে।
এক কথায়, goto
সর্বদা অল্প পরিমাণে ব্যবহার করা উচিত, এবং শেষ উপায় হিসাবে - তবে এর জন্য একটি সময় এবং জায়গা রয়েছে। প্রশ্নটি "আপনার এটি ব্যবহার করতে হবে না" তবে এটি ব্যবহারের জন্য "এটি কি সেরা পছন্দ" হওয়া উচিত না?
গোটো খারাপ হওয়ার একটি কারণ, কোডিং শৈলীর পাশাপাশি আপনি ওভারল্যাপিং তৈরি করতে এটি ব্যবহার করতে পারেন তবে অ-নেস্টেড লুপগুলি:
loop1:
a
loop2:
b
if(cond1) goto loop1
c
if(cond2) goto loop2
এটি উদ্ভট, তবে সম্ভবত আইনী প্রবাহের নিয়ন্ত্রণ কাঠামো তৈরি করবে যেখানে একটি ক্রম (ক, খ, সি, বি, ক, বি, ক, বি, ...) সম্ভব, যা সংকলক হ্যাকারকে অসন্তুষ্ট করে তোলে। স্পষ্টতই বেশ কয়েকটি চতুর অপ্টিমাইজেশন কৌশল রয়েছে যা এই ধরণের কাঠামোর উপর নির্ভর করে না। (আমার ড্রাগন বইয়ের আমার অনুলিপিটি পরীক্ষা করা উচিত ...) এর ফলস্বরূপ (কিছু সংকলক ব্যবহার করে) এমন হতে পারে যে অন্যান্য অপ্টিমাইজেশানগুলি সে কোডগুলির জন্য করা হয়নি goto
।
এটি কার্যকর হতে পারে যদি আপনি কেবল এটি জানেন , "ওহ, উপায় দ্বারা", দ্রুত কোড নির্গমন করতে সংকলককে রাজি করায়। ব্যক্তিগতভাবে, আমি গোটোয়ের মতো কৌশল ব্যবহার করার আগে কী কী সম্ভাব্য এবং কী কী তা সম্পর্কে সংস্থাপককে ব্যাখ্যা করার চেষ্টা করতে পছন্দ করব তবে তর্কসাপেক্ষে, আমি goto
হ্যাকিং এসেম্বলারের আগে চেষ্টাও করতে পারি ।
goto
একটি দরকারী এটি হ'ল এটি আপনাকে এই জাতীয় লুপগুলি তৈরি করতে দেয়, অন্যথায় লজিক্যাল কনট্রোশনগুলির একটি গুচ্ছ প্রয়োজন হয়। আমি আরও যুক্তি দিই যে যদি অপ্টিমাইজার এটি কীভাবে পুনরায় লিখতে না জানেন তবে ভাল । এর মতো লুপটি পারফরম্যান্স বা পঠনযোগ্যতার জন্য করা উচিত নয়, তবে কারণ এটি হ'ল ক্রমটি যাতে ঘটতে হবে। কোন ক্ষেত্রে আমি বিশেষত অপটিমাইজারটিকে এটির সাথে ঘুরিয়ে দিতে চাই না।
আমি মজার বিষয়বোধ করি যে কিছু লোক গোটো গ্রহণযোগ্য এমন মামলার একটি তালিকা দেবে যতক্ষণ না এই বলে যে অন্য সমস্ত ব্যবহার অগ্রহণযোগ্য। আপনি কি সত্যিই মনে করেন যে প্রতিটি ক্ষেত্রেই আপনি জানেন যে অ্যালগরিদম প্রকাশের জন্য গোটোই সেরা পছন্দ?
উদাহরণস্বরূপ, আমি আপনাকে একটি উদাহরণ দেব যা এখানে কেউ এখনও দেখায় নি:
আজ আমি একটি হ্যাশ টেবিলে একটি উপাদান forোকানোর জন্য কোড লিখছিলাম। হ্যাশ টেবিলটি পূর্ববর্তী গণনার একটি ক্যাশ যা ইচ্ছায় ওভাররাইট করা যেতে পারে (পারফরম্যান্সকে প্রভাবিত করে তবে নির্ভুলতা নয়)।
হ্যাশ টেবিলের প্রতিটি বালতিতে 4 টি স্লট রয়েছে এবং বালতি পূর্ণ হলে কোন উপাদানটি ওভাররাইট করা হবে তা সিদ্ধান্ত নেওয়ার জন্য আমার কাছে অনেকগুলি মানদণ্ড রয়েছে। এই মুহূর্তে এর অর্থ একটি বালতি দিয়ে তিনটি পর্যন্ত যাত্রা করা, এরকম:
// Overwrite an element with same hash key if it exists
for (add_index=0; add_index < ELEMENTS_PER_BUCKET; add_index++)
if (slot_p[add_index].hash_key == hash_key)
goto add;
// Otherwise, find first empty element
for (add_index=0; add_index < ELEMENTS_PER_BUCKET; add_index++)
if ((slot_p[add_index].type == TT_ELEMENT_EMPTY)
goto add;
// Additional passes go here...
add:
// element is written to the hash table here
এখন যদি আমি গোটো ব্যবহার না করি তবে এই কোডটি কেমন দেখাচ্ছে?
এটার মতো কিছু:
// Overwrite an element with same hash key if it exists
for (add_index=0; add_index < ELEMENTS_PER_BUCKET; add_index++)
if (slot_p[add_index].hash_key == hash_key)
break;
if (add_index >= ELEMENTS_PER_BUCKET) {
// Otherwise, find first empty element
for (add_index=0; add_index < ELEMENTS_PER_BUCKET; add_index++)
if ((slot_p[add_index].type == TT_ELEMENT_EMPTY)
break;
if (add_index >= ELEMENTS_PER_BUCKET)
// Additional passes go here (nested further)...
}
// element is written to the hash table here
যদি আরও পাস যুক্ত করা হয় তবে এটি আরও খারাপ এবং খারাপ দেখাবে, যদিও গোটো সহ সংস্করণ সর্বদা একই ইন্ডেন্টেশন স্তরটি রাখে এবং যদি বিবৃতিযুক্ত ফলাফলগুলি পূর্ববর্তী লুপের প্রয়োগের দ্বারা বোঝানো হয় তবে বিব্রতকর ব্যবহার এড়ানো যায়।
সুতরাং আরও একটি মামলা রয়েছে যেখানে Goo কোডকে ক্লিনার এবং আরও সহজে লেখার এবং বোঝার সহজ করে তোলে ... আমি নিশ্চিত যে আরও অনেকগুলি রয়েছে, সুতরাং গোটো দরকারী যেখানে রয়েছে তার সমস্ত ক্ষেত্রে জানার ভান করবেন না, আপনি যে ভাল কিছু করতে পারছেন না তা বাতিল করে দিন ভাবেন না।
goto
প্রতিটি ফাংশনটি বিমূর্ততার একই স্তরের হওয়াতে যে কোনও বিরোধিতার চেয়ে অনেক বেশি গুরুত্বপূর্ণ । এটি এড়ানো goto
একটি বোনাস।
container::iterator it = slot_p.find(hash_key); if (it != slot_p.end()) it->overwrite(hash_key); else it = slot_p.find_first_empty();
আমি এই ধরণের প্রোগ্রামিং পড়তে অনেক সহজ মনে করি। এক্ষেত্রে প্রতিটি ফাংশন খাঁটি ফাংশন হিসাবে লেখা যেতে পারে, যা সম্পর্কে তর্ক করা খুব সহজ। মূল ফাংশনটি এখন ব্যাখ্যা করে যে কোডটি কেবল ফাংশনগুলির নাম দিয়ে কী করে এবং তারপরে আপনি চাইলে এটি কীভাবে এটি করে তা জানতে আপনি তাদের সংজ্ঞাটি দেখে নিতে পারেন।
গোটো সহ যে নিয়মটি আমরা ব্যবহার করি তা হ'ল কোনও ফাংশনে একক প্রস্থান ক্লিনআপ পয়েন্টে এগিয়ে যাওয়ার জন্য গোটো ঠিক আছে। সত্যিই জটিল ক্রিয়াকলাপগুলিতে আমরা অন্যান্য নিয়ম লাফিয়ে এগিয়ে যাওয়ার নিয়মটি শিথিল করি। উভয় ক্ষেত্রেই আমরা গভীরভাবে ঘৃণ্যতা এড়াচ্ছি যদি প্রায়শই ত্রুটি কোড চেকিংয়ের সাথে ঘটে এমন বিবৃতি, যা পাঠযোগ্যতা এবং রক্ষণাবেক্ষণে সহায়তা করে।
"গুনী গোটো স্টেটমেন্ট" এর জায়গায় ব্যবহার করা যেতে পারে তবে গোটো স্টেটমেন্টের মতো সহজেই অপব্যবহার করা যায় গোটো স্টেটমেন্ট, তাদের বৈধ ব্যবহারসমূহ এবং বিকল্প কাঠামোগুলির সর্বাধিক চিন্তাশীল এবং পুঙ্খানুপুঙ্খ আলোচনা হ'ল ডোনাল্ড নুথের নিবন্ধ " গেটো স্টেটমেন্ট সহ স্ট্রাকচার্ড প্রোগ্রামিং " , ডিসেম্বর 1974 এর কম্পিউটিং সার্ভেগুলিতে (আয়তন 6, নং 4. পিপি 261 - 301)।
অবাক হওয়ার মতো বিষয় নয়, 39 বছরের পুরানো এই গবেষণাপত্রের কয়েকটি দিক তারিখযুক্ত: প্রসেসিং পাওয়ারের ক্রমবর্ধমান অর্ডারগুলি নুথের কিছু কর্মক্ষমতা উন্নতকে মাঝারি আকারের সমস্যার জন্য অপ্রয়োজনীয় করে তোলে এবং এর পর থেকে নতুন প্রোগ্রামিং-ল্যাঙ্গুয়েজ কনস্ট্রাক্টগুলি আবিষ্কার করা হয়েছিল। (উদাহরণস্বরূপ, ট্রাই-ক্যাচ ব্লকগুলি জাহ্নের কন্সট্রাক্টকে গ্রাহ্য করে, যদিও সেগুলি খুব কমই ব্যবহৃত হয়)
পার্ল মডিউলে আপনি মাঝে মাঝে ফ্লাইতে সাবরুটাইন বা ক্লোজার তৈরি করতে চান। জিনিসটি হ'ল, একবার সাবউটাইন তৈরি করার পরে আপনি কীভাবে এটি পেতে পারেন। আপনি কেবল এটি কল করতে পারেন, তবে তারপরে যদি সাবরুটাইন ব্যবহার করে তবে caller()
এটি ততটা সহায়ক হবে না। এই যেখানে goto &subroutine
প্রকরণটি সহায়ক হতে পারে।
sub AUTOLOAD{
my($self) = @_;
my $name = $AUTOLOAD;
$name =~ s/.*:://;
*{$name} = my($sub) = sub{
# the body of the closure
}
goto $sub;
# nothing after the goto will ever be executed.
}
আপনি এই ফর্মটি goto
টেল-কল অপ্টিমাইজেশানের একটি প্রাথমিক রূপ সরবরাহ করতেও ব্যবহার করতে পারেন ।
sub factorial($){
my($n,$tally) = (@_,1);
return $tally if $n <= 1;
$tally *= $n--;
@_ = ($n,$tally);
goto &factorial;
}
( পার্ল 5 সংস্করণ 16 এ আরও ভাল লেখা হবে goto __SUB__;
)
এমন একটি মডিউল রয়েছে যা একটি tail
সংশোধক এবং একটি আমদানি করবে যা আপনি recur
যদি এই ফর্মটি ব্যবহার না করতে পছন্দ করেন তবে আমদানি করবে goto
।
use Sub::Call::Tail;
sub AUTOLOAD {
...
tail &$sub( @_ );
}
use Sub::Call::Recur;
sub factorial($){
my($n,$tally) = (@_,1);
return $tally if $n <= 1;
recur( $n-1, $tally * $n );
}
goto
অন্যান্য কীওয়ার্ড দিয়ে আরও ভালভাবে সম্পন্ন হয়।redo
কিছুটা কোড ইনগ করার মতো :
LABEL: ;
...
goto LABEL if $x;
{
...
redo if $x;
}
বা last
একাধিক জায়গা থেকে কোডের একটি বিট যেতে:
goto LABEL if $x;
...
goto LABEL if $y;
...
LABEL: ;
{
last if $x;
...
last if $y
...
}
যদি তাই হয় তবে কেন?
সি এর কোনও মাল্টি-লেভেল / লেবেল বিরতি নেই এবং সমস্ত নিয়ন্ত্রণ প্রবাহ সহজে সি এর পুনরাবৃত্তি এবং সিদ্ধান্তের আদিমতার সাথে মডেল করা যায় না। এই ত্রুটিগুলি নিরসনের দিকে এগিয়ে চলেছে।
কখনও কখনও এটি এক ধরণের সিউডো-মাল্টি-লেভেল ব্রেককে প্রভাবিত করতে কোনও ধরণের ফ্ল্যাগ ভেরিয়েবল ব্যবহার করা আরও পরিষ্কার হয় তবে এটি সর্বদা গোটোর চেয়ে উচ্চতর হয় না (কমপক্ষে একটি গিটো পতাকাটির পরিবর্তনশীলের বিপরীতে নিয়ন্ত্রণটি কোথায় যায় তা সহজেই নির্ধারণ করতে দেয়) ), এবং কখনও কখনও আপনি খুব সহজেই এড়াতে পতাকাগুলি / অন্যান্য সংযোজনগুলির পারফরম্যান্স মূল্য দিতে চান না।
libavcodec একটি পারফরম্যান্স-সংবেদনশীল কোড। নিয়ন্ত্রণ প্রবাহের সরাসরি প্রকাশ সম্ভবত একটি অগ্রাধিকার, কারণ এটি আরও ভালভাবে চালানোর ঝোঁক পাবে।
(মিথ্যা) ব্যবহারের পুরোপুরি বিদ্রোহ করার সময় আমি করণীয়টি পাই। এটা অনুমেয় যে আমাকে কিছুটা বিজোড় ক্ষেত্রে এটি প্রয়োজন তা বোঝাতে পারে তবে এটি কখনই পরিষ্কার ধারণাযোগ্য কোড নয়।
আপনার যদি এমন কিছু লুপ করতেই হয় তবে পতাকা পরিবর্তকের উপর নির্ভরতা সুস্পষ্টভাবে কেন তৈরি করবেন না?
for (stepfailed=0 ; ! stepfailed ; /*empty*/)
/*empty*/
হবে stepfailed = 1
? যে কোনও ক্ষেত্রে এটি কীভাবে ভাল do{}while(0)
? উভয় ক্ষেত্রেই আপনাকে break
এটি (বা আপনার মধ্যে stepfailed = 1; continue;
) এড়িয়ে চলতে হবে । আমার কাছে অপ্রয়োজনীয় মনে হচ্ছে।
1) আমি জানি যে গোটোর সবচেয়ে সাধারণ ব্যবহারটি হ'ল যে ভাষাগুলি এটির প্রস্তাব দেয় না তাদের ব্যতিক্রম হ্যান্ডলিং অনুকরণ করে, যেমন সি তে (উপরে নিউক্লিয়ার প্রদত্ত কোডটি ঠিক এটি।) লিনাক্স উত্স কোডটি দেখুন এবং আপনি ' দেখব একজন বাজিলিয়ান গোটোস সেভাবে ব্যবহৃত হয়েছে; : একটি দ্রুত জরিপ 2013 সালে পরিচালিত অনুযায়ী লিনাক্স কোডে 100,000 সম্পর্কে gotos ছিল http://blog.regehr.org/archives/894 । লিনাক্স কোডিং স্টাইল গাইডেও গোটো ব্যবহারের কথা উল্লেখ করা হয়েছে: https://www.kernel.org/doc/Docamentation/CodingStyle । যেমন অবজেক্ট ওরিয়েন্টেড প্রোগ্রামিং ফাংশন পয়েন্টার দিয়ে জনিত স্ট্র্ট ব্যবহার করে অনুকরণ করা হয়, তেমন সি প্রোগ্রামিংয়ে গোটোর স্থান রয়েছে। তাহলে কে সঠিক: ডিজকস্ট্রা বা লিনাস (এবং সমস্ত লিনাক্স কার্নেল কোডার)? এটি তত্ত্ব বনাম অনুশীলন মূলত।
সংকলন-স্তরের সমর্থন না থাকায় এবং সাধারণ নির্মাণ / নিদর্শনগুলির জন্য চেক না পাওয়ার জন্য সাধারণত গোটচা রয়েছে: সেগুলি ভুল ব্যবহার করা এবং সংকলন-সময় চেক না করে বাগ প্রবর্তন করা আরও সহজ। উইন্ডোজ এবং ভিজ্যুয়াল সি ++ তবে সি মোডে এসইএইচ / ভিইএইচ-এর মাধ্যমে ব্যতিক্রম হ্যান্ডলিংয়ের জন্য খুব একই কারণে অফার রয়েছে: ব্যতিক্রমগুলি ওওপি ভাষার বাইরেও অর্থাত্ একটি পদ্ধতিগত ভাষায় কার্যকর। তবে সংকলকটি সর্বদা আপনার বেকন সংরক্ষণ করতে পারে না, এমনকি এটি ভাষাতে ব্যতিক্রমগুলির জন্য সিনট্যাক্টিক সমর্থন সরবরাহ করে। আধুনিক অ্যাপল এসএসএল "গেটো ফেইল" বাগটি পরবর্তীকালের উদাহরণ হিসাবে বিবেচনা করুন, যা কেবলমাত্র এক গোটোকে বিপদজনক পরিণতির সাথে ডুপ্লিকেট করেছে ( https://www.imperialviolet.org/2014/02/22/applebug.html ):
if (something())
goto fail;
goto fail; // copypasta bug
printf("Never reached\n");
fail:
// control jumps here
সংকলক-সমর্থিত ব্যতিক্রমগুলি ব্যবহার করে আপনার ঠিক একই বাগ থাকতে পারে, যেমন সি ++ তে:
struct Fail {};
try {
if (something())
throw Fail();
throw Fail(); // copypasta bug
printf("Never reached\n");
}
catch (Fail&) {
// control jumps here
}
সংকলক যদি অ্যাক্সেসযোগ্য কোড সম্পর্কে আপনাকে বিশ্লেষণ করে এবং সতর্ক করে দেয় তবে বাগের উভয় রূপ এড়ানো যেতে পারে। উদাহরণস্বরূপ / ডাব্লু 4 সতর্কতা স্তরে ভিজ্যুয়াল সি ++ দিয়ে সংকলন করার ক্ষেত্রে উভয় ক্ষেত্রেই বাগটি খুঁজে পাওয়া যায়। উদাহরণস্বরূপ জাভা একটি খুব ভাল কারণে অ্যাক্সেসযোগ্য কোড (যেখানে এটি এটি সন্ধান করতে পারে!) নিষিদ্ধ করেছে: এটি সম্ভবত জো এর কোডে একটি বাগ হতে পারে। যতক্ষণ না গেটো কনস্ট্রাক্ট লক্ষ্যগুলি মঞ্জুরি দেয় না যে সংকলক সহজেই বের করতে পারে না, যেমন গোটোসকে গণনা করা ঠিকানাগুলি (**) হিসাবে, ডিজকস্ট্রার ব্যবহারের চেয়ে গোটোসের সাথে কোনও ফাংশনের অভ্যন্তরে অ্যাক্সেসযোগ্য কোড খুঁজে পাওয়া কোনও কমপ্লায়ার নয় not অনুমোদিত কোড
(**) পাদটীকা: বেসিকের কয়েকটি সংস্করণে গুন থেকে গণিত লাইন সংখ্যাগুলি সম্ভব, যেমন গোটো 10 * এক্স যেখানে এক্স একটি পরিবর্তনশীল। বরং বিভ্রান্তিকরভাবে, ফোর্টরানে "গণিত গোটো" সি এর একটি সুইচ স্টেটমেন্টের সমতুল্য এমন একটি কনস্ট্রাক্টকে বোঝায় যে স্ট্যান্ডার্ড সি ভাষায় গণিত গোটোসকে অনুমতি দেয় না, তবে কেবল স্ট্যাটিকাল / সিনট্যাক্টিকালি ঘোষিত লেবেলের গোটোস os GNU C তবে একটি লেবেলের ঠিকানা পাওয়ার জন্য একটি এক্সটেনশন রয়েছে (অ্যানারি, উপসর্গ && অপারেটর) এবং শূন্য * প্রকারের একটি চলকটিতে গোটোকে অনুমতি দেয়। এই অস্পষ্ট সাব-বিষয় সম্পর্কে আরও জানতে https://gcc.gnu.org/onlinesocs/gcc/Labels-as-Vueues.html দেখুন । এই পোস্টের বাকি অংশগুলি সেই অস্পষ্ট GNU সি বৈশিষ্ট্যের সাথে সম্পর্কিত নয়।
স্ট্যান্ডার্ড সি (অর্থাত গণনা করা হয়নি) গোটোস সাধারণত সঙ্কলনের সময় অ্যাক্সেসযোগ্য কোডটি সন্ধান করার কারণ নয়। সাধারণ কারণ হ'ল নীচের মত লজিক কোড। প্রদত্ত
int computation1() {
return 1;
}
int computation2() {
return computation1();
}
সংকলকের পক্ষে নিম্নলিখিত 3 টির মধ্যে যে কোনও একটিতে অ্যাক্সেসযোগ্য কোড খুঁজে পাওয়া ঠিক যেমন কঠিন:
void tough1() {
if (computation1() != computation2())
printf("Unreachable\n");
}
void tough2() {
if (computation1() == computation2())
goto out;
printf("Unreachable\n");
out:;
}
struct Out{};
void tough3() {
try {
if (computation1() == computation2())
throw Out();
printf("Unreachable\n");
}
catch (Out&) {
}
}
(আমার ব্রেস-সম্পর্কিত কোডিং স্টাইলটি ক্ষমা করুন, তবে আমি উদাহরণগুলি যতটা সম্ভব কমপ্যাক্ট রাখার চেষ্টা করেছি))
ভিজ্যুয়াল সি ++ / ডাব্লু 4 (এমনকি / অক্স সাথেও) এর যে কোনও একটিতে অ্যাক্সেসযোগ্য কোড সন্ধান করতে ব্যর্থ হয় এবং আপনি সম্ভবত জানেন যে অ্যাক্সেসযোগ্য কোড সন্ধান করার সমস্যাটি সাধারণভাবে অনস্বীকার্য। (আপনি যদি আমার সম্পর্কে বিশ্বাস না করেন তবে: https://www.cl.cam.ac.uk/teaching/2006/OptComp/slides/lecture02.pdf )
সম্পর্কিত সমস্যা হিসাবে, সি গোটো কেবল কোনও ফাংশনের শরীরে ব্যতিক্রম অনুকরণ করতে ব্যবহার করা যেতে পারে। অ-স্থানীয় প্রস্থান / ব্যাতিক্রমগুলি অনুকরণের জন্য স্ট্যান্ডার্ড সি লাইব্রেরিতে একটি সেটজ্যাম্প () এবং লংজ্যাম্প () জোড় যুক্ত করে, তবে অন্যান্য ভাষার অফারগুলির তুলনায় সেগুলির কিছু গুরুতর ত্রুটি রয়েছে। উইকিপিডিয়া নিবন্ধ http://en.wikedia.org/wiki/Setjmp.h এই উত্তরোত্তর বিষয়টি মোটামুটিভাবে ব্যাখ্যা করেছে। এই ফাংশন জুটি উইন্ডোজেও কাজ করে ( http://msdn.microsoft.com/en-us/library/yz2ez4as.aspx ) , তবে এসইএইচ / ভিইএইচ উচ্চতর যেহেতু কেউই এগুলি ব্যবহার করে না। এমনকি ইউনিক্সেও আমি মনে করি সেটজ্যাম্প এবং লংজ্যাম্প খুব কমই ব্যবহৃত হয়।
2) আমি মনে করি সি তে গোটোর দ্বিতীয় সাধারণ ব্যবহার বহু-স্তরের বিরতি বা মাল্টি-লেভেল চালিয়ে যাওয়া বাস্তবায়ন করছে, এটিও মোটামুটি একটি বিতর্কিত ব্যবহারের ক্ষেত্রে। মনে রাখবেন যে জাভা গোটো লেবেলকে অনুমতি দেয় না, তবে ব্রেক লেবেল বা লেবেল চালিয়ে যাওয়ার অনুমতি দেয়। Http://www.oracle.com/technetwork/java/simple-14261616ttml এর মতে , এটি আসলে সিতে গোটোসের সবচেয়ে সাধারণ ব্যবহারের ঘটনা (90% তারা বলে) তবে আমার বিষয়গত অভিজ্ঞতায় সিস্টেম কোড প্রবণতা দেখায় আরও প্রায়শই হ্যান্ডল করার জন্য গোটোস ব্যবহার করতে। সম্ভবত বৈজ্ঞানিক কোডে বা যেখানে ওএস ব্যতিক্রম হ্যান্ডলিং (উইন্ডোজ) অফার করে তবে মাল্টি-লেভেল এক্সিটগুলি হ'ল প্রভাবশালী ব্যবহারের ক্ষেত্রে। তারা তাদের জরিপের প্রসঙ্গে সত্যই কোনও বিবরণ দেয় না।
যোগ করার জন্য সম্পাদিত: এতে দেখা যাচ্ছে যে এই দুটি ব্যবহারের নিদর্শনগুলি পৃষ্ঠার 60 পৃষ্ঠার (সংস্করণের উপর নির্ভর করে) কাছাকাছি, কর্নিগান এবং রিচির সি বইটিতে পাওয়া যায়। আরেকটি বিষয় লক্ষ্য করুন যে উভয় ব্যবহারের ক্ষেত্রে কেবল ফরওয়ার্ড গোটোস জড়িত। এবং দেখা যাচ্ছে যে মিশ্র সি 2012 সংস্করণটি (2004 এর সংস্করণের বিপরীতে) এখন পর্যন্ত গোটোকে অনুমতি দেয়, যতক্ষণ না তারা কেবল ফরোয়ার্ড থাকে।
কেউ কেউ বলেন যে সি ++ এ যাওয়ার জন্য কোনও কারণ নেই। কেউ কেউ বলেন যে 99% ক্ষেত্রে আরও ভাল বিকল্প রয়েছে। এটি যুক্তি নয়, কেবল অযৌক্তিক ছাপ। এখানে একটি দৃ example় উদাহরণ রয়েছে যেখানে গোটো একটি দুর্দান্ত কোডের দিকে নিয়ে যায়, ডু-উইল লুপের মতো উন্নত:
int i;
PROMPT_INSERT_NUMBER:
std::cout << "insert number: ";
std::cin >> i;
if(std::cin.fail()) {
std::cin.clear();
std::cin.ignore(1000,'\n');
goto PROMPT_INSERT_NUMBER;
}
std::cout << "your number is " << i;
এটি গোটো-ফ্রি কোডের সাথে তুলনা করুন:
int i;
bool loop;
do {
loop = false;
std::cout << "insert number: ";
std::cin >> i;
if(std::cin.fail()) {
std::cin.clear();
std::cin.ignore(1000,'\n');
loop = true;
}
} while(loop);
std::cout << "your number is " << i;
আমি এই পার্থক্যগুলি দেখতে পাচ্ছি:
{}
ব্লক প্রয়োজন (যদিও do {...} while
আরও পরিচিত মনে হচ্ছে)loop
চারটি জায়গায় অতিরিক্ত ভেরিয়েবলের প্রয়োজনloop
loop
কোনও ডেটা ধারণ করে না, এটি কেবলমাত্র কার্যকর সম্পাদনের প্রবাহকে নিয়ন্ত্রণ করে, যা সাধারণ লেবেলের চেয়ে কম বোধগম্যএর আরও একটি উদাহরণ রয়েছে
void sort(int* array, int length) {
SORT:
for(int i=0; i<length-1; ++i) if(array[i]>array[i+1]) {
swap(data[i], data[i+1]);
goto SORT; // it is very easy to understand this code, right?
}
}
এবার আসুন "দুষ্ট" গোটো থেকে মুক্তি পাওয়া যাক:
void sort(int* array, int length) {
bool seemslegit;
do {
seemslegit = true;
for(int i=0; i<length-1; ++i) if(array[i]>array[i+1]) {
swap(data[i], data[i+1]);
seemslegit = false;
}
} while(!seemslegit);
}
আপনি দেখতে পাচ্ছেন যে এটি একই ধরণের গোটো ব্যবহারের মতো, এটি ভাল কাঠামোগত প্যাটার্ন এবং এটি কেবলমাত্র প্রস্তাবিত উপায় হিসাবে প্রচার করার উদ্দেশ্যে এগিয়ে যায় না। অবশ্যই আপনি এই জাতীয় "স্মার্ট" কোড এড়াতে চান:
void sort(int* array, int length) {
for(int i=0; i<length-1; ++i) if(array[i]>array[i+1]) {
swap(data[i], data[i+1]);
i = -1; // it works, but WTF on the first glance
}
}
মুল বক্তব্যটি হ'ল গোটো সহজেই অপব্যবহার করতে পারে তবে গোটো নিজেই দোষ দেবে না। নোট করুন যে লেবেলটির সি ++ তে কার্যকারিতা রয়েছে, তাই এটি বিশুদ্ধ সমাবেশের মতো বৈশ্বিক সুযোগকে দূষিত করে না, যেখানে ওভারল্যাপিং লুপগুলির নিজস্ব স্থান রয়েছে এবং এটি খুব সাধারণ - যেমন 8051 এর জন্য নিম্নলিখিত কোডটির মতো যেখানে 7 সেগমেন্ট ডিসপ্লে পি 1 এর সাথে সংযুক্ত রয়েছে। প্রোগ্রামটি চারদিকে বিদ্যুৎ বিভাগকে লুপ করে:
; P1 states loops
; 11111110 <-
; 11111101 |
; 11111011 |
; 11110111 |
; 11101111 |
; 11011111 |
; |_________|
init_roll_state:
MOV P1,#11111110b
ACALL delay
next_roll_state:
MOV A,P1
RL A
MOV P1,A
ACALL delay
JNB P1.5, init_roll_state
SJMP next_roll_state
এর আরও একটি সুবিধা রয়েছে: গোটো নামযুক্ত লুপ, শর্ত এবং অন্যান্য প্রবাহ হিসাবে পরিবেশন করতে পারে:
if(valid) {
do { // while(loop)
// more than one page of code here
// so it is better to comment the meaning
// of the corresponding curly bracket
} while(loop);
} // if(valid)
অথবা আপনি ইনডেন্টেশনের সাথে সমতুল্য গোটো ব্যবহার করতে পারেন, সুতরাং আপনি যদি সঠিকভাবে লেবেলের নামটি বেছে নেন তবে আপনার মন্তব্য করার প্রয়োজন নেই:
if(!valid) goto NOTVALID;
LOOPBACK:
// more than one page of code here
if(loop) goto LOOPBACK;
NOTVALID:;
পার্লে, একটি লুপ থেকে "গোটো" তে একটি লেবেল ব্যবহার করুন - "শেষ" বিবৃতিটি ব্যবহার করুন, যা বিরতির মতো।
এটি নেস্টেড লুপগুলির উপর আরও ভাল নিয়ন্ত্রণের অনুমতি দেয়।
ঐতিহ্যগত এতে যান ট্যাগ খুব সমর্থিত নয়, তবে আমি নই নিশ্চিত অত্যধিক দৃষ্টান্ত যেখানে এই একমাত্র উপায় অর্জনে কি আপনি চান হয় - সাবরুটিনের এবং loops বেশিরভাগ ক্ষেত্রেই জন্য যথেষ্ট হবে।
goto &subroutine
। যা স্ট্রকে বর্তমান সাবরুটিন প্রতিস্থাপন করার সাথে সাথে বর্তমান @_ দিয়ে সাব্রোটিন শুরু করে।
'গোটো' এবং 'গোটো-কম প্রোগ্রামিং' আন্দোলনের সর্বাধিক গুরুত্বপূর্ণ যুক্তিটি হ'ল সমস্যাটি হ'ল আপনি যদি খুব বেশি ঘন ঘন এটি ব্যবহার করেন তবে আপনার কোডটি এটি সঠিকভাবে আচরণ করতে পারে, অপঠনযোগ্য, অচিন্তনীয়, অপরিবর্তনীয় ইত্যাদি হয়ে যায় 99.99% এর মধ্যে কেস 'গোটো' স্প্যাগেটি কোডের দিকে নিয়ে যায়। ব্যক্তিগতভাবে, আমি কেন 'গোটো' ব্যবহার করব সে সম্পর্কে কোনও ভাল কারণ আমি ভাবতে পারি না।
goto
) অন্তর্ভুক্ত করার ব্যয়কে মাপার জন্য একটি যুক্তিযুক্ত যুক্তি হতে পারে । @ সিএসচোলের ব্যবহার একই রকম: সম্ভবত এখনই কোনও ভাষা ডিজাইন করছেন না, (গুলি) তিনি মূলত ডিজাইনারের প্রচেষ্টাটিকে মূল্যায়ন করছেন।
goto
প্রেক্ষাপট বাদে যেখানে ভাষা পরিবর্তন করতে পারে তা বাদ দিয়ে, যে সকল ধরণের নিয়ন্ত্রণ কাঠামোর কারও প্রয়োজন প্রয়োজন সমর্থন করার চেয়ে সস্তা হওয়া উপযুক্ত a goto
অন্য কোনও কাঠামো ব্যবহারের মতো লেখার কোডটি তেমন সুন্দর নাও হতে পারে তবে এ জাতীয় কোডটি লিখতে সক্ষম goto
হওয়া "অভিব্যক্তির ছিদ্র" এড়াতে সহায়তা করবে - এমন একটি কাঠামো যার জন্য কোনও ভাষা দক্ষ কোড লিখতে অক্ষম।
goto
কোড পর্যালোচনা সাইটে থাকা কোড পোস্ট করে , goto
ব্যাপকভাবে মুছে ফেলা কোডটির যুক্তি সহজ করে দেয়।
GOTO অবশ্যই ব্যবহার করা যেতে পারে, তবে কোড শৈলীর চেয়ে আরও একটি গুরুত্বপূর্ণ বিষয় রয়েছে, বা কোডটি ব্যবহার করার সময় আপনার অবশ্যই মনে রাখা উচিত বা পাঠযোগ্য নয়: ভিতরে কোডটি আপনার মতো শক্তিশালী নাও হতে পারে ভাবুন ।
উদাহরণস্বরূপ, নিম্নলিখিত দুটি কোড স্নিপেটগুলি দেখুন:
If A <> 0 Then A = 0 EndIf
Write("Value of A:" + A)
GOTO সহ সমতুল্য কোড
If A == 0 Then GOTO FINAL EndIf
A = 0
FINAL:
Write("Value of A:" + A)
প্রথম যে জিনিসটি আমরা ভাবি তা হ'ল কোডের উভয় বিটের ফলাফলটি হবে "A এর মান: 0" (আমরা অবশ্যই সমান্তরালতা ছাড়াই একটি মৃত্যুদন্ড কার্যকর বলে মনে করি)
এটি সঠিক নয়: প্রথম নমুনায়, এ সর্বদা 0 হবে, তবে দ্বিতীয় নমুনায় (গোটো স্টেটমেন্ট সহ) এ 0 হবে না কেন? কেন?
কারণটি কারণ প্রোগ্রামটির অন্য একটি বিন্দু থেকে আমি একটি sertোকাতে পারি GOTO FINAL
এ এর মান নিয়ন্ত্রণ না করে একটি sertোকাতে পারি
এই উদাহরণটি খুব সুস্পষ্ট, তবে প্রোগ্রামগুলি আরও জটিল হওয়ার সাথে সাথে এই জাতীয় জিনিসগুলি দেখার অসুবিধা বৃদ্ধি পায়।
সম্পর্কিত উপাদান জনাব Djkstra "" যাও যাও বিবৃতি বিরুদ্ধে একটি মামলা " থেকে বিখ্যাত নিবন্ধ পাওয়া যাবে
আমি নিম্নলিখিত ক্ষেত্রে গোটো ব্যবহার করি: যখন বিভিন্ন স্থানে ফানকিশন থেকে ফিরে আসার প্রয়োজন হয়, এবং ফিরে আসার আগে কিছুটা অনিদিয়করণ করা দরকার:
নন-গোটো সংস্করণ:
int doSomething (struct my_complicated_stuff *ctx)
{
db_conn *conn;
RSA *key;
char *temp_data;
conn = db_connect();
if (ctx->smth->needs_alloc) {
temp_data=malloc(ctx->some_size);
if (!temp_data) {
db_disconnect(conn);
return -1;
}
}
...
if (!ctx->smth->needs_to_be_processed) {
free(temp_data);
db_disconnect(conn);
return -2;
}
pthread_mutex_lock(ctx->mutex);
if (ctx->some_other_thing->error) {
pthread_mutex_unlock(ctx->mutex);
free(temp_data);
db_disconnect(conn);
return -3;
}
...
key=rsa_load_key(....);
...
if (ctx->something_else->error) {
rsa_free(key);
pthread_mutex_unlock(ctx->mutex);
free(temp_data);
db_disconnect(conn);
return -4;
}
if (ctx->something_else->additional_check) {
rsa_free(key);
pthread_mutex_unlock(ctx->mutex);
free(temp_data);
db_disconnect(conn);
return -5;
}
pthread_mutex_unlock(ctx->mutex);
free(temp_data);
db_disconnect(conn);
return 0;
}
গেটো সংস্করণ:
int doSomething_goto (struct my_complicated_stuff *ctx)
{
int ret=0;
db_conn *conn;
RSA *key;
char *temp_data;
conn = db_connect();
if (ctx->smth->needs_alloc) {
temp_data=malloc(ctx->some_size);
if (!temp_data) {
ret=-1;
goto exit_db;
}
}
...
if (!ctx->smth->needs_to_be_processed) {
ret=-2;
goto exit_freetmp;
}
pthread_mutex_lock(ctx->mutex);
if (ctx->some_other_thing->error) {
ret=-3;
goto exit;
}
...
key=rsa_load_key(....);
...
if (ctx->something_else->error) {
ret=-4;
goto exit_freekey;
}
if (ctx->something_else->additional_check) {
ret=-5;
goto exit_freekey;
}
exit_freekey:
rsa_free(key);
exit:
pthread_mutex_unlock(ctx->mutex);
exit_freetmp:
free(temp_data);
exit_db:
db_disconnect(conn);
return ret;
}
দ্বিতীয় সংস্করণটি সহজ করে তোলে, যখন আপনাকে ডিওলোকেশন স্টেটমেন্টগুলিতে কিছু পরিবর্তন করতে হবে (প্রতিটি কোডে একবার ব্যবহার করা হয়), এবং কোনও নতুন শাখা যুক্ত করার পরে সেগুলির কোনওটি বাদ দেওয়ার সুযোগ হ্রাস করে। এগুলিকে কোনও ফাংশনে স্থানান্তরিত করা এখানে সহায়তা করবে না, কারণ বিলোপটি বিভিন্ন "স্তরে" করা যেতে পারে।
finally
সি # তে ব্লক রয়েছে
finally
)। বিকল্প হিসাবে, goto
গুলি ব্যবহার করুন , তবে একটি সাধারণ প্রস্থান বিন্দুতে, যা সর্বদা সমস্ত পরিষ্কার-পরিচ্ছন্নতা করে। তবে প্রতিটি ক্লিন-আপ পদ্ধতি হয় হয় এমন কোনও মানকে পরিচালনা করতে পারে যা শূন্য বা ইতিমধ্যে পরিষ্কার, বা শর্তসাপেক্ষ পরীক্ষা দ্বারা সুরক্ষিত থাকে, যখন উপযুক্ত না হয় এড়িয়ে যায়।
goto
সমস্ত একই প্রস্থান পয়েন্টে যেতে ব্যবহার করে , যার একই যুক্তি রয়েছে (যার হিসাবে আপনি বলছেন হিসাবে উত্স অনুসারে অতিরিক্ত প্রয়োজন) extra তবে কিছু মনে করবেন না, আপনি যখন সঠিকভাবে ব্যবহার করছেন C
- কোডটি সি-তে যে কারণেই হোক না কেন, এটি প্রায় অবশ্যই একটি বাণিজ্য-বাণিজ্য যা সবচেয়ে বেশি "প্রত্যক্ষ" কোডকে সমর্থন করে। (আমার পরামর্শ জটিল পরিস্থিতি পরিচালনা করে যেখানে কোনও প্রদত্ত সংস্থান বরাদ্দ থাকতে পারে বা নাও হতে পারে But তবে হ্যাঁ, এক্ষেত্রে ওভারকিল))
কম্পিউটার বিজ্ঞানী এডগার ডিজজস্ট্রার এই ক্ষেত্রটিতে বড় অবদান ছিল, গোটো ব্যবহারের সমালোচনা করার জন্যও বিখ্যাত ছিলেন was উইকিপিডিয়ায় তাঁর যুক্তি সম্পর্কে একটি ছোট্ট নিবন্ধ রয়েছে ।
এটি সময়ে সময়ে চরিত্র অনুসারে স্ট্রিং প্রসেসিংয়ের কাজে আসে।
এই প্রিন্টফ-এসক উদাহরণের মতো কিছু কল্পনা করুন:
for cur_char, next_char in sliding_window(input_string) {
if cur_char == '%' {
if next_char == '%' {
cur_char_index += 1
goto handle_literal
}
# Some additional logic
if chars_should_be_handled_literally() {
goto handle_literal
}
# Handle the format
}
# some other control characters
else {
handle_literal:
# Complicated logic here
# Maybe it's writing to an array for some OpenGL calls later or something,
# all while modifying a bunch of local variables declared outside the loop
}
}
আপনি এটি goto handle_literal
একটি ফাংশন কলে রিফ্যাক্টর করতে পারেন, তবে এটি যদি বিভিন্ন স্থানীয় স্থানীয় ভেরিয়েবলগুলি সংশোধন করে তবে আপনার ভাষা যদি পরিবর্তনীয় ক্লোজারকে সমর্থন না করে তবে আপনার প্রত্যেকটির জন্য রেফারেন্স দিতে হবে। continue
আপনার যুক্তি যদি অন্য কোনও ক্ষেত্রে কাজ না করে তবে একই শব্দার্থকতা পাওয়ার জন্য কল করার পরেও আপনাকে এখনও একটি বিবৃতি (যা তাত্ক্ষণিকভাবে গোটোর একটি রূপ) ব্যবহার করতে হবে।
আমি সাধারণত লেসসারগুলিতে গোটোসকে ন্যায়বিচারের সাথে ব্যবহার করেছি, সাধারণত একই রকমের ক্ষেত্রে। আপনার বেশিরভাগ সময় তাদের প্রয়োজন হয় না, তবে তারা এই অদ্ভুত ঘটনাগুলির জন্য খুব সুন্দর।