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

نوع داده سفارشی

یادداشت

نوع داده سفارشی قبلا به عنوان "نوع داده ترکیبی" در Elm شناخته می‌شد. سایر زبان‌های برنامه‌نویسی، از نام‌هایی مانند Tagged Union و ADT استفاده می‌کنند.

تا به حال انواع داده Bool، Int و String را دیده‌ایم. اما چگونه می‌توانیم نوع داده خودمان را تعریف کنیم؟

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

می‌توانیم این وضعیت را با تعریف یک نوع داده UserStatus توصیف و تمام حالت‌های ممکن را فهرست کنیم:

type UserStatus = Regular | Visitor

نوع داده UserStatus دارای دو حالت است. هر کاربری می‌تواند Regular یا Visitor باشد. بنابراین می‌توانیم یک کاربر را به صورت یک رکورد به این شکل نمایش دهیم:

type alias User =
  { name : String
  , status : UserStatus
  }

type UserStatus
  = Regular
  | Visitor

thomas = { name = "Thomas", status = Regular }
kate95 = { name = "kate95", status = Visitor }

اکنون می‌توانیم پیگیری کنیم آیا کاربری Regular با یک حساب کاربری یا کاربری Visitor که فقط بازدیدکننده است، وجود دارد یا خیر. این کار خیلی سخت نیست، اما می‌توانیم آن را ساده‌تر کنیم!

بجای ایجاد نام مستعار و نوع داده سفارشی، می‌توانیم همه این‌ها را با یک نوع داده سفارشی واحد نمایش دهیم. حالت‌های Regular و Visitor هر کدام داده مربوط به خود را دارند. در این مورد، داده مرتبط یک مقدار String است:

type User
  = Regular String
  | Visitor String

thomas = Regular "Thomas"
kate95 = Visitor "kate95"

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

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

> type User
| = Regular String Int
| | Visitor String
|

> Regular
<function> : String -> Int -> User

> Visitor
<function> : String -> User

> Regular "Thomas" 44
Regular "Thomas" 44 : User

> Visitor "kate95"
Visitor "kate95" : User

سعی کنید یک بازدیدکننده Regular با نام و سن تعریف کنید.

فقط سن را اضافه کردیم، اما حالت‌های یک نوع داده می‌توانند بطور قابل توجهی متفاوت باشند. برای نمونه، شاید بخواهیم موقعیت مکانی را برای کاربران Regular اضافه کنیم تا بتوانیم اتاق‌های چت منطقه‌ای را پیشنهاد دهیم. داده‌های مرتبط بیشتری اضافه کنید! یا شاید بخواهیم کاربران ناشناس داشته باشیم. یک حالت سوم به نام Anonymous اضافه کنید. نتیجه به این صورت می‌شود:

type User
  = Regular String Int Location
  | Visitor String
  | Anonymous

هیچ مشکلی نیست! حالا بیایید چند کاربرد دیگر را ببینیم.

پیام‌ها

در فصل معماری Elm، چند نمونه از تعریف نوع داده Msg را دیدیم. این نوع داده در Elm بسیار رایج است. در اتاق چت، ممکن است نوع داده Msg را به این شکل تعریف کنیم:

type Msg
  = PressedEnter
  | ChangedDraft String
  | ReceivedMessage { user : User, message : String }
  | ClickedExit

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

مدل‌سازی

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

type Profile
  = Loading
  | Failure
  | Success { name : String, description : String }

بنابراین، می‌توانید از حالت Loading شروع کنید و بسته به آنچه اتفاق می‌افتد، به حالت Failure یا Success منتقل شوید. این کار نوشتن یک تابع view را که همیشه چیزی معقول هنگام بارگیری داده نمایش می‌دهد، بسیار ساده می‌کند.

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

یادداشت

نوع داده سفارشی مهم‌ترین ویژگی Elm است. این مفهوم لایه‌های مختلفی دارد، به ویژه زمانی که به مدل‌سازی سناریوهای دقیق عادت کنید. سعی کردم برخی از این لایه‌ها را در بخش‌های نوع داده در مجموعه و نوع داده در حافظه از فصل ضمیمه به اشتراک بگذارم. امیدوارم مفید واقع شود!