Module ২ · type, operator আর coercion: '5' + 2 কেন 7 না
দুটো value একটা operator-এর সামনে: পুরো ছবিটা
এই lesson-এ যা শিখবে
+-এর যেকোনো পাশে string থাকলে কী হয়, আর একই দুটো value পেলে-,*আর/কী করে, আগে থেকেই বলে দিতে পারবে।- Coercion কী, বুঝিয়ে বলতে পারবে,
Number(),String()আরBoolean()দিয়ে ইচ্ছে করে convert করতে পারবে, আর সবগুলো falsy value-র নাম বলতে পারবে। - Default হিসেবে
===দিয়ে তুলনা করতে পারবে,==কোথায় আলাদা সেটা বলতে পারবে, আরNaNধরার একমাত্র কাজের উপায়টা লিখতে পারবে।
Bob-এর প্রথম judged problem-এ দুটো সংখ্যার যোগফল চাওয়া হয়েছে। ও starter paste করে, সংখ্যা দুটো পড়ে, যোগ করে, submit দেয়। Sample input 5 2, আর ওর program print করে 52। Judge বলে Wrong Answer, Bob বলে judge-ই ভুল। Judge ঠিক আছে। এই lesson-এ আমরা engine-এর পেছন পেছন এক ধাপ এক ধাপ করে ওই 52 পর্যন্ত যাব।
Bob-এর 52
এটা Bob-এর program। Module 1-এর lesson 05-এর সেই fixed starter, আর comment-এর জায়গায় ওর নিজের তিনটা লাইন।
const input = require("fs").readFileSync(0, "utf8");
const tokens = input.split(/\s+/).filter(Boolean);
let at = 0;
const next = () => tokens[at++];
const nextInt = () => Number(next());
const out = [];
const a = next();
const b = next();
out.push(a + b);
console.log(out.join("\n"));
52
এই output input 5 2-এর জন্য। Starter input-টাকে space ধরে টুকরো টুকরো করে, প্রতিটা টুকরোকে বলে token। next() পরের token-টা ঠিক যেভাবে টাইপ করা হয়েছিল সেভাবেই ফেরত দেয়, তাই a হলো string "5", সংখ্যা 5 না। Module 1 সোজাসুজি বলে দিয়েছিল: input থেকে যা পড়ো সব text, যতক্ষণ না তুমি নিজে convert করছ।
তাহলে a + b আসলে "5" + "2", আর দুটো string পেলে + ওদের জোড়া লাগায়। Fix হলো প্রতি লাইনে একটা শব্দ বদলানো। nextInt() মানে Number(next()): token পড়ে, তারপর সেটাকে number বানায়।
const input = require("fs").readFileSync(0, "utf8");
const tokens = input.split(/\s+/).filter(Boolean);
let at = 0;
const next = () => tokens[at++];
const nextInt = () => Number(next());
const out = [];
const a = nextInt();
const b = nextInt();
out.push(a + b);
console.log(out.join("\n"));
7
মানে একই + দুটো string পেয়ে দিল 52, আর দুটো number পেয়ে দিল 7। একটা operator কী করবে, সেটা ঠিক হয় ওর দুই পাশের value-র type দেখে। Lesson-এর বাকিটা হলো প্রতিটা ক্ষেত্রের নিয়ম।
Coercion জিনিসটা কী
Operator হলো এমন একটা চিহ্ন, যেটা কয়েকটা value নিয়ে নতুন একটা value বানায়: +, -, ===। যে value-গুলো ও নেয়, সেগুলো ওর operand। প্রতিটা operator নির্দিষ্ট type-এর operand আশা করে। - সংখ্যা বিয়োগ করে, তাই ওর চাই দুটো number।
--কে একটা string দাও, JavaScript error দিয়ে থেমে যাবে না। আগে string-টাকে number বানাবে, তারপর বিয়োগ করবে। Operator যেন কাজ করতে পারে, সেজন্য engine নিজে থেকে যে conversion করে, তার নাম coercion (অনেকে "implicit conversion"-ও বলে)। আর তুমি নিজে হাতে যে conversion লেখো, যেমন Number("5"), সেটা explicit conversion।
Engine-কে কাজটা করতে দেখো। নিচের table সাত জোড়া operand নেয়, একটা একটা করে, আর উত্তর বের হওয়ার আগে engine কোন কোন ধাপ পার হয়, সেটা দেখায়।
প্রতিটা সারি সত্যি। চালিয়ে দেখো, ঠিক এই value আর এই type-ই পাবে।
console.log("5" + 2, typeof ("5" + 2));
console.log("5" - 2, typeof ("5" - 2));
console.log("5" * "2", typeof ("5" * "2"));
console.log(5 + true, typeof (5 + true));
console.log("a" * 1, typeof ("a" * 1));
console.log(1 == "1", 1 === "1");
52 string
3 number
10 number
6 number
NaN number
true false
তাহলে coercion এলোমেলো কিছু না। প্রতিটা operator-এর জন্য engine একটা নিয়ম মানে, আর নিয়মগুলো ছোট।
+-এর নিয়ম, আর বাকিদের নিয়ম
+-এর কাজ দুটো: সংখ্যা যোগ করা, আর string জোড়া লাগানো। Text জোড়া লাগানোর নাম concatenation। দুটো কাজ আছে বলেই +-এর নিয়মটা আলাদা।
- +-এর নিয়ম। যেকোনো একটা operand string হলে অন্যটাও string হয়ে যায়, আর
+দুটো জোড়া লাগায়। না হলে দুটোই number হয়, আর+যোগ করে। - বাকিদের নিয়ম।
-,*,/,%আর**-এর কাজ একটাই, হিসাব। এরা সবসময় দুটো operand-কেই number বানায়।
String না হলে বাকি সবাই number-এর নিয়মে চলে। true হয় 1, false হয় 0। null হয় 0, আর undefined হয় NaN।
console.log(10 - "4");
console.log("10" / "4");
console.log("2" ** 3);
console.log(true + 1);
console.log(null + 1);
console.log(undefined + 1);
console.log("Tk " + 250);
6
2.5
8
2
1
NaN
Tk 250
শুধু শেষ লাইনে +-এর পাশে string ছিল, তাই শুধু ওখানেই text জোড়া লেগেছে। মানে + দেখলে আগে খোঁজো, কোনো পাশে string আছে কি না। না থাকলে ওটা যোগ।
প্রতিটা operator পরিবারের জন্য lesson 02-তে আলাদা অংশ আছে। এখানে সবগুলো এক card-এ রাখা হলো, যাতে একটা একটা করে শেখার আগেই পুরো সেটটা চোখে পড়ে।
Operator-এর চারটা পরিবার
arithmetic a + b a - b a * b a / b a % b a ** b
comparison a === b a !== b a < b a > b a <= b a >= b (and a == b, a != b)
logical a && b a || b !a a ?? b
assignment x = v x += v x -= v x *= v x /= v ...
- Arithmetic সংখ্যা থেকে সংখ্যা বানায়। শুধু
+string-ও জোড়া লাগায়। - Comparison দুটো value নিয়ে একটা হ্যাঁ-না প্রশ্ন করে, আর উত্তর দেয়
trueবাfalse। - Logical হ্যাঁ-না উত্তরগুলোকে মেলায়, আর প্রতিটা value truthy না falsy সেটা দেখে কাজ করে, নিচে যার সংজ্ঞা আছে।
- Assignment একটা variable-এ value রাখে;
+=আর এর ভাইবোনেরা হলোx = x + vজাতীয় লাইনের ছোট রূপ।
ইচ্ছে করে convert করা: Number, String, Boolean
Coercion হয় তোমার অগোচরে। যে program-এর ওপর ভরসা করা যায়, সেটা ইচ্ছে করে convert করে, built-in তিনটা converter দিয়ে। প্রতিটা যেকোনো type-এর value নেয়, আর ফেরত দেয় একটা নির্দিষ্ট type।
console.log(Number("42"), Number("3.5"), Number("12px"), Number(""));
console.log(String(42), String(true), String(null));
console.log(Boolean(1), Boolean(0), Boolean("hi"), Boolean(""));
42 3.5 NaN 0
42 true null
true false true false
Number(x) পুরো string-টাকে একটা সংখ্যা হিসেবে পড়ে, দুই মাথায় space থাকলে সমস্যা নেই। কিন্তু মাঝখানে অন্য কোনো অক্ষর ঢুকলে, যেমন "12px"-এ, উত্তর হয় NaN। Number("") খেয়াল করো: খালি string হয় 0, NaN না। String-এর শুধু সামনের অংশ পড়ে এমন converter আছে, lesson 03-এ দেখবে।
String(x) value-টাকে text হিসেবে লেখে, console.log যে text print করে ঠিক সেটাই। Boolean(x) একটাই প্রশ্নের উত্তর দেয়: এই value-টা কি true হিসেবে গোনা হয়?
যে value false হিসেবে গোনা হয়, সেটা falsy। বাকি সব value truthy। Falsy-র তালিকাটা এত ছোট যে মুখস্থ রাখা যায়: ছয়টা value, সাথে শূন্যের আরও দুটো রূপ।
| Falsy value | এটা কী |
|---|---|
false | boolean নিজেই |
0 | শূন্য সংখ্যা, আর এর আরও দুটো রূপ: -0 আর bigint 0n |
"" | খালি string, একটাও character নেই |
null | "ইচ্ছে করে কোনো value নেই" (Module 1) |
undefined | "এখনো কোনো value দেওয়া হয়নি" (Module 1) |
NaN | ব্যর্থ সংখ্যা, এর কথা ঠিক পরেই |
বাকি সব truthy, এমনকি কিছু value যেগুলো দেখতে খালি লাগে, সেগুলোও। "0" আর " " হলো একটা করে character-ওয়ালা string, তাই এরা truthy। পুরো তালিকা, চমকসহ, lesson 03 print করে দেখাবে।
তাহলে Number, String আর Boolean প্রত্যেকে ঠিক বলে দেয় কোন type ফেরত পাবে। Operator-এর ভরসায় ছেড়ে দেওয়ার চেয়ে এগুলো এ কারণেই ভালো।
NaN, যে সংখ্যা আসলে সংখ্যা না
NaN মানে "Not a Number"। Number-এ convert করা ব্যর্থ হলে, অথবা কোনো হিসাবের সংখ্যায় কোনো উত্তর না থাকলে, যেমন 0 / 0, এটা পাওয়া যায়। তবু এর type "number", কারণ এটা number type-এরই একটা বিশেষ value।
NaN ছড়িয়ে পড়ে। যে হিসাবে NaN ঢোকে, তার উত্তরও NaN, তাই একটা খারাপ value পুরো যোগফলকে NaN বানিয়ে দেয়। আর এর আরও একটা অদ্ভুত স্বভাব আছে, যেটা Zara সবার আগে test করে বের করেছে।
const price = Number("abc");
console.log(price);
console.log(typeof price);
console.log(price === NaN);
console.log(NaN === NaN);
console.log(Number.isNaN(price));
NaN
number
false
false
true
NaN কোনো কিছুর সমান না, নিজের সমানও না। তাই যেকোনো x-এর জন্য x === NaN হলো false, এটা দিয়ে কখনো NaN ধরা যায় না। যেটা কাজ করে, সেটা Number.isNaN(x)। মানে কোনো conversion ব্যর্থ হতে পারলে ফলটা Number.isNaN দিয়ে check করো, === দিয়ে কখনো না।
=== type আর value দুটোই দেখে; == আগে convert করে
JavaScript-এ equality operator দুটো। === হলো strict equality। দুটো operand-এর type এক আর value এক হলেই শুধু এটা true বলে, আর কোনো কিছু convert করে না।
== হলো loose equality। Type আলাদা হলে এটা আগে এক বা দুটো operand-কে convert করে, widget-এ 1 == "1"-এর বেলায় যেমন দেখলে, তারপর তুলনা করে। এর conversion-গুলো একটা লম্বা নিয়ম মানে, যার কয়েকটা চমক বেশ বিখ্যাত।
console.log(7 === 7, 7 === "7");
console.log(7 == 7, 7 == "7");
console.log(0 == "", 0 === "");
console.log(null == undefined, null === undefined);
true false
true true
true false
true false
এই track default হিসেবে === আর !== লেখে, বেশিরভাগ team-ও তাই করে। == একটা জায়গায় বেশি পরিষ্কার, আর lesson 04 ঠিক সেই জায়গাটা দেখায়। তাই তুলনা করো === দিয়ে, আর type আলাদা হতে পারলে আগে নিজে convert করে নাও।
এই lesson-এর সবচেয়ে ছোট program। প্রতিটা ফলের পাশে তার type print করে, যাতে type বদলানোটা চোখে পড়ে।
console.log(4 + 4, typeof (4 + 4));
console.log("4" + 4, typeof ("4" + 4));
console.log("4" - 4, typeof ("4" - 4));
console.log("4" * "4", typeof ("4" * "4"));
console.log(4 / "four", typeof (4 / "four"));
8 number
44 string
0 number
16 number
NaN number
শুধু দ্বিতীয় লাইনে +-এর পাশে string আছে, তাই শুধু ওই উত্তরটাই string। শেষ লাইনে "four" convert হতে পারেনি, তবু type number, কারণ NaN একটা number।
Amara-র দরজার তালা PIN রাখে number 4721 হিসেবে। Guess আসে input থেকে, তাই আসে text হয়ে। ওর প্রথম check token-টাকেই সরাসরি তুলনা করে; দ্বিতীয়টা আগে convert করে নেয়।
const input = require("fs").readFileSync(0, "utf8");
const tokens = input.split(/\s+/).filter(Boolean);
let at = 0;
const next = () => tokens[at++];
const nextInt = () => Number(next());
const out = [];
const PIN = 4721;
const guess = next();
out.push("as typed: " + (guess === PIN));
out.push("converted: " + (Number(guess) === PIN));
console.log(out.join("\n"));
as typed: false
converted: true
এই output input 4721-এর জন্য, মানে ঠিক PIN দিলে। প্রথম check string "4721"-কে number 4721-এর সাথে তুলনা করে, আর type আলাদা বলে === বলে না। দ্বিতীয়টা ইচ্ছে করে convert করে, আর একই === বলে হ্যাঁ।
প্রতিটা তুলনার চারপাশের bracket জরুরি। ওগুলো না থাকলে === চলার আগেই + label আর guess জোড়া লাগিয়ে ফেলত, কেন সেটা lesson 02 বলবে।
Zara-র আবহাওয়া station n-টা reading পাঠায়। কোনো sensor বিগড়ে গেলে সংখ্যার বদলে পাঠায় err। ও প্রতিটা reading convert করে, যেগুলো NaN হয়ে আসে সেগুলো বাদ দেয়, আর বাকিগুলোর গড় করে। for loop আর if সেই দুটোই, যা Module 1-এর lesson 05-এ দেখেছ; ঠিকমতো শেখাবে Module 4।
const input = require("fs").readFileSync(0, "utf8");
const tokens = input.split(/\s+/).filter(Boolean);
let at = 0;
const next = () => tokens[at++];
const nextInt = () => Number(next());
const out = [];
const n = nextInt();
let sum = 0;
let good = 0;
for (let i = 0; i < n; i++) {
const reading = nextInt();
if (!Number.isNaN(reading)) {
sum += reading;
good += 1;
}
}
out.push("good readings: " + good + " of " + n);
out.push("average: " + sum / good);
console.log(out.join("\n"));
good readings: 3 of 5
average: 21.333333333333332
এই output input 5, তারপর 21.5 err 23 err 19.5-এর জন্য। Number.isNaN check না থাকলে একটা err-ই sum-কে NaN বানিয়ে দিত, আর গড় print হতো NaN।
শেষ লাইনে number type-এর লম্বা দশমিকটা দেখা যাচ্ছে। দেখানোর জন্য lesson 03 এটাকে toFixed দিয়ে গোল করবে। Zara-র প্রথম test ছিল সব err: তখন good হয় 0, আর গড় দাঁড়ায় 0 / 0, মানে NaN।
এটা কোথায় কাজে লাগে
- Web form। যেকোনো browser-এ
<input>element-এরvalueসবসময় string, field-টাtype="number"হলেও। Code নিজে convert না করা পর্যন্ত form-এর যোগফল মানেই Bob-এর 52-এর অপেক্ষা (Module 15)। - Web address। Browser আর Node দুই জায়গাতেই built-in
URLSearchParamsURL-এর query অংশ পড়ে।new URLSearchParams("page=2").get("page")ফেরত দেয় string"2", তাই page নিয়ে হিসাব করার আগেNumber()লাগে। - Command-line tool। Node-এর
process.argv-এ থাকেnode script.js-এর পরে টাইপ করা শব্দগুলো, আর প্রতিটাই string।node add.js 5 2চালালে script হাতে পায়"5"আর"2"। - Server থেকে আসা JSON।
JSON.parse('{"price": 250}')দেয় একটা number, কিন্তু'{"price": "250"}'দেয় string। Type ঠিক করে পাঠানো পক্ষ, তাই JSON পড়া code type check করে নেয় (Module 8)।
যে ভুলগুলো সবাই করে
১. next() দিয়ে সংখ্যা পড়া।
const input = require("fs").readFileSync(0, "utf8");
const tokens = input.split(/\s+/).filter(Boolean);
let at = 0;
const next = () => tokens[at++];
const nextInt = () => Number(next());
const out = [];
out.push(next() + next());
console.log(out.join("\n"));
52
কোনো error নেই, কোনো warning নেই: program চলে, input 5 2 পেয়ে print করে 52, আর judge বলে Wrong Answer। প্রতিটা সংখ্যা পড়ো nextInt() দিয়ে। তুমি next() লিখবে, কারণ screen-এ token-টাকে সংখ্যার মতোই দেখায়, আর screen type দেখায় না।
২. Input-এর token-কে === দিয়ে number-এর সাথে তুলনা করা।
const typed = "10";
console.log(typed === 10);
console.log(Number(typed) === 10);
false
true
প্রথম লাইন চুপচাপ false, আর যে branch এই ফলের ওপর নির্ভর করে, সেটা কখনো চলে না। আগে token convert করো, তারপর তুলনা। === শেখার ঠিক পরেই তুমি এই ভুলটা করবে, কারণ operator ঠিক, type ভুল।
৩. === দিয়ে NaN খোঁজা।
const value = Number("twelve");
console.log(value === NaN);
console.log(Number.isNaN(value));
false
true
value আসলেই NaN, তবু value === NaN বলে false, কারণ NaN কারো সমান না। লেখো Number.isNaN(value)। তুমি === NaN লিখবে, কারণ পড়তে একদম সাধারণ ইংরেজি বাক্যের মতো লাগে।
৪. ভাবা যে Number() খালি string ফিরিয়ে দেবে।
const field = "";
console.log(Number(field));
console.log(Number.isNaN(Number(field)));
0
false
খালি field convert হয়ে হয় 0, দেখতে একদম আসল সংখ্যা, আর Number.isNaN সেটা আটকায় না। খালি value মানে যদি "নেই" হয়, তাহলে convert করার আগে "" check করো। তুমি NaN আশা করবে, কারণ text-এ কোনো সংখ্যাই নেই, কিন্তু নিয়ম বলে খালি string মানে 0।
Bob নিজের দুটো উত্তরই পাশাপাশি দেখতে চায়, ভুলটা আর ঠিকটা, যাতে আর কখনো গুলিয়ে না ফেলে।
Input. দুটো token, a আর b, প্রতিটা দশমিক পদ্ধতিতে লেখা একটা সংখ্যা। Token-এ minus চিহ্ন, দশমিক বিন্দু বা শুরুতে বাড়তি শূন্য থাকতে পারে।
Output. দুই লাইন। লাইন 1-এ a আর b-কে number হিসেবে যোগ করে JavaScript যা print করে। লাইন 2-এ token দুটো text হিসেবে জোড়া লাগিয়ে।
Constraints. প্রতিটা token-এ 1 থেকে 25টা অক্ষর।
Sample. Input 5 2 দিলে দুই লাইনে আসে 7 আর 52।
const input = require("fs").readFileSync(0, "utf8");
const tokens = input.split(/\s+/).filter(Boolean);
let at = 0;
const next = () => tokens[at++];
const nextInt = () => Number(next());
const out = [];
// your code: read with next() and nextInt(), push every line of output to out
console.log(out.join("\n"));
Grade হবে sum-and-join হিসেবে। Hidden test-এ শুরুর বাড়তি শূন্য, negative সংখ্যা আর 0.1 0.2-এর মতো দশমিক আছে, তাই প্রতিটা token একবার পড়ে রেখে দাও।
Zara একটা sensor log থেকে কিছু token পেয়েছে, আর জানতে চায় কোনগুলো পরিষ্কার সংখ্যা। Number(token) NaN না হলে token-টা পরিষ্কার।
Input. n, তারপর n-টা token। কোনো token-এর ভিতরে space নেই।
Output. প্রতি token-এর জন্য এক লাইন: পরিষ্কার হলে yes, একটা space, আর JavaScript সংখ্যাটা যেভাবে print করে; না হলে no।
Constraints. 1 <= n <= 30000। প্রতিটা token-এ 1 থেকে 20টা অক্ষর।
Sample. Input 5 আর 12 3.50 abc 007 12px দিলে পাঁচ লাইনে আসে yes 12, yes 3.5, no, yes 7 আর no।
const input = require("fs").readFileSync(0, "utf8");
const tokens = input.split(/\s+/).filter(Boolean);
let at = 0;
const next = () => tokens[at++];
const nextInt = () => Number(next());
const out = [];
// your code: read with next() and nextInt(), push every line of output to out
console.log(out.join("\n"));
Grade হবে clean-numbers হিসেবে। Hidden test-এ এমন token আছে যেগুলো সবাইকে চমকে দেয়, যেমন NaN, Infinity আর 0x1f। চালানোর আগে প্রতিটার উত্তর আন্দাজ করে নাও।
Example 3-এর Zara-র আবহাওয়া station এখনো একটা test-এ ফেল করে: সব reading err হলে গড় print হয় NaN। Report-টা যেন কথায় সেটা বলে, সেই ব্যবস্থা করো।
Input. n, তারপর n-টা token। একটা token হলো 21.5-এর মতো একটা reading, অথবা sensor বিগড়ে গেলে যে শব্দটা পাঠায়।
Output. দুই লাইন। লাইন 1-এ good: আর যতগুলো token number-এ convert হয়, তার সংখ্যা। লাইন 2-এ average: আর ওদের গড়, JavaScript যেভাবে print করে; একটা token-ও convert না হলে average: none।
Constraints. 1 <= n <= 1000। প্রতিটা token-এ 1 থেকে 20টা অক্ষর।
Sample. Input 4 আর 20 err 22 err দিলে আসে good: 2 আর average: 21। Input 2 আর err err দিলে আসে good: 0 আর average: none।
const input = require("fs").readFileSync(0, "utf8");
const tokens = input.split(/\s+/).filter(Boolean);
let at = 0;
const next = () => tokens[at++];
const nextInt = () => Number(next());
const out = [];
// your code: read with next() and nextInt(), push every line of output to out
console.log(out.join("\n"));
আলাদা করে grade হয় না। Example 3 থেকে শুরু করো, আর ভাগ করার আগে good check করো। তারপর Infinity reading-টা দিয়ে চালাও, আর ঠিক করো তোমার station এটাকে গুনবে কি না।
Example 2-এর Amara-র দরজার তালা এখন PIN রাখে text হিসেবে, 0472, কারণ PIN 0 দিয়েও শুরু হতে পারে। প্রতিটা guess-এর জন্য ও জানতে চায়: সেটা টাইপ করা PIN-এর সাথে হুবহু মেলে, নাকি শুধু দুটোকে number বানানোর পরে মেলে, নাকি একদমই মেলে না।
Input. PIN, তারপর n, তারপর n-টা guess। কোনো token-এ space নেই।
Output. প্রতিটা guess-এর জন্য এক লাইন: guess আর PIN হুবহু একই text হলে text, তা না হয়ে Number(guess) === Number(pin) হলে number, আর বাকি সব ক্ষেত্রে no।
Constraints. PIN-এ 4 থেকে 8টা digit। 1 <= n <= 1000। প্রতিটা guess-এ 1 থেকে 20টা অক্ষর।
Sample. Input 0472, 5 আর 0472 472 +472 4.72e2 4720 দিলে পাঁচ লাইনে আসে text, number, number, number আর no।
const input = require("fs").readFileSync(0, "utf8");
const tokens = input.split(/\s+/).filter(Boolean);
let at = 0;
const next = () => tokens[at++];
const nextInt = () => Number(next());
const out = [];
// your code: read with next() and nextInt(), push every line of output to out
console.log(out.join("\n"));
আলাদা করে grade হয় না। কঠিন অংশটা হলো দেখা, Number() কত রকম লেখাকে একই সংখ্যা হিসেবে পড়ে: একটা চিহ্ন, একটা দশমিক বিন্দু, একটা exponent। তিনটা উত্তরের কোনটা দিয়ে আসলে দরজা খোলা উচিত?
সচরাচর যে প্রশ্নগুলো আসে
JavaScript convert করতেই বা যায় কেন? Python তো error দিয়ে থেমে যায়।
হ্যাঁ, Python 3-এ
"5" + 2দিলে আসেTypeError: can only concatenate str (not "int") to str। JavaScript বানানো হয়েছিল 1995-এ, web page-এর ভিতরের ছোট ছোট script-এর জন্য, আর এটাকে বানানো হয়েছিল থেমে না গিয়ে চলতে থাকার জন্য। পুরনো page না ভেঙে সেই সিদ্ধান্ত এখন আর ফেরানো যায় না। তাই তুমি ইচ্ছে করে convert করো, engine-এর আর কিছু আন্দাজ করার থাকে না।typeof NaNকেন "number"?কারণ
NaNnumber type-এরই একটা value, আলাদা করে রাখা হয়েছে "এই হিসাবের কোনো সংখ্যায় উত্তর নেই" বোঝাতে। এটা এসেছে IEEE 754 থেকে, floating-point সংখ্যার যে standard প্রায় সব processor মানে, তাই C আর Python-এও এটা আছে। Lesson 05 ওই standard-টা খুলে দেখায়।অনেককে convert করতে
+xলিখতে দেখেছি। এটা কিNumber(x)-এর মতোই?হ্যাঁ। শুধু একটা operand-ওয়ালা
+, value-র আগে লেখা, সেটাকে number বানায়, ঠিকNumber(x)-এর মতো।+"42"হলো 42। এই trackNumber(x)লেখে, কারণ পড়তে গিয়ে কেউ এটা মিস করে না।Coercion কি ভাষাটার একটা bug?
না, এটা একটা নিয়ম, আর নিয়মটা ভাষার standard, ECMAScript-এ লেখা আছে। এর কিছু ফল মানুষকে চমকে দেয়, আর interview-তে ঠিক ওগুলোই জিজ্ঞেস করে (lesson 06)। কোথায় conversion কাজে আসে, আর কোথায় bug লুকিয়ে রাখে, lesson 04 দেখায়।
মূল কথা
- Operator যেন কাজ করতে পারে, সেজন্য engine operand-এর type বদলে দেয়, এটাই coercion;
Number(),String()আরBoolean()ইচ্ছে করে convert করে। - +-এর নিয়ম: যেকোনো পাশে string থাকলে
+text জোড়া লাগায়।-,*,/,%আর**সবসময় number বানায়। - Input-এর প্রতিটা token একটা string: সংখ্যা পড়ো
nextInt()দিয়ে। - Falsy value হলো
false,0(সাথে-0আর0n),"",null,undefinedআরNaN; বাকি সব truthy। NaNকারো সমান না, নিজেরও না, তাই এটা ধরোNumber.isNaNদিয়ে।===কোনো conversion ছাড়া type আর value দুটোই মেলায়, আর এটাই default;==আগে convert করে নেয়।- আরও গভীরে: Under the Hood, abstract equality algorithm আর floating point (Pro)।
এরপর lesson 02 প্রতিটা operator একটা একটা করে ধরবে, logical operator-গুলোও, যারা এমন value ফেরত দেয় যা তুমি হয়তো আশা করোনি।
lesson ১ শেষ
শেষ হলে চিহ্ন দিন, অগ্রগতি আপনার সাথে থাকবে।
পরেরটা: প্রতিটা operator, একটা একটা করে