سینتکس قندی

[جایگزین=یک نمونه Syntactic sugar در تعریف متغیر در زبان go. در Syntactic sugar کامپایلر زبان گو، تایپ متغیر را استنتاج می‌کند|بندانگشتی|378x378px|یک نمونه سینتکس قندی در تعریف [متغیر (علوم رایانه)|متغیر در زبان گو. وقتی از این سینتکس قندی استفاده می‌شود، کامپایلر زبان گو، تایپ متغیر را استنتاج می‌کند.]]
در علوم کامپیوتر و طراحی کامپایلر، **سینتکس قندی**  نوعی سینتکس یا نحو خاص است که به یک زبان برنامه‌نویسی اضافه می‌شود تا نوشتن کد و گاهی فهمیدن آن را برای دیگران راحت‌تر و سریع‌تر کند. این نحو اضافه شده با ساختاری واضح تر و مختصر، در کنار نحو اصلی، باعث به اصطلاح «شیرین تر» شدن آن زبان برنامه‌نویسی برای انسان می‌شود. معمولا سینتکس قندی روشی مختصرتر برای بیان یک دستور رایج و نسبتاً طولانی‌تر است. در واقع برنامه‌نویس می‌تواند هم سینتکس قندی و کوتاه‌تر و هم نحو اصلی و طولانی‌تر را استفاده کند، اما معمولاً از شکل کوتاه‌تر استفاده می‌شود که نوشتن و خواندن و فهمیدن آن برای همه سریع تر و راحت تر است.

مثلاً در خیلی از زبان‌های برنامه‌نویسی، روش‌های متفاوتی برای بررسی و ایجاد و تغییر عناصر یک آرایه، ارائه می‌شود که اگر بخواهیم کلی تر نگاه کنیم، واکشی مقدار یک عنصر می‌تواند یک تابع با دو آرگومان ورودی باشد: یکی خود آرایه و دیگری اندیس عنصر مدنظر در همان آرایه که می‌تواند به صورت `get_array(Array, vector(i,j))` بیان شود. ولی بسیاری از زبان‌ها در کنار این، نحو دیگری مانند `Array[i,j]` هم ارائه می‌کنند که نمونه ای از سینتکس قندی است.

در عمل هم می‌توان سینتکس قندی را کاملاً از زبان حذف کرد و این کار هیچ تأثیری در عملکرد و قدرت زبان نمی‌گذارد، فقط حذف شدن سینتکس‌های قندی باعث طولانی‌تر شدن و ناخواناتر شدن کدها می‌شود، ولی توانایی‌ها، همان است.

بیشتر کامپایلرها و مفسرها، ساختار سینتکس‌های قندی را قبل از پردازش، به معادل‌های اصلی زبان تبدیل می‌کنند. به این فرایند گاهی اوقات به آن «قند زدایی» یا «desugaring» هم می‌گویند.

## نمونه ها
به عنوان مثال در خیلی از زبان‌های برنامه‌نویسی به این صورت داریم:
```c#
int i = 2
i = i + 3

// Sugar
i += 3
i -= 3

//Sugar
i++ // i += 1    --===> i = i + 1
i-- // i -= 1    --===> i = i - 1
```
نمونه بالا بسیار رایج است و می‌شود آن را در خیلی از زبان های برنامه نویسی دید

#### [[سی شارپ]] / [[C++|سی پلاس پلاس]]
در زبان سی شارپ، استنتاج نوع (Type Inference) از طریق کلمه کلیدی `var` هم نوعی سینتکس قندی است :
```c#
int y = 4 // Base Syntax
var x = 8 // Syntactic Sugar
```
همین فرایند در ++C با استفاده از کلمه کلیدی `auto` یک نمونه سینتکس قندی است :
```c++
int x = 16 // Base syntax
auto y = 8 // Syntactic Sugar
```


#### [[جاوااسکریپت|جاوا اسکریپت]] / [[تایپ‌اسکریپت|تایپ اسکریپت]] ( خانواده [[اکما اسکریپت|اِکما اسکریپت]])
به عنوان مثال در جاوا اسکریپت تعرف یک شئ از طریق `class` که در ES6 اضافه شده است، به شکل زیر یک سینتکس قندی است:
```javascript
class ClassA {
  constructor(foo, bar) {
    this.Foo = foo
    this.Bar = bar
  }
}

 const bux = new ClassA("Hello", "World")
 
// bux.Foo is "Hello"
// bux.Bar is "World"
```
نمونه پایین حالت واقعی همین مثال بالاست که از ES5 به قبل استفاده می‌شد : 
```javascript
const ClassA = function (foo, bar) {
this.Foo = Foo;
this.Bar = bar;
}
const bux = new ClassA("Hello", "World")
 
// bux.Foo is "Hello"
// bux.Bar is "World"
```
جاوا اسکریپت در واقع ارثبری را در میان اشیاء از طریق پروتوتایپ‌ها انجام می‌دهند . `constructor` تعریف شده در هر دو مثال، پروتوتایپ شئ تولید شده خواهد بود.

#### [[پایتون (زبان برنامه‌نویسی)|پایتون]]
در پایتون، دکوراتورها یک سینتکس قندی هستند. در واقع حالت زیر حالت واقعی سینتکس زبان است:
```python3
# pre-decorators
def Y():
    pass
Y = X(Y)
```
که سینتکس قندی آن به این صورت است : 
```python3
@X
def Y():
    pass
```

#### [[گو (زبان برنامه‌نویسی)]]
دستور زیر در زبان گو، نوعی سینتکس قندی است : 
```go
var m map[string]int = map[string]int{} //Base syntax
m := map[string]int{} //Syntactic sugar
```
یا مثال دیگر آن کلمه کلیدی `any` است : 
```golang
func main() {
	var a interface{} // any
	var b any         // interface{}

	a = "Hello, world"
	b = a

	fmt.Println(a == b) // true
}
```
در این مثال میبینید که `any` همان `{}interface` است (در Playground ببینید) و کامپایلر مشکلی ندارد نوع `any` با `{}interface` مقایسه شود یا مقدار دیگری در این یکی قرار گیرد. در ابتدا هم `{}interface` در سینتکس وجود داشت اما بعد کلمه کلیدی `any` را به عنوان یک alias برای `{}interface` به زبان گو اضافه کردند. مفهوم `{}interface` از پیچیده ترین مفاهیم سیستم تایپ دهی در گولنگ است. علت اینکه {}interface هر نوع داده ای را در خود جا می دهد، روش پیاده سازی آن است. هر اینترفیس در زبان گو از دو نشان گر به دو مجموعه تشکیل شده است. یکی از این نشان گر ها، اشاره به محتوای بین دو `{` `}` دارد. نشانگر دیگر اشاره به محتوایی که بعدا در `interface` قرار میگیرد. تایپ سیستم باید بین آن چیز هایی که در زمان اجرا در `interface` قرار میگیرند، محتوای داخل `{` `}` را پیدا کند. اگر پیدا کرد، اجازه میدهد که داده ها در آن متغیر ذخیره شوند. وگرنه برنامه را میبندد. اگر محتوایی بین `{` و `}` قرارندهید، هر داده ای در متغیر ذخیره می شود و اینگونه تایپ `any` به تایپ سیستم go راه می یابد. 

بطور ویژه هرگونه استنتاج نوع در زبان های برنامه نویسی مثل سی شارپ، سی پلاس پلاس، تایپ اسکریپت، پایتون و... یک سینتکس قندی است.

همان‌طور که گفته شد، سینتکس قندی را می‌توان حذف کرد و هیچ تأثیری در کارایی زبان ندارد فقط کد را خواناتر و تمیزتر می‌کند.

## اصطلاحات مربوط
### سینتکس شور
این استعاره با ابداع اصطلاح *سینتکس شور* معروف شده است، که شاره آن به سینتکسی است که باعث سخت‌تر شدن کار و بدتر نوشته شدن کد است.

مثلاً در سی شارپ  برای جلوگیری از مشکلاتی که نحوه پیاده سازی دستور switch وجود دارد، برنامه‌نویس ملزم است که از عبارت `break` (یا عبارت‌های `[[goto]]` ،`return` یا `throw`) در انتهای هر `case` استفاده کند. در زبان های سطح پایین تری مثل  C یا C++ فلسفه وجودیا ین دستور این است که اگر داده A باید با داده B و C و... مقایسه شود، بجای اینکه هر بار خود A را در کنار B و C و... در رجیستر پردازنده قراردهیم، یک بار A را در رجیستر بگذاریم و فقط B و C و... را در یه رجیستر قرار دهیم و مقایسه کنیم. باگ پیاده سازی این ماجرا این است که وقتی در یکی از `case` ها (فرضا این `case` در خط n قرار دارد) به برابری میرسیدیم، دستور کامپایر این بود که دیگر شرطی بررسی نشود، A از رجیستر خارج و کد ها از همان خط n به بعد اجرا شوند. وقتی محدوده `case` ما به پایان می رسید، کامپایلر متوفق نمیشد چون شرطی بررسی نمیشد و قرار بود کد ها از خط n به بعد اجرا شوند و به همین ترتیب ممکن بود کد های `case` های دیگر نیز اجرا شوند. به همین علت برنامه نویس ها مجبور بودند در انتهای هر `case` یک دستور `break` یا `goto` یا `return` و... که کار بلوک را تمام میکنند را قرار میدادند تا بقیه کد ها ناخواسته اجرا نشوند. اما در زبان سطح بالاتری مانند سی شارپ که اصلا با پردازنده ارتباط چنین مستقیمی ندارد می شد کامپایلر را به گونه ای طراحی کرد که دستور `break` در انتهای هر `case` لازم نباشد. ایراد اینجاست که سی شارپ به عنوان یه ویژگی این را ارائه نکرده است. اگر شما `break` در انتهای هر `case` قرار ندهید، کامپایلر به شما ارور سینتکس میدهد که یعنی گذاشتن آن `break` آنجا اجباریست. این یک سینتکس شور است. 4 کاراکتر اضافه به کد های شما افزوده می شود در حالی که لازم نبوده اند و کد های شما شلوغ تر می شوند.  

## منابع
* 

* A Beginner’s Guide to JavaScript’s Prototype ,Tyler McGinnis
* MDN Webdocs, Object.prototype.constructor
* Python is (mostly) made of syntactic sugar, Jake Edge
* Robert Griesemer, Golang Official Blog, Everything You Always Wanted to Know About Type Inference - And a Little Bit More

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