در برخی لهجههای انگلیسی، وقتی «two for» را تند میگویید، شبیه «two fer» به گوش میرسد. «two-for-one» یعنی اگر یکی بخرید، یکی دیگر را هم رایگان میگیرید. پس عبارت «two-fer» اغلب به پیشنهاد دو به قیمت یک اشاره دارد.
یک قنادی را تصور کنید که برای تعطیلات پیشنهادی دارد: میتوانید دو شیرینی را به قیمت یکی بخرید («two-fer one!»). شما این پیشنهاد را میپذیرید و (بسیار سخاوتمندانه) تصمیم میگیرید شیرینی اضافه را به کس دیگری در صف بدهید.
وظیفهی شما این است که مشخص کنید هنگام بخشیدن کوکی اضافه چه میگویید.
اگر اسم آن شخص را بدانید (مثلاً اسمش Do-yun باشد)، میگویید:
One for Do-yun, one for me.
اگر اسم آن شخص را ندانید، بهجایش you میگویید.
One for you, one for me.
چند مثال:
| اسم | گفتوگو |
|---|---|
| Alice | One for Alice, one for me. |
| Bohdan | One for Bohdan, one for me. |
| One for you, one for me. | |
| Zaphod | One for Zaphod, one for me. |
Odin از آرگومانهای پیشفرض پشتیبانی میکند. آرگومانهای پیشفرض قابلیت مفیدی است که اجازه میدهد یک رویه با مجموعههای متفاوتی از پارامترها فراخوانی شود، برای مواردی که به APIهای مرتبط اما متفاوت نیاز دارید.
بدون آرگومانهای پیشفرض، ممکن است تعداد رویههای لازم برای API شما بهشدت زیاد شود. زبانهایی که از آرگومانهای پیشفرض پشتیبانی نمیکنند، مثل Java، برای رسیدن به همان نتیجه به سربارگذاری متد تکیه میکنند (با کد بیشتر) یا باید رویههایی با مجموعهی بزرگی از آرگومانها ارائه دهند.
بیایید مثال یک رویهی greeting را در نظر بگیریم که در آن میخواهیم بتوانیم زبان را مشخص کنیم، اینکه اسم با حروف بزرگ نوشته شود یا نه، و اینکه آیا باید علامت تعجبی در پایان سلام قرار بگیرد یا نه.
پس از کمی بررسی، متوجه شدیم که بزرگترین گروه کاربران زبان انگلیسی را مشخص میکنند، اسم را با حروف بزرگ نمینویسند و علامت تعجبی در پایان نمیخواهند؛ و دومین گروه بزرگ، علامت تعجب را به پایان سلام اضافه میکنند.
میتوانستیم یک رویهی واحد با همهی آرگومانها بسازیم:
greeting :: proc(name: string, language: Language, do_uppercase: bool, add_exclamation: bool) {
...
}
این کار همهی کاربران را مجبور میکرد مستندات همهی آرگومانها را بخوانند و همیشه برای آنها مقدار بدهند.
بدون آرگومانهای پیشفرض، میتوانستیم چندین رویه با مجموعههای متفاوتی از پارامترها هم تعریف کنیم:
greeting_common :: proc(name: string) {...}
greeting_with_exclamation :: proc(name: string) {...}
greeting_general :: proc(name: string, language: Language, do_uppercase: bool, add_exclamation: bool) {...}
// Odin supports overloading but it has to be explicitly defined
greeting :: proc {
greeting_common,
greeting_with_exclamation,
greeting_general,
}
اگر زبان شما، مثل Odin، از آرگومانهای پیشفرض پشتیبانی میکند، میتوانید فقط برای کماستفادهترین آرگومانها مقادیر پیشفرض مناسبی تعیین کنید. فراخوانیکنندهها میتوانند آرگومانهای پیشفرض را نادیده بگیرند، که باعث میشود رویه از پیشفرضهای دادهشده استفاده کند، یا آنها را بازنویسی کنند.
greeting :: proc(name: string, language: Language = Language.English, do_uppercase : bool = false, add_exclamation: bool = false) {...}
// Note: because Odin supports type inference, we can simplify the interface.
greeting :: proc(name: string, language:= Language.English, do_uppercase := false, add_exclamation:= false) {...}
میتوان رویه را با همهی آرگومانهای پیشفرض فراخوانی کرد:
greeting("John Doe")
آرگومانهایی که برای فراخوانیکننده مهم هستند را میتوان بازنویسی کرد:
greeting("John Doe", Language.Spanish)
اگر آرگومانهایی که لازم دارید به ترتیب موقعیت خود قرار دارند، مثل مثال بالا، نیازی نیست آنها را مثل مثال بالا نامگذاری کنید؛ اما اگر لازم است بعضیها را نادیده بگیرید، از اولین آرگومانی که نادیده گرفتید به بعد باید آرگومانها را نامگذاری کنید.
greeting("John Doe", add_exclamation=true)
در این تمرین رویهای را پیادهسازی میکنید که قرار است رشتهای را که برمیگرداند تخصیص دهد. آزادسازی این رشته بر عهدهی فراخوانیکنندهی رویه است.
// The procedure will be called like that:
str := two_fer("Alice")
// ...
// and eventually the caller will delete the string
delete(str)
ممکن است مستندات رسمی Odin دربارهی آرگومانهای پیشفرض و آرگومانهای نامدار هم برایتان جالب باشد.