آیا هوش مصنوعی می‌تواند به فارسی کد بنویسد؟ تولید و اعتبارسنجی برنامه‌های سلام فارسی

نوشتن کد فارسی برای یک مولد کد آزمونی سخت‌تر از نوشتن کد انگلیسی است، چون نمونه‌ی فارسی برای یادگیری بسیار کم است. در این نوشته می‌بینیم کجا اشتباه رخ می‌دهد، کامپایلر سلام چه چیزهایی را به فارسی می‌گیرد و سه راه عملی برای رسیدن به برنامه‌ی فارسی درست کدام است.

در این مقاله
  1. کد فارسی در زبان سلام چه شکلی دارد؟
  2. چرا کد فارسی برای مدل‌های هوش مصنوعی سخت‌تر است؟
  3. کامپایلر سلام به‌عنوان داور، به زبان فارسی
  4. راهبرد ۱: تولید به انگلیسی، سپس ترجمه به فارسی
  5. راهبرد ۲: نوشتن مستقیم به فارسی، با مرجع زبان در دسترس مدل
  6. راهبرد ۳: تعیین رفتار با آزمون‌های فارسی
  7. جایگاه دستیار هوشمند سلام
  8. آنچه نمی‌توانیم بگوییم
  9. پرسش‌های متداول درباره‌ی هوش مصنوعی و کد فارسی

بله، ابزارهای هوش مصنوعی می‌توانند به فارسی کد بنویسند، اما فقط وقتی می‌شود به نتیجه اعتماد کرد که چیزی آن را بررسی کند. زبان برنامه‌نویسی سلام زبانی است که واژه‌های کلیدی، گونه‌ها، کتابخانه‌ی استاندارد و پیام‌های کامپایلرش همه به فارسی هم وجود دارند؛ پس برنامه‌ی سلام فارسی کد واقعی است که به فایل اجرایی بومی کامپایل می‌شود، نه توضیحی ترجمه‌شده کنار کد. همین آن را به آزمونی سخت برای مولدهای کد تبدیل می‌کند: کد منبع فارسی در داده‌های آموزشی بسیار کمیاب است، خط فارسی از راست به چپ نوشته می‌شود و جزئیات کوچکی مثل یک نیم‌فاصله یا شکل عربی یک حرف معنا را عوض می‌کند. چیزی که این کار را شدنی می‌کند این است که کامپایلر سلام کد فارسی را درست به همان سخت‌گیری کد انگلیسی بررسی می‌کند و خطاهایش را به فارسی توضیح می‌دهد.

در این نوشته می‌بینیم سلام فارسی چه شکلی دارد، کد فارسی تولیدشده معمولاً کجا خطا می‌کند، کامپایلر و اجراکننده‌ی آزمون‌ها چطور این خطاها را می‌گیرند، و سه راهبرد عملی برای رسیدن به برنامه‌های فارسی‌ای که بتوان به آن‌ها اعتماد کرد.

کد فارسی در زبان سلام چه شکلی دارد؟

یک برنامه‌ی سلام فارسی واژه‌های کلیدی فارسی و نام‌های فارسی دارد و اگر بخواهید، عددهای فارسی و ویرگول فارسی هم در آن به کار می‌رود. تابع ورودی برنامه ریشه است، بلوک‌ها با پایان بسته می‌شوند، سرچاپ یک خط چاپ می‌کند و متنی که میان گیومه‌های « و » بیاید رشته است، درست مانند متنی که میان دابل‌کوتیشن بیاید:

سلام
ساختار کالا:
    همگانی نام: رشته
    همگانی تعداد: صحیح
    همگانی قیمت: صحیح
پایان

تابع جمع سبد(سبد: وکتور<کالا>): صحیح:
    ناپایا جمع := ۰
    هر ک در سبد:
        جمع += ک.تعداد * ک.قیمت
    پایان
    برگشت جمع
پایان

تابع ریشه:
    ناپایا سبد خرید := وکتور {} برگردان وکتور<کالا>
    دیرکن سبد خرید.آزادکن()
    سبد خرید.بیفزا(کالا { نام = «نان»، تعداد = ۲، قیمت = ۴۵ })
    سبد خرید.بیفزا(کالا { نام = «پنیر»، تعداد = ۱، قیمت = ۱۲۰ })
    سبد خرید.بیفزا(کالا { نام = «چای»، تعداد = ۳، قیمت = ۶۰ })
    کل := جمع سبد(سبد خرید)
    سرچاپ «جمع کل:»، کل
    اگر کل > ۳۰۰:
        سرچاپ «ارسال رایگان است»
    وگرنه:
        سرچاپ «هزینه‌ی ارسال اضافه می‌شود»
    پایان
پایان
خروجیجمع کل: 390 ارسال رایگان است

نام تابع جمع سبد دو کلمه است و نام متغیر سبد خرید هم همین‌طور. سلام فاصله را درون نام‌ها مجاز می‌داند، چون در فارسی بسیاری از مفهوم‌های یکپارچه با دو کلمه نوشته می‌شوند. عددهای درون کد منبع فارسی‌اند، اما عددهای چاپ‌شده با رقم‌های لاتین (ASCII) بیرون می‌آیند؛ جزئیاتی که هنگام بررسی خروجی اهمیت دارد. نوشته‌ی یک زبان، دو خط طراحی دوزبانه‌ی سلام را کامل شرح می‌دهد.

چرا کد فارسی برای مدل‌های هوش مصنوعی سخت‌تر است؟

مولدهای کد از کدهای عمومی یاد می‌گیرند. کد عمومی نوشته‌شده با هر زبان برنامه‌نویسی غیرانگلیسی بسیار کمتر از پایتون یا جاوااسکریپت است، و املای فارسی سلام از آن هم جوان‌تر است؛ پس مدل تقریباً چیزی از آن ندیده است. چند ویژگی فارسی افتادن در این شکاف‌ها را آسان می‌کند:

  • واژه‌های کلیدی دومعنایی. تا در آغاز یک دستور همان until است و درون سرآیند تکرار همان to؛ هر در آغاز دستور each است و درون تکرار گام شمارش (by). هر دو فارسی طبیعی‌اند و هر دو را آسان می‌شود جای نادرست به کار برد.
  • نام‌های داخلی باید فارسی باشند. در یک فایل فارسی، len خطاست و تابع داخلی طول است. مدلی که تابع‌های داخلی انگلیسی را وارد کد فارسی می‌کند، یکی از رایج‌ترین خطاهاست.
  • نویسه‌های نامرئی. نیم‌فاصله (ZWNJ، U+200C) بخشی از املای درست فارسی است، مانند کتاب‌ها. درون یک نام، سلام نیم‌فاصله و فاصله را یکی می‌داند، اما واژه‌ی کلیدی‌ای که بخش‌هایش به هم چسبیده باشد، مثلاً نادرستسرچاپ به‌جای نادرست‌سرچاپ، شناسه‌ای ناشناخته است.
  • شکل‌های عربی حروف. فارسی و عربی «ی» و «ک» را با کدهای متفاوت ذخیره می‌کنند (ی/ي و ک/ك). متنی که با صفحه‌کلید عربی تایپ شده باشد، یا مدلی که بیشتر متن عربی دیده باشد، این دو را با هم قاطی می‌کند.
  • واژه‌های کوتاه رزروشده. و واژه‌ی کلیدی (به معنای and) است و هرگز نمی‌تواند نام باشد.
  • قالب عدد. جداکننده‌ی اعشار فارسی ٫ پذیرفته نمی‌شود؛ ممیز همیشه . است، مانند ۳.۱۴.
  • نقطه‌ی ورود. تابع ورودی ریشه است. اصلی، که ترجمه‌ی تحت‌اللفظی main است، فقط یک تابع معمولی است.

هیچ‌کدام از این‌ها برای یک فارسی‌زبان عجیب نیست، اما هرکدام جایی است که مدلی که بیشتر با کد انگلیسی آموزش دیده، چیزی باورپذیر و نادرست تولید کند. نوشته‌ی طراحی زبان برنامه‌نویسی برای فارسی و عربی توضیح می‌دهد که زبان چرا این انتخاب‌ها را کرده است.

کامپایلر سلام به‌عنوان داور، به زبان فارسی

کامپایلر زبان هر فایل را از واژه‌های کلیدی‌اش تشخیص می‌دهد و خطاها را به همان زبان گزارش می‌کند، با همان کدهای خطای انگلیسی (که در فارسی با رقم‌های فارسی نوشته می‌شوند). این برنامه‌ی کوتاه از len انگلیسی استفاده کرده و متغیری را ناپایا (تغییرپذیر) تعریف کرده که هرگز تغییر نمی‌کند:

متن
تابع ریشه:
    ناپایا اعداد := [۳، ۵، ۸]
    سرچاپ len(اعداد)
پایان

salam check هر دو مشکل را گزارش کرد و برای هر کدام راه اصلاح هم داد:

متن
خطا[خطا۰۰۱]: شناسه‌ی 'len' در یک فایل فارسی باید فارسی باشد
 --> bad.salam:3:11
  |
3 |     سرچاپ len(اعداد)
  |           ^
  |
  = راهنما: نام فارسی آن 'طول' است
  = اصلاح: نوشتن 'طول'
خطا[خطا۰۶۹]: متغیر 'اعداد' با کلیدواژه‌ی 'ناپایا' تعریف شده اما هرگز تغییر نکرده است؛ 'ناپایا' را حذف کنید یا آن را 'پایا' تعریف کنید
 --> bad.salam:2:5
  |
2 |     ناپایا اعداد := [۳، ۵، ۸]
  |     ^
  |
  = اصلاح: حذف 'ناپایا'

خطای نخست می‌گوید شناسه‌ی len در فایل فارسی باید فارسی باشد و نام فارسی‌اش طول است؛ دومی خطای ۰۶۹ است، یعنی متغیر تغییرپذیری که هیچ‌وقت تغییر نمی‌کند. salam check --fix این اصلاح‌های بی‌خطر را مستقیم در فایل اعمال می‌کند. اگر بازبینی‌کننده انگلیسی را راحت‌تر می‌خواند، --error-lang=en همین پیام‌ها را برای فایل فارسی به انگلیسی چاپ می‌کند و --error-lang=fa برعکس. فایلی که تابع ورودی‌اش را اصلی نامیده باشد هم گیر می‌افتد: ساختن آن با این پیام متوقف می‌شود: «نقطه‌ی ورود وجود ندارد: یک تابع 'ریشه' تعریف کنید».

یکسان‌سازی نویسه‌ها در جهت دیگر کار می‌کند. کامپایلر شکل‌های عربی و فارسی حروف، و فاصله یا نیم‌فاصله درون یک نام را یک شناسه می‌داند؛ پس ورودی درهمی که ممکن است یک مدل تولید کند باز هم درست پیدا می‌شود. اما محتوای رشته‌ها دقیقاً همان‌طور که نوشته شده‌اند می‌ماند:

سلام
تابع ریشه:
    تعداد کتاب‌ها := ۱۲
    سرچاپ تعداد كتاب ها + ۳
    سرچاپ «یک» == «يک»
پایان
خروجی15 false

نام متغیر با «ک» فارسی و نیم‌فاصله تعریف شده و با «ك» عربی و فاصله به کار رفته، و برنامه باز هم آن را پیدا کرده است. دو رشته فقط در «ی» با هم فرق دارند و حاصل مقایسه false است، که درست است: داده‌ی متنی پشت سر شما بازنویسی نمی‌شود. نوشته‌ی یونیکد و برنامه‌نویسی راست به چپ عمیق‌تر به اینکه تحلیلگر واژگانی (Lexer) چطور با این موارد کنار می‌آید می‌پردازد.

راهبرد ۱: تولید به انگلیسی، سپس ترجمه به فارسی

مطمئن‌ترین راه امروز برای رسیدن به یک برنامه‌ی فارسی این است که بگذاریم مولد کد در جایی کار کند که قوی‌تر است، و سپس ترجمه را به ابزاری قطعی بسپاریم. salam translate fa کد سلام انگلیسی را به فارسی بازنویسی می‌کند: واژه‌های کلیدی، true، false، null و this، تابع ورودی، نام گونه‌های پایه و متدهای داخلی وکتورها، نگاشت‌ها و پرونده‌ها. هر چیز دیگری، از جمله نام‌های خود شما، توضیح‌ها و رشته‌ها، بایت به بایت دست‌نخورده می‌ماند. این برنامه‌ی انگلیسی را در نظر بگیرید:

سلام
func average(scores: Vector<int>): f64:
    if scores.len() == 0:
        ret 0.0
    end
    mut sum := 0
    each s in scores:
        sum += s
    end
    ret (sum as f64) / (scores.len() as f64)
end

func main:
    mut scores := Vector {} as Vector<int>
    defer scores.free()
    scores.push(18)
    scores.push(15)
    scores.push(20)
    println "average:", average(scores)
end
خروجیaverage: 17.666666666666668

salam translate fa avg.salam فایل avg.fa.salam را نوشت که دقیقاً همان خط را چاپ می‌کند:

سلام
// زبان: فارسی
تابع average(scores: وکتور<صحیح>): اعشار۶۴:
    اگر scores.طول() برابر 0:
        برگشت 0.0
    پایان
    ناپایا sum := 0
    هر s در scores:
        sum += s
    پایان
    برگشت (sum برگردان اعشار۶۴) / (scores.طول() برگردان اعشار۶۴)
پایان

تابع ریشه:
    ناپایا scores := وکتور {} برگردان وکتور<صحیح>
    دیرکن scores.آزادکن()
    scores.بیفزا(18)
    scores.بیفزا(15)
    scores.بیفزا(20)
    سرچاپ "average:"، average(scores)
پایان
خروجیaverage: 17.666666666666668

ساختار حالا فارسی است، با برابر به‌جای == و سرآیند زبان // زبان: فارسی، اما نام‌های average، scores و sum هنوز انگلیسی‌اند. تغییر نام آن‌ها کاری است که به یک انسان یا یک مدل نیاز دارد، و این کار بسیار کوچک‌تر و کم‌خطرتر از نوشتن کل برنامه به فارسی است. ترجمه در جهت عکس هم کار می‌کند: salam translate en روی مثال سبد خرید بالا، واژه‌های کلیدی انگلیسی را دور همان نام‌های فارسی گذاشت و نتیجه همان دو خط را چاپ کرد. نوشته‌ی ابزار salam translate گزینه‌ها و محدودیت‌ها را شرح می‌دهد.

راهبرد ۲: نوشتن مستقیم به فارسی، با مرجع زبان در دسترس مدل

وقتی مدل مستقیم به فارسی می‌نویسد، بهترین کمک مرجع زبان است. پرونده‌ی SKILL.md در مخزن سلام بخشی کامل برای سلام فارسی دارد: همه‌ی واژه‌های کلیدی با معادل انگلیسی‌شان، نام فارسی گونه‌ها، متدهای داخلی و بسته‌های کتابخانه‌ی استاندارد، راهنمای نحو فارسی، فهرستی از دام‌های ویژه‌ی فارسی و چند برنامه‌ی کامل فارسی. این پرونده برای این نوشته شده که در زمینه‌ی (context) یک مدل بارگذاری شود.

سرور MCP سلام ابزارهایی برای همین کار اضافه می‌کند: salam_keywords جدول واژه‌های کلیدی انگلیسی و فارسی را برمی‌گرداند، salam_translate برنامه را در هر دو جهت تبدیل می‌کند، salam_stdlib_symbols میانجی برنامه‌نویسی (API) یک بسته را نشان می‌دهد و salam_check خطاهایی را گزارش می‌کند که مدل می‌تواند بر اساسشان کد را اصلاح کند. نوشته‌ی زبان‌های برنامه‌نویسی در عصر هوش مصنوعی توضیح می‌دهد که این چرخه‌ی «بررسی و اصلاح» چطور کار می‌کند و چرا برای یک زبان جوان اهمیت دارد.

راهبرد ۳: تعیین رفتار با آزمون‌های فارسی

کامپایلر فقط می‌تواند بگوید برنامه خوش‌ساخت است یا نه. اینکه برنامه کار درست را انجام می‌دهد یا نه، پرسشی است که آزمون‌ها باید پاسخ دهند، و اجراکننده‌ی آزمون سلام هم فارسی می‌فهمد. دستورهای آزمون املای فارسی دارند و عددهای درونشان می‌توانند فارسی باشند. با افزودن دو خط به بالای برنامه‌ی سبد خرید، آن را به یک آزمون تبدیل می‌کنیم:

متن
// انتظار-خط: جمع کل: 390
// انتظار-کد: ۰

انتظار-خط می‌خواهد یکی از خط‌های خروجی دقیقاً همین متن باشد و انتظار-کد کد خروج برنامه را تعیین می‌کند. salam test این آزمون را با موفقیت گذراند؛ پس از تغییر جمع مورد انتظار به ۴۰۰، آزمون شکست خورد و خط مورد انتظار را کنار خروجی واقعی چاپ کرد. نوشتن رفتار مورد انتظار پیش از تولید کد، و به همان زبانی که کد نوشته می‌شود، محکم‌ترین سد در برابر برنامه‌ای است که کامپایل می‌شود و باز هم نادرست است.

جایگاه دستیار هوشمند سلام

دستیار هوشمند سلام (Salam AI)، دستیار خود پروژه، رابط کاربری فارسی و راست‌به‌چپ دارد و کد سلامی را که می‌نویسد با کامپایلر سلام بررسی می‌کند. طبیعی‌ترین جا برای درخواست کد سلام فارسی همین‌جاست، و نوشته‌ی دستیار هوشمند سلام و دستیار زبان سلام آن را همراه با دستیار رومیزی با جزئیات معرفی می‌کند. همان راهبردها آن‌جا هم برقرارند: آزمون نگه دارید، خروجی را بخوانید و هر جا قابل‌پیش‌بینی‌ترین نتیجه را می‌خواهید از ترجمه استفاده کنید.

آنچه نمی‌توانیم بگوییم

ما هیچ عددی درباره‌ی دقت هیچ مدلی در نوشتن سلام فارسی منتشر نمی‌کنیم. چنین عددهایی به مدل، دستور (prompt) و نوع کار بستگی دارند و بدون یک ارزیابی عمومی و تکرارپذیر فقط حدس خواهند بود. آنچه می‌توانیم بگوییم ساختاری است: کامپایلر کد فارسی بدساخت را با توضیح فارسی رد می‌کند، ترجمه‌ی قطعی بیشتر خطر واژه‌های کلیدی را از میان برمی‌دارد و باقی را آزمون‌ها تعیین می‌کنند.

یک پرسش کیفی هم هست که هیچ ابزاری به آن پاسخ نمی‌دهد. نام‌های فارسی خوب، یعنی نام‌هایی که طبیعی خوانده شوند و از قراردادهای پروژه پیروی کنند (کتابخانه‌ی استاندارد سلام میان کلمه‌های نام‌های فارسی فاصله می‌گذارد)، به خواننده‌ای مسلط به فارسی نیاز دارند. نام‌های تولیدشده ممکن است از نظر دستوری درست و باز هم نامأنوس باشند. در آموزش، همین بازبینی بخشی از ارزش کار است: دانشجویی که با دوره‌ی آموزش فارسی یاد می‌گیرد، می‌تواند کد تولیدشده را به زبان خودش بخواند و اصلاح کند، و این همان هدف برنامه‌نویسی به زبان مادری است.

پرسش‌های متداول درباره‌ی هوش مصنوعی و کد فارسی

آیا دستیارهای عمومی هوش مصنوعی می‌توانند به زبان سلام فارسی کد بنویسند؟

دستیارهای عمومی سلام را بسیار کم و سلام فارسی را از آن هم کمتر دیده‌اند، به همین دلیل اغلب تابع‌های داخلی انگلیسی یا نحو زبان‌های دیگر را وارد کد می‌کنند. وقتی خطاهای کامپایلر، مرجع SKILL.md یا سرور MCP در چرخه‌ی کار باشند، این اشتباه‌ها پیش از انتشار پیدا و اصلاح می‌شوند.

آیا خطاهای کامپایلر سلام به فارسی نمایش داده می‌شوند؟

بله. فایل فارسی خطاهای فارسی می‌گیرد، با همان کدهای خطای نسخه‌ی انگلیسی، و گزینه‌ی --error-lang زبان پیام‌ها را برای هر فایلی عوض می‌کند.

بهتر است کد فارسی را مستقیم تولید کنیم یا ترجمه کنیم؟

برای نتیجه‌ی قابل‌پیش‌بینی، کد سلام را به انگلیسی تولید کنید یا بنویسید، salam translate fa را اجرا کنید و سپس نام‌ها را فارسی کنید. نوشتن مستقیم به فارسی وقتی بهترین نتیجه را می‌دهد که مرجع فارسی زبان در دسترس مدل باشد و کامپایلر هر پیش‌نویس را بررسی کند.

آیا کد فارسی در زبان برنامه‌نویسی سلام کندتر از کد انگلیسی اجرا می‌شود؟

نه. هر دو املا از همان کامپایلر می‌گذرند و همان فایل اجرایی را می‌سازند؛ برنامه‌ی سبد خرید پس از ترجمه به انگلیسی دقیقاً همان خروجی را چاپ کرد.

راه پیش رو

اجرای مدل‌های هوش مصنوعی با زبان سلام: بارگذاری مدل‌های زبانی GGUF، اجرای ONNX و ساخت ابزار یادگیری ماشین بدون پایتون

کتابخانه‌ی استاندارد سلام می‌تواند مدل‌های زبانی GGUF را بخواند، مدل‌های کوچک خانواده‌ی Llama را روی پردازنده اجرا کند و گراف‌های ONNX را به کار بیندازد، همه با کد خالص سلام. در این نوشته می‌بینیم چه چیزی کار می‌کند، چه هزینه‌ای دارد و برای چه کاری ساخته نشده است.

خواندن مقاله
راه پیش رو

یک زبان برنامه‌نویسی تازه چطور زیست‌بوم متن‌باز خودش را می‌سازد: بسته‌ها، فهرست بسته‌ها، مستندات و مشارکت‌کنندگان در سلام

هر زبانی به اندازه‌ی کدهای اطرافش مفید است. در این نوشته می‌بینیم مدیر بسته، کتابخانه‌ی استاندارد، مستندات و روند مشارکت در سلام چطور ساخته شده‌اند، و با صداقت می‌گوییم که این زیست‌بوم هنوز چقدر کوچک است.

خواندن مقاله
راه پیش رو

سلام در آموزش برنامه‌نویسی: آموزش مبتدیان، علوم کامپیوتر و طراحی کامپایلر با یک زبان دوزبانه

سلام به دانش‌آموز اجازه می‌دهد با فارسی شروع کند، بی‌آنکه زبان را عوض کند به واژه‌های کلیدی انگلیسی برسد، و بعدها کامپایلری واقعی را بخواند که با همان زبان نوشته شده است. امروز چه چیزی برای معلمان آماده است و کلاس‌های درس هنوز به چه نیاز دارند.

خواندن مقاله