মান ব্লক অভিব্যক্তি অনুরূপ. যখন আপনি একটি অভ্যন্তরীণ ব্লক হিসাবে একটি মান ব্লক ব্যবহার করেন, তখন আপনাকে আপনার ব্লকের কোডে একাধিকবার তৈরি করা অভিব্যক্তিটি ব্যবহার করতে হতে পারে। উদাহরণস্বরূপ, একটি ব্লক যেটি একটি তালিকার শেষ উপাদানটি পায় সে অভিব্যক্তিটি ব্যবহার করে যা তালিকাটি দুইবার তৈরি করে।
// Incorrect block-code generator.
javascriptGenerator.forBlock['last_element'] = function(block, generator) {
// Get the expression that creates the list.
const listCode = generator.valueToCode(block, 'LIST', Order.MEMBER);
// listCode is used twice.
const code = `${listCode}[${listCode}.length - 1]`;
return [code, Order.MEMBER];
}
এটি সমস্যার সৃষ্টি করে যদি অভ্যন্তরীণ ব্লকের কোড প্রতিবার কার্যকর করার সময় বিভিন্ন মান তৈরি করে, বা কোডটির পার্শ্বপ্রতিক্রিয়া থাকে। উদাহরণস্বরূপ, যদি অভ্যন্তরীণ ব্লকের কোডটি আসলে একটি ফাংশন কল হয় তবে এই নির্দিষ্ট কোডটি পরিসীমার বাইরের অবস্থার কারণ হতে পারে:
randomList()[randomList().length - 1]
এই সমস্যা এড়াতে, আপনার কোডটি একটি অভ্যন্তরীণ ব্লকের কোডটি ঠিক একবার কার্যকর করা উচিত। এটি করার দুটি উপায় আছে:
অস্থায়ী ভেরিয়েবল : অস্থায়ী ভেরিয়েবলে অভ্যন্তরীণ ব্লকের কোড মূল্যায়নের ফলাফল ক্যাশে করুন এবং পরিবর্তে অস্থায়ী পরিবর্তনশীল ব্যবহার করুন। আপনি এই পদ্ধতিটি ব্যবহার করতে পারেন শুধুমাত্র যদি আপনার ব্লক একটি স্টেটমেন্ট ব্লক হয়।
ইউটিলিটি ফাংশন : এমন একটি ফাংশন তৈরি করুন যা আপনাকে যে কাজটি করতে হবে তা সঞ্চালন করে এবং এই ফাংশনের যুক্তি হিসাবে অভ্যন্তরীণ ব্লকের কোড মূল্যায়নের ফলাফলটি পাস করে। আপনি মান এবং বিবৃতি উভয় ব্লকের জন্য এই পদ্ধতিটি ব্যবহার করতে পারেন।
অস্থায়ী ভেরিয়েবল
একটি অস্থায়ী পরিবর্তনশীল একটি অভ্যন্তরীণ ব্লকের কোড স্ট্রিংয়ের মান সংরক্ষণ করে যাতে কোডটি শুধুমাত্র একবার মূল্যায়ন করা হয় এবং তারপরে মানটি একাধিকবার উল্লেখ করা যেতে পারে।
মান ব্লকে অস্থায়ী ভেরিয়েবল ব্যবহার করা যাবে না কারণ মান ব্লকগুলিকে অবশ্যই কোডের একটি লাইন দিতে হবে। পরিবর্তে একটি ইউটিলিটি ফাংশন ব্যবহার করুন।
import {javascriptGenerator, Order} from 'blockly/javascript';
// Correct block-code generator for a statement block that prints the last element of a list.
javascriptGenerator.forBlock['print_last_element'] = function(block, generator) {
// Get the expression that creates the list.
const listCode = generator.valueToCode(block, 'LIST', Order.MEMBER);
// Get the name of a temporary variable.
const listVar = generator.nameDB_.getDistinctName(
'temp_list', Blockly.names.NameType.VARIABLE);
// Evaluate listCode once and assign the result to the temporary variable.
const code = `var ${listVar} = ${listCode};\n`;
// Print the last element of the list.
code += `print(${listVar}[${listVar}.length - 1]);\n`;
return code;
}
উদাহরণস্বরূপ, যদি ভিতরের ব্লকের কোডটি ফাংশন কল randomList()
হয়, তাহলে জেনারেট করা কোডটি হল:
var temp_list = randomList();
print(temp_list[temp_list.length - 1]);
getDistinctName
কলটি আপনার পছন্দের পরিবর্তনশীল নামটি গ্রহণ করে এবং এমন একটি নাম প্রদান করে যা কোনো ব্যবহারকারী-সংজ্ঞায়িত ভেরিয়েবলের সাথে বিরোধপূর্ণ নয়।
অপ্রয়োজনীয় কোড হ্রাস করুন
অস্থায়ী ভেরিয়েবলের নেতিবাচক দিক হল যে যদি অভ্যন্তরীণ ব্লকের কোডটি একটি মান হয় এবং একটি ফাংশন বা অভিব্যক্তি নয়, তাহলে আপনি অপ্রয়োজনীয় কোড পাবেন:
// Assigning to temp_list is unnecessary.
var temp_list = foo;
print(temp_list[temp_list.length - 1]);
ক্লিনার কোড তৈরি করতে আপনি অভ্যন্তরীণ ব্লকের কোডটি একটি মান কিনা তা পরীক্ষা করতে পারেন এবং যদি তা না হয় তবে শুধুমাত্র অস্থায়ী পরিবর্তনশীলটি অন্তর্ভুক্ত করুন।
if (listCode.match(/^\w+$/)) {
const code = `print(${listCode}[${listCode}.length - 1]);\n`;
} else {
const listVar = generator.nameDB_.getDistinctName(
'temp_list', Blockly.names.NameType.VARIABLE);
const code = `var ${listVar} = ${listCode};\n`;
code += `print(${listVar}[${listVar}.length - 1]);\n`;
}
ইউটিলিটি ফাংশন
একটি ইউটিলিটি ফাংশন হল একটি ডেভেলপার-সংজ্ঞায়িত ফাংশন যা জেনারেট করা কোড স্ট্রিং এর অংশ হিসাবে অন্তর্ভুক্ত। অভ্যন্তরীণ-ব্লক কোড শুধুমাত্র একবার মূল্যায়ন করা হয়েছে তা নিশ্চিত করতে আপনি এগুলি ব্যবহার করতে পারেন এবং তারপরে মানটি একাধিকবার উল্লেখ করা যেতে পারে।
ইউটিলিটি ফাংশন মান ব্লক এবং স্টেটমেন্ট ব্লক ব্যবহার করা যেতে পারে. যাইহোক, স্টেটমেন্ট ব্লকে সাধারণত অস্থায়ী ভেরিয়েবল ব্যবহার করা উচিত, যেগুলি সাধারণত বেশি পাঠযোগ্য।
import {javascriptGenerator, Order} from 'blockly/javascript';
// Correct block-code generator for a value block that gets the last element of a list.
javascriptGenerator.forBlock['last_element'] = function(block, generator) {
// Get the expression that creates the list.
const listCode = generator.valueToCode(block, 'LIST', Order.NONE);
// Create a function that accepts a list and returns its last element. The
// language generator adds this function to your code.
const functionName = generator.provideFunction_(
'list_lastElement',
[
`function ${generator.FUNCTION_NAME_PLACEHOLDER_}(list) {`,
` return list[list.length - 1];`,
`}`
]
);
// Create an expression that calls the function with listCode as its argument.
// This evaluates listCode once and passes the resulting list to the function.
const code = `${functionName}(${listCode})`;
return [code, Order.FUNCTION_CALL];
}
উদাহরণস্বরূপ, যদি ভিতরের ব্লকের কোডটি ফাংশন কল randomList()
হয়, তাহলে জেনারেট করা কোডটি হল:
// This code is added to the overall code returned by the code generator.
function list_lastElement(list) {
return list[list.length - 1];
}
// This code is returned by your inner block.
list_lastElement(randomList());
ফাংশন প্রদান
আপনি provideFunction_
ব্যবহার করে ব্লক-কোড জেনারেটরের ভিতরে ইউটিলিটি ফাংশন সংজ্ঞায়িত করতে পারেন। এটি আপনার ইউটিলিটি ফাংশনের জন্য আপনি যে নামটি চান তা লাগে এবং ফাংশনের সংজ্ঞা ধারণ করে এমন কোড স্ট্রিংগুলির একটি অ্যারে। এটি ব্যবহারকারী-সংজ্ঞায়িত ফাংশনগুলির সাথে বিরোধ না করার জন্য (সম্ভবত) পরিবর্তন করার পরে আপনার ইউটিলিটি ফাংশনের ফলের নাম প্রদান করে।
provideFunction_
এছাড়াও ইউটিলিটি ফাংশন সংজ্ঞা ডিডুপ করে, যাতে প্রতিটি ইউটিলিটি ফাংশন শুধুমাত্র একবারই বিদ্যমান থাকে, এমনকি যদি ব্লকের ধরনটি সংজ্ঞায়িত করে তা একাধিকবার বিদ্যমান থাকে।
অগ্রাধিকার আপডেট করুন
আপনি যখন একটি ইউটিলিটি ফাংশন সংজ্ঞায়িত করেন, তখন আপনাকে ব্লক-কোড জেনারেটরে অন্তর্ভুক্ত অগ্রাধিকারগুলি (যা কীভাবে বন্ধনী ঢোকানো হয় তা সংজ্ঞায়িত করে) আপডেট করা উচিত।
অগ্রাধিকার সর্বদা ব্লক-কোড জেনারেটর দ্বারা প্রত্যাবর্তিত কোড স্ট্রিং এর উপর ভিত্তি করে। এটি ইউটিলিটি ফাংশনের ভিতরে অপারেটরদের সম্পর্কে চিন্তা করে না। তাই আগের উদাহরণে valueToCode
কলটি Order.NONE
এ পরিবর্তিত হয়েছে এবং রিটার্ন টিপলটি Order.FUNCTION_CALL
এ পরিবর্তিত হয়েছে।