بستهها و پروندهها
برنامههای بزرگ در چند پرونده نوشته میشوند. هر پرونده به یک بسته تعلق دارد و هر بسته فقط چیزهایی را با بقیهی برنامه شریک میشود که همگانی کرده است.
بسته
پروندهای که با بسته نام شروع شود به آن بسته تعلق دارد. فقط تابعها، پایاها، گونهها و فیلدهایی که همگانی شدهاند از بیرون بسته در دسترساند؛ بقیه جزئیات درونیاند و میتوانید بعداً عوضشان کنید بیآنکه کد کس دیگری خراب شود. پروندهای که خط بسته ندارد در بستهی main است.
بسته ابزار
همگانی پایا نسخه := "۱.۰"
تابع دوبرابر(ع: صحیح): صحیح:
برگشت ع * ۲
پایان
همگانی تابع چهاربرابر(ع: صحیح): صحیح:
برگشت دوبرابر(دوبرابر(ع))
پایاناین پرونده ریشه ندارد و بهتنهایی اجرا نمیشود؛ قرار است برنامهای آن را فراخوانی کند، همانطور که در بخش بعد میبینید.
فراخوانی پروندههای خودتان
فراخوانی نام "پرونده.salam" پروندهای از پروژهی خودتان را با یک نام کوتاه به برنامه میآورد و با نام.چیزی به عضوهای همگانیاش میرسید. مسیر نسبت به پروندهای است که فراخوانی را نوشته.
فراخوانی ابزار "pkg-lib.salam"
تابع ریشه:
سرچاپ ابزار.چهاربرابر(۵)
سرچاپ "نسخهی ابزار:", ابزار.نسخه
پایان- نوشتن نام اختیاری است:
فراخوانی "lib/money.salam"با نام پرونده در دسترس است، یعنیmoney.چیزی. هر جا نام پرونده بلند یا نامفهوم است، نام کوتاهی برایش بگذارید. - مسیری که با
@/شروع شود از ریشهی پروژه حساب میشود، نه از پروندهی فعلی؛ پسفراخوانی "@/lib/money.salam"از هر پوشهای در پروژه به همان پرونده میرسد. پروژه را از پوشهی خودش بسازید تا ریشه همان جایی باشد که انتظار دارید. - مسیر را با
./شروع نکنید. مترجم با این پیام میایستد و دو شکل درست را هم پیشنهاد میدهد:E008: مسیر فراخوانی './lib/money.salam' نباید با './' آغاز شود. - پروندهای که پیدا نشود هم خطاست (
E008) و هیچوقت بیصدا نادیده گرفته نمیشود.
واردسازی کتابخانه
کتابخانههای استاندارد با نام فارسیشان و بدون نقلقول وارد میشوند، مثل واردسازی رشته یا واردسازی سیستم عامل، و تابعهایشان هم نام فارسی دارند. بستهای که درون بستهی دیگری است با نقطه نوشته میشود، مثل واردسازی کدگذاری.جیسون، و با بخش آخرش به کار میرود: جیسون.دریافت(...). بهطور خلاصه: واردسازی برای کتابخانههاست و فراخوانی برای پروندههای خودتان.
واردسازی رشته
واردسازی ریاضی
تابع ریشه:
متن := " سلام دنیا "
سرچاپ رشته.پیرایش(متن)
سرچاپ رشته.شامل است(متن، "دنیا")
سرچاپ ریاضی.جذر(۸۱.۰)، ریاضی.توان(۲.۰، ۱۰.۰)
پایانواردسازی کدگذاری.جیسون
تابع ریشه:
سفارش := `{"id": 42, "item": "دفتر", "qty": 3}`
اگر وارونه جیسون.معتبر(سفارش):
سرچاپ "جیسون معتبر نیست"
برگشت ۱
پایان
سرچاپ "سفارش"، جیسون.دریافت عدد(سفارش، "id")
سرچاپ جیسون.دریافت عدد(سفارش، "qty")، "عدد"، جیسون.دریافت(سفارش، "item")
سرچاپ جیسون.دارد(سفارش، "coupon")
پایانواردسازیای که به کار نرود خطاست (E082)، پس فهرست واردسازیهای بالای هر پرونده همیشه دقیقاً میگوید آن پرونده به چه چیزهایی وابسته است.
همگانی و خصوصی
خصوصی بودن برای عضوهای ساختار هم کار میکند. در این بستهی بانک، دارنده همگانی است ولی موجودی نه؛ پس تنها راه تغییر موجودی تابعهای واریز و برداشت است که هر مبلغی را بررسی میکنند. تابع کمکی مبلغ معتبر هم خصوصی است. حساب.باز کن یک سازندهی ایستاست؛ راه معمول برای ساختن مقدار آماده از گونهای که فیلدهایش خصوصیاند.
بسته بانک
همگانی پایا سقف_واریز := ۱۰۰۰۰۰۰
ساختار حساب:
همگانی دارنده: رشته = ""
موجودی: صحیح = ۰
همگانی ایستا تابع باز کن(دارنده: رشته): حساب:
برگشت حساب { دارنده = دارنده }
پایان
همگانی تابع مانده(): صحیح:
برگشت این.موجودی
پایان
همگانی ناپایا تابع واریز(مبلغ: صحیح): منطقی:
اگر وارونه مبلغ معتبر(مبلغ) یا مبلغ > سقف_واریز:
برگشت نادرست
پایان
این.موجودی += مبلغ
برگشت درست
پایان
همگانی ناپایا تابع برداشت(مبلغ: صحیح): منطقی:
اگر وارونه مبلغ معتبر(مبلغ) یا مبلغ > این.موجودی:
برگشت نادرست
پایان
این.موجودی -= مبلغ
برگشت درست
پایان
پایان
تابع مبلغ معتبر(مبلغ: صحیح): منطقی:
برگشت مبلغ > ۰
پایانفراخوانی بانک "pkg-bank.salam"
تابع ریشه:
ناپایا ح := بانک.حساب.باز کن("سارا")
سرچاپ ح.واریز(۵۰۰)، ح.برداشت(۸۰۰)، ح.برداشت(۱۲۰)
سرچاپ ح.دارنده، ح.مانده()
سرچاپ ح.واریز(بانک.سقف_واریز + ۱)
پایاناگر در برنامه بنویسید ح.موجودی، مترجم نمیپذیرد و میگوید فیلد در ساختار خصوصی است (E017)، و برای صدا زدن تابع کمکی هم پیامی مثل این میدهد: E017: 'مبلغ معتبر' توسط بستهی 'بانک' صادر نشده است (آن را 'همگانی' کنید). چیزی را برای این همگانی کنید که کد دیگری قرار است به کارش ببرد، نه برای ساکت کردن خطا؛ هر چیز همگانی قولی است که باید پایش بمانید.
بستهای در یک پوشه
وقتی بستهای بزرگ شد، آن را در چند پرونده درون یک پوشه بنویسید. پوشه را همنام بسته بگذارید و پروندهای با همان نام در آن بسازید، مثل shop/shop.salam. فراخوانی همین یک پرونده همهی پروندههای .salam دیگر آن پوشه را هم جزو همان بسته میآورد.
| پرونده | محتوا |
|---|---|
pkg-folder.salam | برنامه؛ shop/shop.salam را فراخوانی میکند |
shop/shop.salam | بسته فروشگاه، واردسازی رشته، تابع خصوصی برچسب قیمت و تابع همگانی خوشامد |
shop/cart.salam | بسته فروشگاه و تابع همگانی جمع سبد |
فراخوانی فروشگاه "shop/shop.salam"
تابع ریشه:
سرچاپ فروشگاه.خوشامد("سارا")
سرچاپ فروشگاه.جمع سبد([۱۲۵۰، ۳۹۹، ۲۰۵])
پایانپروندههای یک بسته همه چیز را با هم شریکاند: cart.salam تابع خصوصی برچسب قیمت را از shop.salam صدا میزند و رشته را بدون واردسازی به کار میبرد، چون بسته یک بار آن را وارد کرده است.
نامهای دوزبانه
در پروندهی فارسی باید نامهای فارسی را به کار ببرید و نام انگلیسی مثل رشته.Len خطاست؛ پروندهی انگلیسی هم نام انگلیسی میخواهد. هر تابع کتابخانهی استاندارد هر دو نام را دارد: کتابخانه به انگلیسی نوشته شده و نام فارسی هر تابع با @fa کنارش آمده است، و همین است که پروندههای فارسی میتوانند صدایش بزنند. تابعهای همگانی خودتان را هم میتوانید همینطور با @en و @fa دو نام بدهید:
@en "Twice"
@fa "دوبار"
همگانی تابع دوبار(ع: صحیح): صحیح:
برگشت ع * ۲
پایان
تابع ریشه:
سرچاپ دوبار(۲۱)
پایانکتابخانهای که به انگلیسی نوشته شده و تابعهایش @fa دارند، از برنامهی فارسی با نام فارسی صدا زده میشود؛ مثلاً تابع Twice با برچسب @fa "دوبار" در پروندهی فارسی با دوبار(۲۱) صدا زده میشود و ۴۲ برمیگرداند.
ترتیب تعریفها
سلام ترتیب مشخصی برای تعریفهای سطح بالای هر پرونده میخواهد تا همهی پروندهها یکجور خوانده شوند، و هر گام کد خطای خودش را دارد:
بسته- واردسازیها، سپس فراخوانیها (واردسازی پس از فراخوانی خطای
E108است) - پایاها و متغیرهای سراسری (اگر پس از تابع یا گونه بیایند،
E084وE085) - گونهها: ساختار، جداشمار، میانجی و کاربست (اگر پس از تابعی بیایند،
E087) - تابعها، اول خصوصیها و در پایان تابعهای همگانی
فرمان salam format کد را مرتب میکند و خیلی از این جابهجاییها را خودش انجام میدهد.
چیدمان یک پروژه
salam new shop پوشهای به نام shop با پروندهی main.salam که نقطهی شروع برنامه است و یک salam.toml که نام پروژه را نگه میدارد میسازد. هر پروژه از main.salam شروع میشود: درون آن پوشه، فرمان salam build بدون هیچ نام پروندهای همین پرونده را به برنامهای همنام پوشه تبدیل میکند، و پوشهای که آن را ندارد ساخته نمیشود. از اینجا پروژه معمولاً اینطور رشد میکند:
main.salamکوتاه میماند: ورودیها را میخواند، بستهها را صدا میزند و نتیجه را چاپ میکند.- هر بخش برنامه پوشهای میشود که یک بسته است، مثل
cart/cart.salamیاstore/store.salam، و با بزرگ شدن به چند پرونده تقسیم میشود. - بستهها یکدیگر را با مسیرهای
@/فراخوانی میکنند تا جابهجا کردن یک پرونده، فراخوانیهای درونش را خراب نکند. - هر بسته رابط همگانیاش را کوچک نگه میدارد و نامهایش را با
@enو@faدوزبانه میکند.
همهچیز همراه سلام است
کل کتابخانه همراه مترجم نصب میشود، از جمله کارخواههای پایگاه داده مانند db.sqlite، db.postgres و db.redis، یادگیری ماشین (tensor، nn، llm)، صدا، سرویسهای شبکه مانند grpc، ssh و net.websocket، و gui.webview، opencv و excel. اینها مانند هر کتابخانهی دیگری وارد میشوند و پیش از آن چیزی برای افزودن نیست. کتابخانهای که به یک کتابخانهی سیستمی نیاز دارد، مانند db.sqlite، آن را نخستین باری که برنامهای با آن را ترجمه میکنید پیدا یا ساخته میکند.
بستههایی از گیتهاب
بستههایی که دیگران نوشتهاند در مخزن خودشان هستند. بستهای که در کتابخانهی استاندارد نیست با مخزنش نام برده و با یک رشته وارد میشود: import "github.com/owner/repo" نام repo را میسازد، و import "github.com/owner/repo/sub" به بستهی پوشهی sub همان مخزن میرسد. چنین واردسازیای فقط درون یک پروژه کار میکند، چون salam.toml پروژه میگوید کدام نسخه به کار برود و salam.lock دقیقاً همان چیزی را که بارگیری شده نگه میدارد، تا همهی رایانهها یک کد را بسازند.
| فرمان | کارش |
|---|---|
salam add github.com/owner/repo | تازهترین انتشار (یا @v1.2.0) را به salam.toml میافزاید، بارگیریاش میکند و salam.lock را بهروز میکند |
salam remove github.com/owner/repo | آن را از هر دو پرونده برمیدارد |
salam update | همهی بستهها، یا آنهایی را که نام برده شدهاند، به تازهترین انتشارِ همان نسخهی اصلی میبرد؛ salam update pkg@latest به نسخهی اصلی تازه میرود |
salam deps | هر چه در salam.lock آمده بارگیری میکند و چکسام هر کدام را میسنجد؛ پس از کلون کردن یک پروژه اجرایش کنید |
salam install github.com/owner/tool | main.salam یک برنامه را میسازد و در ~/.salam/bin میگذارد؛ بدون نام، پروژهای را که در آن هستید نصب میکند |
salam uninstall hello | برنامهای را که salam install گذاشته برمیدارد؛ بدون نام، فهرستشان را نشان میدهد |
salam search websocket | بستهها را در کتابخانهی استاندارد و در فهرست بستهها پیدا میکند |
هر نسخه از هر بسته یک بار در ~/.salam/pkg نگه داشته میشود. اگر git نصب باشد بارگیری با git انجام میشود؛ بی git، بستههای گیتهاب به شکل بایگانی دریافت و با خود سلام باز میشوند. وابستگیهای یک بسته از salam.toml خود آن بسته پیدا میشوند، و اگر دو بسته نسخههای گوناگونی بخواهند، نسخهی تازهتر به کار میرود.
افزودن، بهروزرسانی، نوشتن و انتشار بسته صفحهی جداگانه دارد: مدیر بسته.
هر بستهی کتابخانهی استاندارد صفحهی خودش را در مرجع کتابخانه دارد، و درس بعد خطاهای مترجم، از جمله همینها، را یکجا آورده است.