زیستبوم متنباز یک زبان همهی چیزهایی است که در اطراف آن به مردم اجازه میدهد از کار یکدیگر دوباره استفاده کنند: یک مدیر بسته، جایی برای پیدا کردن بستهها، راهی برای اعتماد به آنچه دانلود میکنید، مستندات، پشتیبانی ویرایشگرها، و جامعهای که همهی اینها را زنده نگه دارد. برای یک زبان برنامهنویسی تازه، ساختن این زیستبوم از ساختن کامپایلر سختتر است. این نوشته نشان میدهد زبان برنامهنویسی سلام چطور به این مسئله نزدیک میشود: اول یک کتابخانهی استاندارد بزرگ، سپس یک مدیر بستهی مبتنی بر گیت با فایل قفل و چکیدهی رمزنگاشتی، یک فهرست بستهها، و ابزارهایی که بستهها را هم برای کد انگلیسی و هم برای کد فارسی قابل استفاده میکنند. همچنین بیتعارف از وضعیت کنونی میگوید، که هنوز آغاز راه است.
زیستبوم یک زبان برنامهنویسی از چه ساخته شده است؟
زیستبوم یک زبان برنامهنویسی مجموعهی کدهای مشترک، ابزارها، زیرساخت و آدمهایی است که یک کامپایلر را به چیزی تبدیل میکنند که بشود با آن محصول ساخت. Rust کتابخانهی crates.io و Cargo را دارد، پایتون PyPI و pip را، جاوااسکریپت npm را، و Go مسیرهای ماژول، یک پراکسی ماژول و یک پایگاه دادهی چکیدهها را. هرکدام از اینها سالها و جامعهای بزرگ لازم داشت تا رشد کند.
یک زبان تازه با مسئلهی «مرغ و تخممرغ» روبهروست. برنامهنویسان پیش از پذیرفتن یک زبان منتظر کتابخانهها میمانند، و کتابخانهها فقط وقتی پیدا میشوند که برنامهنویسان زبان را پذیرفته باشند. راههای بیرون رفتن از این دور فقط چندتاست:
- کتابخانهی استانداردی عرضه کنید که آنقدر بزرگ باشد که کاربران نخستین برای کارهای رایج به کد شخص ثالث نیاز نداشته باشند؛
- انتشار و استفاده از بستهها را بسیار ساده کنید تا چند نویسندهی نخست با هیچ اصطکاکی روبهرو نشوند؛
- تعامل با یک زیستبوم موجود را ارزان کنید تا کتابخانههای غایب را بتوان قرض گرفت؛
- روی مستندات و ابزارها سرمایهگذاری کنید، که بخشی از زیستبوماند حتی وقتی کسی این اسم را رویشان نمیگذارد.
سلام هر چهار کار را میکند، و توازن میان آنها چیزهای زیادی دربارهی جایگاه امروز پروژه میگوید.
کتابخانهی استاندارد بهعنوان نخستین زیستبوم
شرط اصلی سلام تا امروز یک کتابخانهی استاندارد بزرگ است که همراه کامپایلر عرضه میشود. مرجع کتابخانه بیش از ۱۷۰ بسته را مستند کرده است: متن و یونیکد، پروندهها و فرایندها، سرورها و کلاینتهای HTTP با مسیریاب، WebSocket، gRPC، SSH و TLS، راهاندازهای SQLite، PostgreSQL، MySQL، Redis و ClickHouse، فشردهسازی و بایگانی، رمزنگاری، تصویر، صدا، ماتریس، تانسور و شبکهی عصبی. هیچکدام به salam add نیاز ندارد؛ یک واردسازی کافی است.
این همان راهبرد «باتری همراه» (batteries included) است که پایتون مشهورش کرد، و هزینهی روشنی دارد: هر بستهی درون std/ را پروژهی اصلی نگهداری میکند، پس بار همهاش بر دوش پروژهی اصلی است. برای یک زبان جوان سود روشنی هم دارد. کسی که سلام را ارزیابی میکند میتواند یک سرویس وب با پایگاه داده، API جیسون و TLS بنویسد، بیآنکه به حتی یک بسته از یک غریبه وابسته باشد.
پروژه این انتخاب را در اکتبر ۲۰۲۶ صریح کرد، وقتی شاخهی جداگانهی packages/ با کتابخانههایش در std/ ادغام شد. صفحهی مدیر بسته قاعده را بیان میکند: هر چیزی در کتابخانهی استاندارد همراه کامپایلر عرضه میشود و فرمانهای بسته برای کدی است که کسی در مخزن خودش منتشر میکند.
برای کتابخانههای C، میانجی تابعهای بیگانه (FFI) سومین راه گریز است: یک بلوک درونداد (extern) میتواند هر تابع C را فراخوانی کند و مانیفست یک بسته میتواند توضیح دهد که کتابخانهی C ای که بسته روی آن پوسته کشیده چطور پیدا یا ساخته شود.
مدیر بستهی سلام: salam.toml، salam add و فایل قفل
کد شخص ثالث در مخزنهای معمولی گیت نگهداری میشود. یک پروژه پوشهای است با main.salam و یک مانیفست salam.toml، و salam new یا salam init هر دو را میسازد. افزودن یک وابستگی یک فرمان است:
salam init
salam add github.com/owner/repo # تازهترین انتشار
salam add github.com/owner/repo@^1.2 # یک بازهی نسخه
salam deps # پس از کلون تازه: دانلود و راستیآزمایی
salam update # تازهترین انتشار با همان نسخهی اصلی
salam install github.com/owner/tool # ساخت یک برنامه در ~/.salam/binمانیفست آنچه را خواستهاید ثبت میکند و salam.lock دقیقاً آنچه را گرفتهاید:
[package]
name = "myapp"
version = "0.1.0"
salam = ">=0.5.9"
[dependencies]
"github.com/owner/repo" = "v1.2.0"
"example.com/me/lib" = { path = "../lib" }طراحی آشکارا از ماژولهای Go وام گرفته است. هر بسته با مسیر مخزنش نامگذاری میشود؛ پس نام مرکزیای برای ثبت کردن وجود ندارد. نسخهها برچسبهای گیتاند (v1.2.0) و برای مخزنهایی که برچسب ندارند شبهنسخه ساخته میشود. وقتی دو وابستگی نسخههای متفاوتی از یک ماژول بخواهند، نسخهی تازهتر برنده میشود؛ سند PACKAGES.md این را «انتخاب کمینهی نسخه» (minimal version selection) مینامد، «مانند Go». هر نسخهی اصلی تازه مسیر ماژول جداگانهای دارد (.../v2)؛ پس v1 و v2 میتوانند در یک برنامه کنار هم باشند.
دو جزئیات این طراحی را برای یک جامعهی کوچک کاربردی میکند. بستهها را میتوان از GitHub، GitLab و Codeberg حتی بدون نصب گیت، از راه API بایگانی هر میزبان، دریافت کرد. و [package].salam قدیمیترین کامپایلری را که بسته با آن ساخته میشود اعلام میکند؛ پس salam add با پیام «به سلام X یا تازهتر نیاز دارد» متوقف میشود، بهجای آنکه با یک خطای کامپایل گیجکننده شکست بخورد. این برای زبانی پیش از نسخهی ۱٫۰ که نحوش هنوز میان انتشارها تغییر میکند اهمیت دارد.
اعتماد: چکیدههای رمزنگاشتی و نسخههای تغییرناپذیر
مدیر بسته ابزاری در زنجیرهی تأمین نرمافزار است و شکست خطرناکش این است که بیصدا کدی متفاوت با آنچه نویسنده منتشر کرده نصب شود. سلام در سه لایه به این مسئله پاسخ میدهد.
- چکیدههای فایل قفل. هر ردیف در
salam.lockیک چکیدهی SHA-256 روی همهی پروندههای بسته (بهجز.git) دارد؛ پس دریافت از راه گیت و دانلود بایگانی tar به یک چکیده میرسند.salam depsاین چکیده را دوباره بررسی میکند. - یک سابقهی محلی روی هر دستگاه. نخستین باری که یک دستگاه نسخهای را دانلود میکند، چکیدهی آن در
~/.salam/pkg/sums.txtنگه داشته میشود. اگر دانلود بعدی همان نسخه فرق داشته باشد، مثلاً چون کسی پس از انتشار برچسب را جابهجا کرده، فرمان متوقف میشود. - یک فهرست منتشرشده. چکیدهها با
registry/sums.txtدر مخزن سلام هم مقایسه میشوند؛ فهرستی بازبینیشده از خطهایی به شکلmodule@version sum. دانلودی که با یک خط منتشرشده نخواند رد میشود.salam deps sumsخطها را برای یک درخواست ادغام (Pull Request) چاپ میکند.
لایهی سوم خویشاوند کوچک و بازبینیشدهی پایگاه دادهی چکیدههای Go است. منصفانه است اضافه کنیم که تازه است: پرونده وجود دارد و ابزارها از آن استفاده میکنند، اما هنوز هیچ ردیفی در آن نیست.
کشف بستهها: فهرست بستهها و salam search
پیدا کردن بستهها نیمهی دیگر یک زیستبوم است. salam search در دو جا جستوجو میکند: کتابخانهی استاندارد، و registry/index.toml، پروندهای در مخزن اصلی که نویسندگان با یک درخواست ادغام ردیفی برای بستهشان به آن اضافه میکنند.
salam search ggufai.gguf (standard library, import it directly)قالب این فهرست عمداً ساده است: یک نام، یک توضیح یکخطی و چند برچسب. انتشار هم به همان اندازه ساده است: مخزنی با یک salam.toml و یک پروندهی ورودی همنام مخزن بسازید، یک انتشار برچسب بزنید و یک درخواست ادغام برای فهرست باز کنید. صفحهی مدیر بسته این مسیر را با یک مثال کارا نشان میدهد.
واقعیت ناخوشایند این است: تا آبان ۱۴۰۵ (نوامبر ۲۰۲۶)، فهرست بستهها هیچ بستهی شخص ثالثی ندارد. سازوکار سر جایش است و کتابخانهی استاندارد بیشتر نیازهای نخستین را پوشش میدهد، اما جامعهی نویسندگان بسته هنوز شکل نگرفته است. هر توصیف صادقانهای از زیستبوم سلام باید از همین عدد شروع شود.
نوشتن یک بسته برای دو جامعهی زبانی
یک بخش از طراحی زیستبوم سلام در زبانهای رایج معادل مستقیمی ندارد. کد سلام را میتوان به انگلیسی یا فارسی نوشت و یک تابع همگانی میتواند به هر زبان یک نام داشته باشد. کتابخانهی استاندارد این کار را برای همهی نامهای همگانیاش کرده و بیش از ۲۱ هزار برچسب @fa دارد. یک بستهی شخص ثالث هم میتواند همین کار را بکند. این بار تابع را در یک فایل فارسی مینویسیم و نام انگلیسیاش را با @en اعلام میکنیم:
واردسازی رشته
@en "Slug"
@fa "نامک"
همگانی تابع نامک(عنوان: رشته): رشته:
ناپایا خروجی := ""
ناپایا فاصله := نادرست
هر حرف در رشته.کوچک(رشته.پیرایش(عنوان)):
اگر (حرف >= "a" و حرف <= "z") یا (حرف >= "0" و حرف <= "9"):
اگر فاصله و خروجی != "":
خروجی += "-"
پایان
خروجی += حرف
فاصله = نادرست
وگرنه:
فاصله = درست
پایان
پایان
برگشت خروجی
پایان
تابع ریشه:
سرچاپ نامک("Hello, World!")
سرچاپ نامک(" Salam 0.6: what's new? ")
پایانبرنامهی انگلیسی Slug را فراخوانی میکند و برنامهی فارسی نامک را، و هر دو به یک تابع در یک بستهی کامپایلشده میرسند. (این تابع نمونه فقط حرفها و رقمهای لاتین را نگه میدارد، چون نامک نشانیهای وب معمولاً لاتین است؛ برای همین ورودیهایش انگلیسیاند.) برای نویسندهی کتابخانه یعنی یک کد منبع به دو جامعه خدمت میکند، بیآنکه کتابخانهی پوششی یا انشعاب (fork) لازم باشد. اینکه این به یک مزیت واقعی تبدیل شود یا نه، به این بستگی دارد که برنامهنویسان فارسیزبان بسته منتشر کنند و به کار ببرند، و این بخشی از پرسش باز است. نوشتهی یک زبان، دو خط خود مدل دوزبانه را شرح میدهد.
همین ابزارها به تکامل بستهها هم کمک میکنند. تابعی که بیکاره (deprecated) علامت خورده باشد کار میکند، اما هر فراخوان آن هنگام کامپایل هشدار W013 میگیرد؛ این راهی استاندارد به نویسندگان میدهد تا نام یک API را عوض کنند بیآنکه کاربران را یکشبه گرفتار کنند.
مستندات، آزمونها و ویرایشگرها هم بخشی از زیستبوماند
کتابخانهها فقط نیمی از چیزیاند که تازهواردان دنبالش میگردند. نیمهی دیگر این است: «میتوانم این را یاد بگیرم، و ویرایشگرم آن را میفهمد؟» مخزن سلام وزن زیادی روی این بخش گذاشته است:
- مستنداتی که از کد آزمودهشده ساخته میشوند. مرجع کتابخانه برای هر بسته یک صفحه دارد و مثالهایش هنگام ساخت وبسایت کامپایل میشوند. این مجله هم همینطور کار میکند: هر برنامهی سلام در این نوشتهها کامپایل میشود و آنهایی که خروجی دارند اجرا و با خروجی نوشتهشده مقایسه میشوند.
- یک دورهی رایگان با ۴۷ درس به انگلیسی و فارسی، از نخستین برنامه تا وبسرورها، در بخش آموزش.
salam docبرای پروژهی خودتان یک صفحهی API میسازد وsalam testتابعهایtest_(در فارسیآزمون) را در پروندههای*_test.salamاجرا میکند؛ پس نویسندگان بسته بدون ابزار اضافه مستندسازی و آزمون دارند.- ویرایشگرها. مخزن برای یازده ویرایشگر افزونه یا پروندهی نحو دارد، از جمله VS Code، Vim، Emacs، Sublime Text، Kate و محیطهای JetBrains، بهعلاوهی یک دستور زبان tree-sitter و یک سرور زبان (LSP) که درون خود کامپایلر ساخته شده است (
salam lsp). نوشتهی ابزارهای برنامهنویسی سلام آنها را پوشش میدهد.
یک تصمیم مربوط به پروانه هم به این بخش تعلق دارد. پروانهی مخزن GPL-3.0 است، اما پوشهی افزونهی VS Code، از جمله دستور زبان TextMate، با پروانهی MIT منتشر شده است. پروندهی readme دلیلش را میگوید: رنگآمیزی نحو فقط وقتی مفید است که پروژههای دیگر بتوانند دستور زبان را درون خود بگذارند، و برخی از آنها، از جمله GitHub Linguist، برای دستور زبانها فقط پروانههای سهلگیر را میپذیرند. نمونهی کوچکی از فکر کردن به زیستبوم، نه فقط به کامپایلر.
مشارکتکنندگان و راه ورود کار به پروژه
زیستبومهای متنباز از آدمها ساخته میشوند؛ پس عددها اهمیت دارند. در سال ۲۰۲۶ شاخهی اصلی حدود ۲٬۷۵۰ کامیت از نزدیک به پنجاه نام نویسندهی متفاوت دریافت کرد (برخی از آنها یک نفرند با املاهای مختلف). حدود دو سوم این کامیتها از طراح زبان، سید علی محمدیه، بوده و یک مشارکتکنندهی دیگر چند صد کامیت دیگر را نوشته است. این شکلی معمول برای یک زبان جوان است و در عین حال یک خطر: پروژهای که بیشترش بر دوش یک نفر است، به همان یک نفر وابسته است.
روند مشارکتهای بیرونی متعارف و مستند است. CONTRIBUTING.md روش کار با fork و شاخه، سبک پیام کامیت و ساختن کامپایلر را توضیح میدهد. برای گزارش اشکال و درخواست ویژگی قالبهای issue وجود دارد، یک آییننامهی رفتاری هست، و یکپارچهسازی پیوسته (CI) روی درخواستهای ادغام آزمونها، بررسیکنندههای سبک و پویش CodeQL را اجرا میکند. گفتوگوها در یک گروه تلگرام، در دیسکورد و در دو پیامرسان ایرانی، ایتا و بله، جریان دارد که نشان میدهد جامعهی نخستین کجاست.
صفحهی جامعه مشارکتهایی را هم فهرست میکند که به کامپایلر دست نمیزنند: نوشتن آموزش و مثال به هر یک از دو زبان، گزارش اشکال با نمونههای کوچک بازتولیدپذیر، و معرفی سلام به دانشآموزان و معلمان. برای یک زیستبوم جوان، اینها مشارکتهای کمارزشتری نیستند.
آیندهی زیستبوم زبان سلام: گامهای بعدی
این بخش تحلیل است، نه نقشهی راه منتشرشده. با نگاه به آنچه هست و آنچه نیست، اینها گامهاییاند که سلام را از «زبانی با کتابخانهی استاندارد بزرگ» به «زبانی با زیستبوم» میرسانند:
- نخستین بستههای واقعی شخص ثالث. فهرست بستهها به نخستین ردیفهایش نیاز دارد، ترجیحاً کتابخانههایی که کتابخانهی استاندارد عمداً پوشش نمیدهد: کلاینتهای ویژهی یک حوزه، چارچوبهایی با دیدگاه مشخص، اتصال به کتابخانههای محبوب C.
- فهرست چکیدههای پرشده، تا مدل اعتماد با بستههای واقعی به کار گرفته شود، نه فقط با آزمونها.
- نگهدارندگان بیشتر. پخش کردن بازبینی و مالکیت میان آدمهای بیشتر بزرگترین گام برای سلامت بلندمدت است؛ نوشتهی آمادگی برای محیط عملیاتی توضیح میدهد چرا خریداران اول به همین نگاه میکنند.
- پایداری. نویسندگان بسته باید مطمئن باشند که کدشان سال بعد هم کامپایل میشود. انتشار نسخهی ۱٫۰ با تعهد سازگاری برای زیستبوم از هر ویژگی منفردی مهمتر است.
- پروژههای نمونه با کد منبع، تا تازهواردان بتوانند سلامِ بومی و جاافتاده را در مقیاس بزرگ بخوانند.
هیچکدام از اینها تضمینشده نیست، و هر زبانی که امروز زیستبوم سالمی دارد از همین مرحلهی «فهرست خالی» گذشته است. کاری که سلام کرده برداشتن بیشتر بهانههای فنی است: انتشار یعنی یک برچسب گیت، استفاده یعنی یک فرمان، و مدل اعتماد از ابتدا طراحی شده است. باقی به آدمها بستگی دارد. نوشتهی آیندهی سلام به این مسیر بلندتر نگاه میکند.
پرسشهای متداول دربارهی بستهها و زیستبوم زبان سلام
چطور یک بستهی سلام نصب کنم؟
درون یک پروژه، salam add github.com/owner/repo را اجرا کنید. این فرمان تازهترین انتشار را دانلود میکند، آن را در salam.toml و salam.lock ثبت میکند و شما با import "github.com/owner/repo" واردش میکنید. بستههای کتابخانهی استاندارد اصلاً به نصب نیاز ندارند.
آیا زبان سلام فهرست مرکزی بستهها دارد؟
یک فهرست بستهها در مخزن اصلی هست که salam search آن را میخواند، اما خود بستهها مانند ماژولهای Go در مخزنهای گیت خودشان نگهداری میشوند. تا آبان ۱۴۰۵ این فهرست هنوز هیچ بستهی شخص ثالثی ندارد.
سلام چطور از بستههای دستکاریشده جلوگیری میکند؟
هر بستهی قفلشده یک چکیدهی SHA-256 دارد که salam deps آن را راستیآزمایی میکند. هر دستگاه هم چکیدهی هر نسخهای را که دانلود کرده به خاطر میسپارد و اگر نسخهی بعدی فرق داشته باشد متوقف میشود، و دانلودها با فهرستی بازبینیشده از چکیدههای منتشرشده در مخزن سلام مقایسه میشوند.
چطور در پروژهی متنباز زبان برنامهنویسی سلام مشارکت کنم؟
CONTRIBUTING.md را در گیتهاب بخوانید، یک issue کوچک انتخاب کنید و از یک شاخهی تازه درخواست ادغام بفرستید. مستندات، مثالها، ترجمه میان انگلیسی و فارسی، گزارش اشکال و بستههای خودتان همه مشارکتهای سودمندیاند.