গ্লোবাল ফাংশন

এই ফাংশনগুলো স্টার্টআপে গ্লোবাল স্কোপে রেজিস্টার হয়। আপনি import ছাড়াই যেকোনো ফাইল থেকে এদের কল করতে পারেন। যেখানে একটি ইংরেজি নামের বাংলা সমার্থক আছে, দুটিই একই callable-এ bind হয়।

I/O ও display

print(...args) / লিখুন(...args)

প্রতিটি আর্গুমেন্টের display স্ট্রিং standard output-এ লেখে, একটি স্পেস দিয়ে আলাদা করে, শেষে একটি নতুন লাইন যোগ করে। Variadic — যেকোনো সংখ্যক আর্গুমেন্ট নেয়।

print("hello", 42, true);    // hello 42 true
লিখুন("নম্বর:", 7);          // নম্বর: 7

কোনো আর্গুমেন্ট list বা map হলে print সেটাকে pretty-এর মতো ফরম্যাট করে: ছোট হলে inline, বড় হলে 4-space indent দিয়ে multi-line। Collection-এর ভেতরের স্ট্রিংগুলো quote-সহ দেখানো হয়, যাতে identifier থেকে আলাদা বোঝা যায়।

print([1, 2, 3]);
// [1, 2, 3]

print({a: 1, b: "hello", c: [10, 20, 30]});
// {a: 1, b: "hello", c: [10, 20, 30]}

stdout যখন interactive terminal, তখন collection-এর ভেতরের value-গুলো টাইপ অনুযায়ী রঙিন হয় (number cyan, string green, bool yellow, null gray, map key bright cyan)। নিয়ন্ত্রণ করতে:

  • BNL_PRINT_COLOR=1 — force on
  • BNL_PRINT_COLOR=0 বা NO_COLOR=1 — force off

Pipe বা redirect করলে (bnl app.bnl > out.txt) color আপনাআপনি বন্ধ হয়ে যায়, যাতে file byte-clean থাকে।

null ফেরত দেয়।

input(prompt?) / ইনপুট(prompt?)

Standard input থেকে একটি লাইন পড়ে। prompt দিলে পড়ার আগে stdout-এ লেখে (trailing newline ছাড়া)।

ফেরত স্ট্রিং-এ trailing newline থাকে না। EOF-এ (Windows-এ Ctrl-Z + Enter, POSIX-এ Ctrl-D) null ফেরত দেয়, তাই if (line == null) { ... } দিয়ে end-of-input detect করতে পারেন।

var name = input("নাম? ");
if (name == null) { return; }
print("হ্যালো,", name);

টাইপ কনভার্শন

str(value)

যেকোনো মান-কে তার display স্ট্রিং-এ রূপান্তর — print যে ফর্মে দেখাতো সেই একই।

print(str(42));         // "42"
print(str([1, 2, 3]));  // "[1, 2, 3]"
print(str(null));       // "null"

to_number(s)

একটি স্ট্রিং-কে সংখ্যায় parse করে। ব্যর্থ হলে throw না করে null ফেরত দেয় — == null চেক-এর সাথে pair করুন। সংখ্যার চারপাশের whitespace tolerate করে। সংখ্যা যেমন আছে তেমনই pass through হয়।

print(to_number("3.14"));    // 3.14
print(to_number("  42 "));   // 42
print(to_number("abc"));     // null
print(to_number(7));         // 7

chr(n)

একটি byte value থেকে একটি single-byte স্ট্রিং বানায়। n 0..255-এ একটি সংখ্যা হতে হবে। অন্যথায় throw করে।

print(chr(65));     // "A"
print(chr(10));     // "\n"

Reflection

type(value) / ধরণ(value)

মানের টাইপ-নাম একটি স্ট্রিং হিসেবে ফেরত দেয়। সম্ভাব্য ফলাফল: "null", "bool", "number", "string", "list", "map", "function", "class", "instance", "module", "future"

print(type(null));        // null
print(type(true));        // bool
print(type(42));          // number
print(type("hi"));        // string
print(type([1, 2]));      // list
print(type({a: 1}));      // map
print(type(print));       // function

এরর recovery

try_call(thunk, on_err)

thunk() কে কোনো আর্গুমেন্ট ছাড়াই কল করে। স্বাভাবিকভাবে return করলে তার মান ফেরত দেয়। Throw করলে on_err(<message-or-thrown-value>) কল করে এবং সেটি যা ফেরত দেয় তা ফেরত দেয়।

try_call সেইসব জায়গায় কাজে আসে যেখানে try / catch syntax awkward — যেমন expression-level recovery কোনো call-এর ভেতরে, অথবা একটি লাইব্রেরির ভেতরে যেখানে handler exception-কে response-এ রূপান্তর করতে হবে।

var result = try_call(
    function () { return risky_op(); },
    function (err) { print("recovered:", err); return null; }
);

ডিবাগিং

pretty(value)

একটি মান-কে nested indentation সহ multi-line স্ট্রিং-এ pretty-print করে। স্ট্রিং quotes-এ দেখানো হয় (তাই "x" একটি bare identifier থেকে আলাদাভাবে দৃশ্যমান)। আউটপুট BNL_PRINT_LIMIT codepoints-এ truncate হয় (default 100; disable করতে BNL_PRINT_LIMIT=0 সেট করুন), কাটা হলে শেষে "..." যোগ হয়।

print(pretty({ user: "alice", roles: ["admin", "editor"], age: 30 }));

print(pretty(x)); হিসেবে ব্যবহার্য — যখন nested ডাটার দ্রুত legible view চান।

dump(value)

pretty-এর মতই একই formatter, কিন্তু truncation ছাড়া। যখন debug করার সময় পুরো মান দেখতে চান তখন ব্যবহার করুন।

print(dump(big_response));

অ্যাসিনক্রোনাস মান

Future

ভবিষ্যতে settle হবে (fulfill বা reject) এমন মানের জন্য built-in টাইপ। wait কীওয়ার্ড দিয়ে straight-line script-এর মতো async কোড লেখা যায়।

Future callable (constructor হিসেবে কল করা যায়) এবং তার static method-ও আছে:

var f = Future(function (resolve, reject) {
    timers.set(0, function () { resolve("done"); });
});

Future.of(7);                    // ইতিমধ্যেই 7 দিয়ে fulfilled
Future.err("nope");              // ইতিমধ্যেই rejected
Future.all([f1, f2, f3]);        // সবগুলো fulfill হলে [v1, v2, v3]; প্রথম error-এ reject
Future.race([f1, f2]);           // প্রথম settle হওয়াটা জেতে
Future.all_settled([f1, f2]);    // সবসময় fulfill হয় — প্রতিটার {ok, value?, error?} map-এর তালিকা

প্রতিটি Future-এ chain করার method:

Methodবর্ণনা
f.next(on_ok) / f.next(on_ok, on_err)Fulfill হলে on_ok চলে। নতুন Future ফেরত দেয়।
f.fail(on_err)Reject হলে on_err চলে।
f.always(fn)যাই হোক, fn চলে। মান বদলায় না।
f.state"pending", "fulfilled", বা "rejected"

যেকোনো ফাংশনের ভেতরে wait f কলটিকে suspend করে যতক্ষণ না f settle হয়; তারপর মান ফেরত দেয় (rejection হলে throw করে)। সম্পূর্ণ রেফারেন্স — Future মডিউল পেজ।

function fetch_user(id) {
    var resp = wait request.get("/users/" + str(id));
    return resp.data;
}

futurify(fn)

কলব্যাক-স্টাইল ফাংশন (যার শেষ আর্গুমেন্ট একটি (err, result) callback) wrap করে — তার পরিবর্তে একটি Future ফেরত দেয়। legacy API বা নিজের callback-driven কোড-কে wait/Future-এ আনার জন্য।

function legacy_read(path, cb) {
    timers.set(0, function () { cb(null, "data from " + path); });
}

var read_async = futurify(legacy_read);
read_async("file.txt").next(function (data) { print(data); });
// অথবা
var data = wait read_async("file.txt");

futurify একটি ফাংশন ফেরত দেয় যার arity = "মূলের আর্গুমেন্ট − trailing callback"। শুধুমাত্র cb(err, result) shape সাপোর্ট করে।

নোট

  • এই পেজের প্রতিটি global-এর একটি বাংলা সমার্থক আছে — সবগুলো একই callable-কে নির্দেশ করে: print/লিখুন, input/ইনপুট, str/স্ট্রিং, to_number/সংখ্যা, chr/অক্ষর, type/ধরণ, try_call/নিরাপদ_কল, pretty/সুন্দর, dump/বিস্তারিত, Future/ভবিষ্যৎ, futurify/ভবিষ্যৎকর। পূর্ণ table-এর জন্য দ্বিভাষিক নাম
  • এগুলো সত্যিকারের function value — আপনি এদের pass around করতে পারেন: var p = print; p("hi");
  • এরা গ্লোবাল স্কোপে থাকে, তাই একই স্কোপে একই নামের যেকোনো user-defined variable এদের shadow করবে।