پرش به محتویات

مفاهیم پایه

بیایید با حال و هوای Elm آشنا شویم! هدف آشنا شدن با مقدار و تابع است تا وقتی به مثال‌های بزرگ‌تر می‌رسیم، با اطمینان بیشتری کد Elm را بخوانید.

مقدار

کوچک‌ترین واحد ساختاری در Elm مقدار نامیده می‌شود. این واحد شامل چیزهایی مانند 42، True و "!Hello" است.

بیایید با نگاهی به اعداد شروع کنیم:

> 1 + 1
2

تمام مثال‌های این صفحه را می‌توانید در Elm REPL وارد کنید. عبارت 2 + 2 را تایپ کنید و کلید ENTER را فشار دهید. باید 4 چاپ شود. باید بتوانید با هر یک از مثال‌های این صفحه به همین روش تعامل داشته باشید!

سعی کنید چیزهایی مانند 30 * 60 * 1000 و 2 ^ 4 را تایپ کنید. باید درست مانند یک ماشین حساب کار کند! محاسبات ریاضی خوب است، اما در بیشتر برنامه‌ها کاربرد کمی دارند! کار کردن با رشته‌های متنی بسیار رایج‌تر است:

> "hello"
"hello"

> "butter" ++ "fly"
"butterfly"

سعی کنید چند رشته را با عملگر (++) کنار هم قرار دهید. این مقادیر اولیه زمانی جالب‌تر می‌شوند که شروع به نوشتن توابعی برای تبدیل آن‌ها کنیم!

یادداشت

درباره عملگرهایی مانند (+) ، (/) و (++) در مستندات ماژول Basics می‌توانید اطلاعات بیشتری کسب کنید. در یک مقطع، خواندن تمام مستندات آن بسته ارزشمند است!

تابع

یک تابع روشی برای تبدیل مقدار است. یک مقدار را می‌گیرد و مقدار دیگری تولید می‌کند.

در ادامه، یک تابع greet وجود دارد که یک نام را می‌گیرد و خوش آمد می‌گوید:

> greet name =
|   "Hello " ++ name ++ "!"
|
<function>

> greet "Alice"
"Hello Alice!"

> greet "Bob"
"Hello Bob!"

سعی کنید به شخص دیگری خوش آمد بگویید، مانند "Evan" یا "Richard".

مقدار ورودی به تابع معمولا آرگومان‌ نامیده می‌شود، بنابراین می‌توانید بگویید "greet یک تابع است که یک آرگومان می‌گیرد."

خوب، حالا که خوش آمدگویی تمام شد، تابع madlib که دو آرگومان می‌گیرد چطور نوشته می‌شود؟

> madlib animal adjective =
|   "The ostentatious " ++ animal ++ " wears " ++ adjective ++ " shorts."
|
<function>

> madlib "cat" "ergonomic"
"The ostentatious cat wears ergonomic shorts."

> madlib ("butter" ++ "fly") "metallic"
"The ostentatious butterfly wears metallic shorts."

سعی کنید دو آرگومان به تابع madlib بدهید.

توجه کنید که چگونه از پرانتزها برای گروه‌بندی "butter" ++ "fly" در مثال دوم استفاده کردیم. هر آرگومان باید یک مقدار اولیه مانند "cat" باشد یا در پرانتز قرار بگیرد!

یادداشت

افرادی که از زبان‌هایی مانند جاوااسکریپت می‌آیند ممکن است تعجب کنند که چرا فراخوانی تابع در اینجا متفاوت به نظر می‌رسد:

madlib "cat" "ergonomic"                  -- Elm
madlib("cat", "ergonomic")                // JavaScript

madlib ("butter" ++ "fly") "metallic"     -- Elm
madlib("butter" + "fly", "metallic")      // JavaScript
این سبک ممکن است در ابتدا شگفت‌انگیز باشد، اما در نهایت از پرانتزها و ویرگول‌های کمتری استفاده می‌کند. وقتی به آن عادت کنید، زبان واقعا مختصر و مفید به نظر می‌رسد!

عبارت شرطی

وقتی می‌خواهید رفتار شرطی در Elm داشته باشید، از یک عبارت شرطی استفاده می‌کنید.

بیایید یک تابع greet جدید بسازیم که به رییس جمهور آبراهام لینکلن بطور مناسب احترام بگذارد:

> greet name =
|   if name == "Abraham Lincoln" then
|     "Greetings Mr. President!"
|   else
|     "Hey!"
|
<function>

> greet "Tom"
"Hey!"

> greet "Abraham Lincoln"
"Greetings Mr. President!"

احتمالا موارد دیگری نیز وجود دارد که باید پوشش داده شوند، اما فعلا همین کافی است!

لیست

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

لیست‌ها می‌توانند مقادیر زیادی را نگه دارند. این مقادیر باید همه از یک نوع باشند. در ادامه چند مثال وجود دارد که از توابع ماژول List استفاده می‌کنند:

> names =
|   [ "Alice", "Bob", "Chuck" ]
|
["Alice","Bob","Chuck"]

> List.isEmpty names
False

> List.length names
3

> List.reverse names
["Chuck","Bob","Alice"]

> numbers =
|  [4,3,2,1]
|
[4,3,2,1]

> List.sort numbers
[1,2,3,4]

> increment n =
|  n + 1
|
<function>

> List.map increment numbers
[5,4,3,2]

سعی کنید لیست خود را بسازید و از توابعی مانند List.length استفاده کنید. به یاد داشته باشید، تمام عناصر لیست باید از یک نوع باشند!

تاپِل

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

> isGoodName name =
|   if String.length name <= 20 then
|      (True, "name accepted!")
|    else
|      (False, "name was too long; please limit it to 20 characters")
|
<function>

> isGoodName "Tom"
(True, "name accepted!")

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

رکورد

یک رکورد می‌تواند مقادیر زیادی را نگه دارد و هر مقدار با یک نام مرتبط است. در ادامه، یک رکورد وجود دارد که اقتصاددان بریتانیایی جان آ. هابسون را ذخیره می‌کند:

> john =
|   { first = "John"
|   , last = "Hobson"
|   , age = 81
|   }
{ age = 81, first = "John", last = "Hobson" }

> john.last
"Hobson"

یک رکورد با سه فیلد تعریف کردیم که اطلاعاتی درباره نام، نام خانوادگی و سن جان را شامل می‌شود. سعی کنید به فیلدهای دیگر مانند john.age دسترسی یابید.

همچنین می‌توانید به فیلدهای رکورد با استفاده از یک "تابع دسترسی به فیلد" مانند نمونه زیر دسترسی پیدا کنید:

> john = { first = "John", last = "Hobson", age = 81 }
{ age = 81, first = "John", last = "Hobson" }

> .last john
"Hobson"

> List.map .last [john,john,john]
["Hobson","Hobson","Hobson"]

معمولا پیش می‌آید که مقادیر را در یک رکورد بروزرسانی کنید:

> john = { first = "John", last = "Hobson", age = 81 }
{ age = 81, first = "John", last = "Hobson" }

> { john | last = "Adams" }
{ age = 81, first = "John", last = "Adams" }

> { john | age = 22 }
{ age = 22, first = "John", last = "Hobson" }

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

توجه کنید که وقتی برخی از فیلدهای john را بروزرسانی می‌کنیم، یک رکورد کاملا جدید ایجاد می‌شود. این کار، رکورد قبلی را بازنویسی نمی‌کند. Elm این کار را با به اشتراک‌گذاری حداکثر محتوا بهینه‌سازی می‌کند. اگر یکی از ده فیلد را بروزرسانی کنید، رکورد جدید نه مقدار بدون تغییر را به اشتراک می‌گذارد.

بنابراین یک تابع برای بروزرسانی سن ممکن است به این شکل باشد:

> john = { first = "John", last = "Hobson", age = 81 }
{ age = 81, first = "John", last = "Hobson" }

> celebrateBirthday person =
|   { person | age = person.age + 1 }
|
<function>

> celebrateBirthday john
{ age = 82, first = "John", last = "Hobson" }

بروزرسانی فیلدهای رکورد به این شکل بسیار رایج است، بنابراین در بخش بعدی بیشتر با آن آشنا خواهیم شد!


یادداشت مترجم

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

> elm repl