زبان برنامهنویسی غیرانگلیسی زبانی است که واژههای کلیدیاش، و در حالت مطلوب کتابخانه و پیامهای خطایش، به یک زبان انسانی جز انگلیسی نوشته شده باشد. دشواری ساختن یک زبان برنامهنویسی فارسی یا عربی انتخاب واژههای کلیدی نیست؛ دشواری در همهی چیزهای اطراف آن است: نامهایی که بهطور طبیعی فاصله دارند، یک نویسهی نامرئی برای جدا کردن، دو رمزگذاری یونیکد برای یک حرف، واژههایی با دو معنا، ترتیب کلماتی که با انگلیسی فرق دارد، و پیامهای خطا، ویرایشگرها و ابزارهایی که همه باید با هم هماهنگ باشند. بیشتر تلاشها در جدول واژههای کلیدی متوقف میشوند و نتیجه، انگلیسیای است که لباس مبدل پوشیده.
سلام یک زبان همهمنظورهی کامپایلی است که کنار املای انگلیسیاش یک املای کامل فارسی هم دارد. این مقاله مسئلههای طراحیای را که یک زبان با خط فارسی با آنها روبهرو میشود، تصمیم سلام دربارهی هر کدام و هزینهی این تصمیمها را مرور میکند. جایگاه سلام را هم در تاریخچهی طولانی زبانهای برنامهنویسیای که به انگلیسی نوشته نمیشوند نشان میدهد.
چرا جدول واژههای کلیدی کافی نیست
یک زبان برنامهنویسی فقط از راه واژههای کلیدی با کاربرش تماس ندارد. بشمارید نوآموز در ساعت اول چه چیزهایی میخواند: واژههای کلیدی و نام گونهها، نام تابعها و متدهای داخلی، نام بستهها و تابعهای کتابخانهی استاندارد که صدا میزند، پیامهای خطای کامپایلر، مستندات، و رنگآمیزی و تکمیل خودکار ویرایشگر. اگر فقط مورد اول ترجمه شود، یادگیرنده در همهی جاهای دیگر با انگلیسی روبهرو میشود، از جمله در پراسترسترین جا: پیام خطا.
قاعدهی سلام این است که هر چیزی که زبان تعریف میکند دو املا دارد: واژههای کلیدی، گونهها، واژههای لفظی مثل درست، تابع ورود، تابعها و متدهای داخلی، بستههای کتابخانهی استاندارد و تابعهای عمومیشان، ثابتهای زمان کامپایل و پیامهای کامپایلر، که ۱٬۲۹۹ پیاماند. هر دو املا از یک تحلیلگر واژگانی میگذرند و به توکنهای یکسان میرسند. همین هستهی مشترک است که بقیهی این مقاله را ممکن میکند، چون هر قاعدهی ویژهی فارسی فقط در یک جا زندگی میکند: تحلیلگر واژگانی و کد بستهی زبانی. مقالهی طراحی دوزبانه این سازوکار را شرح میدهد.
تاریخچهی کوتاه زبانهای برنامهنویسی غیرانگلیسی
این ایده قدیمی است و هر تلاش بخش متفاوتی از مسئله را حل کرده است:
- ALGOL 68 زبان را از شکل چاپیاش جدا کرد و گزارش رسمیاش اجازه میداد واژههای کلیدی به زبانهای طبیعی دیگر باشند؛ نسخههایی به زبانهایی مثل روسی و آلمانی هم ساخته شد.
- صفحهگستردهها دهههاست نام تابعهایشان را بومی میکنند: در نسخهی آلمانی Microsoft Excel، تابع
SUMهمانSUMMEاست. صدها میلیون نفر از یک زبان فرمول بومیشده استفاده کردهاند بی آنکه آن را برنامهنویسی بدانند. - 1C:Enterprise، سکوی تجاری پرکاربرد در روسیه، یک زبان اسکریپت با واژههای کلیدی روسی و معادلهای انگلیسی دارد.
- Scratch بلوکهایش را به زبانهای بسیاری ترجمه میکند، و این کار خوب جواب میدهد چون در کد بلوکی واژهی کلیدیای برای تایپ کردن وجود ندارد.
- قلب (Qalb)، ساختهی رمزی ناصر (Ramsey Nasser) در سال ۲۰۱۲، یک Lisp است که سراسر به عربی نوشته میشود و تا حدی بیانیهای بود دربارهی اینکه انگلیسی چقدر عمیق در ابزارهای برنامهنویسی ریشه دوانده است.
- Wenyan-lang که در ۲۰۱۹ ساخته شد، برنامهها را به چینی کلاسیک مینویسد.
- Hedy، ساختهی فلین هرمانز (Felienne Hermans) برای آموزش، نحوی شبیه پایتون را گام به گام معرفی میکند و واژههای کلیدیاش را به زبانهای طبیعی بسیاری عرضه میکند.
- زبانهای اصلی گام کوچکتری برداشتند: پایتون ۳ (PEP 3131)، جاوا، Go و زبانهای دیگر حرفهای غیر ASCII را در شناسهها میپذیرند، پس نامها میتوانند به هر خطی باشند، هرچند واژههای کلیدی انگلیسی میمانند.
دو الگو برجسته است. پروژههایی که فقط واژههای کلیدی را ترجمه میکنند معمولاً در حد نمایش میمانند، چون کتابخانه و پیامهای خطا هنوز انگلیسیاند. پروژههایی که جلوتر میروند معمولاً زبانهای کوچک و تکمنظوره برای آموزشاند. هدف سلام یک زبان همهمنظوره و سیستمی کامل است که به کد بومی کامپایل میشود و املای فارسیاش کامل است، نه یک زیرمجموعهی آموزشی.
انتخاب واژههای کلیدی فارسی
واژهی کلیدی باید کوتاه، بیابهام و خوانا باشد و نباید واژهای را که مردم برای نامگذاری لازم دارند از دسترس خارج کند. در فارسی این هدفها بیشتر از انگلیسی با هم در کشمکشاند. برخی از انتخابهای سلام:
| انگلیسی | فارسی | معنای واژه |
|---|---|---|
func | تابع | تابع (اصطلاح ریاضی) |
ret | برگشت | بازگشت، برگشتن |
main | ریشه | ریشه، نقطهی آغاز |
mut | ناپایا | ناپایدار، تغییرپذیر |
struct | ساختار | ساختار |
enum | جداشمار | آنچه جداجدا شمرده میشود |
match | همخوان | هماهنگ، جور |
defer | دیرکن | به تأخیر بینداز |
as | برگردان | تبدیل کن، به شکل دیگر درآور |
end | پایان | پایان |
تابع ورود نمونهی خوبی از انتخابی است که پیامد دارد. ترجمهی بدیهی main واژهی اصلی است. سلام بهجای آن ریشه را به کار میبرد و تابع اصلی یک تابع معمولی است: برنامهای که آن را تعریف کند کامپایل میشود، اما نقطهی ورود ندارد. آموزش فارسی در همان درس اول دربارهی این موضوع هشدار میدهد و کامپایلر پیام «نقطهی ورود وجود ندارد» را نشان میدهد. سود این انتخاب آن است که اصلی برای نامهایی مثل صفحه اصلی آزاد میماند.
هزینه در واژههای خیلی کوتاه پیدا میشود. and در فارسی و است، یک حرف تنها که پرکاربردترین واژهی زبان هم هست. کلیدی کردن آن یعنی و هرگز نمیتواند نام متغیر باشد؛ و۱ یا واحد اشکالی ندارند. راه دیگر، یعنی واژهی بلندتری برای and، هر شرطی را نامأنوس میکرد.
یک واژه، دو معنا
فارسی واژههای کوتاه کمتری برای جریان کنترل دارد، پس دو واژهی کلیدی سلام عمداً دوبار به کار رفتهاند و تجزیهگر آنها را از روی جایگاهشان از هم تشخیص میدهد:
تادر ابتدای دستور همانuntil(حلقهی while سلام) است و درون سرآیندتکرارهمانto.هردر ابتدای دستور همانeachاست و درون سرآیندتکرارهمانby(گام).
این برنامه هر دو معنای هر دو واژه را به کار میبرد:
تابع شمار رقمها(عدد: صحیح): صحیح:
ناپایا ن := عدد
ناپایا تعداد := ۰
تا ن > ۰:
ن /= ۱۰
تعداد++
پایان
برگشت تعداد
پایان
تابع ریشه:
تکرار ۰ تا ۲۰ هر ۱۰ در ای:
سرچاپ «گام»، ای
پایان
هر عدد در [۷، ۱۴۰۵، ۲۰۲۶۱۱]:
سرچاپ عدد، شمار رقم ها(عدد)
پایان
پایاناجرای salam translate en روی این برنامه نشان میدهد کامپایلر هر تا و هر را چطور میخواند: حلقه به until تبدیل میشود، سرآیند تکرار به repeat ۰ to ۲۰ by ۱۰ in ای و حلقهی آخر به each. شناسهها و رقمهای فارسی همانطور که هستند میمانند و فایل انگلیسی با همان خروجی اجرا میشود:
// lang: en
func شمار رقمها(عدد: int): int:
mut ن := عدد
mut تعداد := ۰
until ن > ۰:
ن /= ۱۰
تعداد++
end
ret تعداد
end
func main:
repeat ۰ to ۲۰ by ۱۰ in ای:
println "گام", ای
end
each عدد in [۷, ۱۴۰۵, ۲۰۲۶۱۱]:
println عدد, شمار رقم ها(عدد)
end
endیک پیامد خوشایند هم دارد: until انگلیسی تازهکارها را گیج میکند، چون until c: در سلام تا وقتی c درست است تکرار میشود. تا فارسی بهطور طبیعی «تا وقتی که» خوانده میشود، پس املای فارسی رایجترین اشتباه املای انگلیسی را پیش نمیآورد.
نامهای چندکلمهای و نیمفاصله در کد فارسی
فارسی بسیاری از مفهومهای واحد را با دو یا چند کلمه مینویسد: شمار رقمها، جمع کل. به زور در قالب snake_case گذاشتن یا چسباندن این کلمات چیزی میسازد که هیچ خوانندهی فارسیزبانی آن را نمینوشت. برای همین سلام در هر دو زبان فاصله را درون نامها مجاز میداند: func line total(o: Order) در سلام انگلیسی درست است و تابع جمع ردیف(...) در سلام فارسی.
فارسی مسئلهی دومی هم دارد: نیمفاصله (Zero-Width Non-Joiner یا ZWNJ، نویسهی U+200C). این نویسه دو بخش یک واژه را بدون فاصلهی دیدنی جدا میکند، مثل رقمها. نویسندهها در به کار بردنش یکدست نیستند؛ یک واژه گاهی با نیمفاصله، گاهی با فاصله و گاهی چسبیده نوشته میشود، و دو شکل اول روی صفحه تقریباً یکسان دیده میشوند. تصمیم سلام این است:
- فاصله و نیمفاصله درون نام همارزند:
رقمهاورقم هایک ناماند (برنامهی بالاشمار رقمهارا تعریف میکند وشمار رقم هارا صدا میزند)؛ - شکلهای چسبیده نامهای دیگریاند:
رقمهاهمانرقم هانیست و پیشنهاد «منظورتان این بود؟» کامپایلر شکل فاصلهدار را پیشنهاد میدهد؛ - واژههای کلیدیای که نیمفاصله دارند، مثل
نادرستچاپ(printerr)، با فاصله هم نوشته میشوند، اما چسبیده نه.
مجاز بودن فاصله یک محدودیت میسازد: نام چندکلمهای نمیتواند یک واژهی کلیدی را بهعنوان یکی از کلمههایش داشته باشد، وگرنه تجزیهگر نمیفهمد نام کجا تمام میشود. در انگلیسی این کمتر دردسر میسازد؛ در فارسی بسته (package) و تا واژههای روزمره هم هستند، پس نامی مثل بسته بندی باید طور دیگری نوشته شود.
دو رمزگذاری برای یک حرف: «ی» و «ک» عربی و فارسی
یونیکد برای «ی» عربی ي (U+064A) و «ی» فارسی ی (U+06CC)، و برای «ک» عربی ك (U+0643) و «ک» فارسی ک (U+06A9) نقطهکدهای جداگانه دارد. وسط واژه اینها کاملاً یکسان دیده میشوند. چیدمانهای قدیمی صفحهکلید، برخی سیستمعاملها و حجم زیادی از متنهای موجود شکلهای عربی را تولید میکنند، پس دو برنامهنویس میتوانند نام «یکسانی» را تایپ کنند و بایتهای متفاوتی بگیرند.
کامپایلری که نامها را بایت به بایت مقایسه کند شناسهی ناشناختهای گزارش میدهد که دقیقاً شبیه شناسهی تعریفشده است، و این بدترین نوع پیام خطاست. تحلیلگر واژگانی سلام هر نام را هنگام خواندن یکسانسازی میکند: «ی» و «ک» عربی به حرفهای فارسی تبدیل میشوند، نیمفاصله به فاصله، و اعرابگذاری اختیاری (حرکتها) حذف میشود. پس كتاب، کتاب و کِتاب یک شناسهاند. برای داده، و نه کد، بستهی arabic در کتابخانهی استاندارد جلوتر میرود و حرفها، کشیده، اعراب و رقمها را در یک کلید جستوجو یکی میکند.
ترتیب کلمات و جهت خواندن
فارسی زبانی با ترتیب فاعل، مفعول، فعل است: فعل معمولاً در آخر میآید. نحو برنامهنویسی بیشتر عملگر اول یا واژهی کلیدی اول است: اگر پیش از شرط، نام تابع پیش از آرگومانها، برگشت پیش از مقدار. سلام دستور زبانش را برای فارسی جابهجا نمیکند. یک دستور فارسی همان درختی است که دستور انگلیسی هست، فقط واژههایش عوض شدهاند.
این کار دو املا را دقیقاً قابل تبدیل به هم نگه میدارد و دلیل این است که salam translate میتواند توکن به توکن کار کند. بهایش این است که برخی سطرهای فارسی بیشتر شبیه تیتر یا دستورالعمل خوانده میشوند تا جمله. انتخاب واژهها این را نرمتر میکند: بسیاری از نامهای فارسی متدها فعل امرند که در ابتدای عبارت طبیعی خوانده میشوند، مثل بیفزا برای push، آزادکن برای free، دیرکن برای defer و بشکن برای break. واژههای مقایسه مثل بزرگتر اجازه میدهند شرط با کلمه خوانده شود، که مشکل وارونه شدن < و > در متن راست به چپ را هم دور میزند؛ این موضوع در مقالهی برنامهنویسی راست به چپ آمده است.
پیامهای خطا به زبان خواننده
پیام خطا همان جایی است که یک زبان ترجمهشده بیشتر از هر جای دیگر به انگلیسی برمیگردد. در سلام هر پیام نسخهی فارسی دارد، خود کد خطا با رقم فارسی نوشته میشود و راهنماها به نامهای فارسی اشاره میکنند:
خطا[خطا۰۰۱]: شناسهی 'upper' در یک فایل فارسی باید فارسی باشد
= راهنما: نام فارسی آن 'بزرگ' است
= اصلاح: نوشتن 'بزرگ'این پیام اصلاحی هم پیشنهاد میدهد که salam check --fix آن را اعمال میکند. کدها بین زبانها مشترکاند (خطا۰۰۱ همان E001 است)، پس فارسیزبان میتواند منابع انگلیسی دربارهی همان خطا را پیدا کند. پیامهای ابزارها هم از زبان فایل پیروی میکنند: salam format و salam translate وقتی فایل فارسی بگیرند گزارش کارشان را به فارسی میدهند.
ابزارها هم باید هماهنگ باشند
زبان یعنی ابزارهایش هم، و هر ابزار باید قاعدههای فارسی را بداند:
- ویرایشگرها. افزونههای Visual Studio Code و ده ویرایشگر دیگر هر دو مجموعه واژهی کلیدی را رنگآمیزی میکنند و از روی جدولهای خود کامپایلر تولید میشوند تا از آن عقب نمانند. سرور زبان (LSP) درون
salamتکمیل خودکار، راهنمای شناور، تغییر نام و رنگآمیزی معناییای فراهم میکند که نامهای چندکلمهای فارسی را میفهمد، و به ویرایشگری که با محیط فارسی اجرا شده پیامها و متن راهنمای فارسی میفرستد. صفحهی ابزارها را ببینید. - قالببند.
salam formatکد فارسی را دوباره تورفتگی میدهد و فاصلهی اطراف عملگرها را یکدست میکند، بی آنکه املای نامها را دست بزند. - ویرایشگر آنلاین برای فارسی کل چیدمانش، از جمله بخش کد، را راست به چپ میکند.
- مترجم.
salam translateاز تحلیلگر واژگانی خود کامپایلر استفاده میکند، پس قاعدههای نیمفاصله و «ی» را دقیقاً یکسان اعمال میکند؛ مقالهی درون salam translate را ببینید.
چون همهی اینها تحلیلگر واژگانی و جدولهای خود کامپایلر را به کار میبرند، هر قاعدهی فارسی یک بار پیادهسازی میشود.
زبان برنامهنویسی عربی چطور؟
فارسی و عربی خط مشترکی دارند، پس بخش بزرگی از این کار به عربی هم میرسد: سلام رقمهای عربی را در عددها میپذیرد، «ی» و «ک» عربی را در نامها به فارسی تبدیل میکند و کتابخانهی استانداردش متن عربینویس را با بستههای arabic، unicode و bidi پردازش میکند. اما سلام امروز دقیقاً دو بستهی زبانی دارد، انگلیسی و فارسی. مجموعه واژهی کلیدی عربی وجود ندارد و عربزبانی که سلام بنویسد واژههای کلیدی فارسی را میخواند، که بسیاری از آنها ریشهی عربی دارند (مثل تابع و صحیح) و برخی کاملاً فارسیاند (ساختار، پایان).
بستهی زبانی عربی تصمیمهای خودش را لازم دارد: انتخاب واژههای کلیدی، ساختهای دستوریای که عربی برای فعل امر به کار میبرد و ترجمهی همهی پیامها. معماری نیازی به تغییر ندارد، چون کامپایلر همین حالا بستهی زبانی را از هر چیزی که بعد از تحلیلگر واژگانی میآید جدا کرده است.
درسهایی برای هر کسی که زبانی را بومی میکند
- کل سطح زبان را ترجمه کنید. واژههای کلیدی بهتنهایی یادگیرنده را در حساسترین لحظهها به خواندن انگلیسی وادار میکنند.
- یکسانسازی را در تحلیلگر واژگانی انجام دهید. همارزیهایی مثل فاصله و نیمفاصله، یا دو رمزگذاری یک حرف، باید در یک تابع باشند که همهی ابزارها از آن استفاده کنند.
- تبدیل دقیق را بر دستور زبان طبیعی ترجیح دهید. نگاشت توکن به توکن، ترجمه، کتابخانهی مشترک و کدهای خطای مشترک را ممکن میکند.
- کدهای خطا را مستقل از زبان نگه دارید. کد خطا پل میان جامعههاست.
- بپذیرید که واژههای کوتاه گراناند. هر واژهی کلیدی یک واژه را از فهرست نامهای ممکن کم میکند.
آموزش رایگان زبان را به فارسی یاد میدهد و همان ۴۷ درس در سایت انگلیسی هم به انگلیسی وجود دارد.
پرسشهای پرتکرار دربارهی زبان برنامهنویسی فارسی
آیا زبان برنامهنویسی فارسی وجود دارد؟
بله. سلام را میشود از واژههای کلیدی تا فراخوانیهای کتابخانهی استاندارد سراسر به فارسی نوشت و کامپایلرش خطاها را به فارسی گزارش میکند. همان زبانی است که املای انگلیسیاش هست و به فایل اجرایی بومی کامپایل میشود.
چرا واژههای کلیدی یک زبان موجود را ترجمه نکنیم؟
چون کتابخانه، پیامهای خطا و ابزارها همچنان انگلیسی میماندند، و چون مسئلههای ویژهی فارسی مثل نامهای چندکلمهای، نیمفاصله و دو رمزگذاری «ی» و «ک» به پشتیبانی در تحلیلگر واژگانی نیاز دارند، نه فقط در فهرست واژههای کلیدی.
آیا سلام را میشود به عربی نوشت؟
نه با واژههای کلیدی عربی. سلام مجموعه واژهی کلیدی انگلیسی و فارسی دارد. شکل عربی حرفها و رقمهای عربی را میپذیرد و کتابخانهی استانداردش متن عربی را پردازش میکند، اما بستهی زبانی کامل عربی وجود ندارد.
آیا نامهای فارسی فاصلهدار کامپایل را کند یا پیچیده میکنند؟
نه. تحلیلگر واژگانی کلمههای یک نام را به یک شناسه تبدیل میکند و از آن پس یک نام معمولی است. تنها محدودیت این است که نام چندکلمهای نمیتواند یک واژهی کلیدی را بهعنوان یکی از کلمههایش داشته باشد.