مسیرها
/
Elm
Elm
/
تمرین‌ها
/
بلیت، لطفاً!
بلیت، لطفاً!

بلیت، لطفاً!

تمرین یادگیری

مقدمه

تطبیق الگو

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

تطبیق الگوی ساده

تطبیق الگو می‌تواند مقادیر را به متغیرها متصل کند، یا با «جانگهدار» _ آن‌ها را نادیده بگیرد؛ این کار با استفاده از دستور case انجام می‌شود.

type Entity = Alien | Stranger (Maybe String) | Friend { name: String }

hello : Entity -> String
hello entity =
    case entity of
        -- Custom type variant
        Alien -> "Hello, you are not from around here are you?"
        -- Binding to a litteral value nested in Stranger
        Stranger (Just nametag) -> "Hello, erm... " ++ nametag ++ "."
        -- Discarding Friend's data
        Friend _ -> "Hi!"
        -- All other cases
        _ -> "Hello stranger!"

ساختارشکنی

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

pairSum : ( Int, Int ) -> Int
pairSum pair =
    -- Destructuring of a pair in a 'let' binding
    let ( x, y ) = pair
    in x + y

-- Destructuring in the function argument
pairSum : ( Int, Int ) -> Int
pairSum ( x, y ) = x + y

-- Custom type containing a single variant
type Container = Box String

-- Destructuring in the function argument
unbox : Container -> String
unbox (Box str) = str

-- Destructuring combined with pattern matching
unboxMaybe : Maybe Container -> Maybe String
unboxMaybe maybeContainer =
    case maybeContainer of
        Nothing -> Nothing
        Just (Box "42") -> Just "The answer to the universe!"
        Just (Box str) -> Just str

از ساختارشکنی می‌توان برای رکوردها هم استفاده کرد، یا همراه با کلیدواژه‌ی as.

type alias Circle =
    { radius : Float
    , center : ( Float, Float )
    }

perimeter : Circle -> Float
perimeter { radius } =
    2 * pi * radius

left : Circle -> Float
left { radius, center } =
    -- the pair center cannot be pattern matched directly in the function argument
    -- so we do it in a 'let' statement
    let ( x, _ ) = center
    in x - radius

-- using the 'as' keyword to bind both the fields and the whole record
smaller : Float -> Circle -> Circle
smaller reduction ({ radius } as circle) =
    if reduction < radius then
        { circle | radius = radius - reduction }
    else
        circle

دستورالعمل‌ها

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

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

چهار کار زیر سیستم تیکت کنونی‌تان را بهتر می‌کند.

1. تشخیص نظرهای خالی

نظرهای خالی رابط کاربری را شلوغ می‌کنند و هیچ اطلاعاتی به همراه ندارند؛ می‌خواهید آن‌ها را حذف کنید.

یک تابع کمکی به اسم emptyComment تعریف کنید که یک جفت کاربر/نظر می‌گیرد و برای نظرهای خالی True برمی‌گرداند.

برای بیرون کشیدن کاربر و نظر، مستقیماً از «ساختارشکنی» در آرگومان تابع استفاده کنید. چون به آن اطلاعات نیازی ندارید، کاربر را نادیده بگیرید.

emptyComment ( User "Alice", "" )
-- => True

2. شمردن تعداد نظرهای سازنده

مدیرتان می‌خواهد درباره‌ی میزان مشارکت کاربران در فرایند تیکت آمار داشته باشد. او از شما می‌خواهد بررسی کنید که سازنده‌ی تیکت چند نظر ثبت کرده است.

تابعی به اسم numberOfCreatorComments تعریف کنید که یک تیکت می‌گیرد و تعداد نظرهایی را که سازنده‌ی تیکت اضافه کرده برمی‌گرداند.

با ساختارشکنی در آرگومان تابع، رکورد را از نوع Ticket بیرون بکشید و همزمان فیلدهایی را که از رکورد لازم دارید نیز استخراج کنید. سپس createdBy را در یک اتصال let ساختارشکنی کنید تا بتوانید نظرهای مرتبط را بشمارید. برای شمردن از توابع List استفاده کنید و برای جدا کردن جفت کاربر/نظر، در آرگومان تابع یک تابع بینام ساختارشکنی به کار ببرید.

numberOfCreatorComments
numberOfCreatorComments
    (Ticket
        { status = Closed
        , createdBy = ( User "Chiaki", 1 )
        , assignedTo = Nothing
        , comments = [ ( User "Chiaki", "Never mind, fixed it." ) ]
        }
    )
-- => 1

3. تشخیص تیکت‌های واگذارشده به تیم توسعه

بعضی تیکت‌ها باید به Alice، Bob یا Charlie از تیم توسعه ارجاع داده شوند. مهم است که حواستان به آن‌ها باشد تا مطمئن شوید در حال پیشرفت هستند.

یک تابع کمکی به اسم assignedToDevTeam تعریف کنید که بررسی می‌کند آیا تیکت به یکی از اعضای تیم توسعه واگذار شده است یا نه.

با ساختارشکنی در آرگومان تابع، رکورد را از نوع Ticket و همچنین فیلد موردنیازتان بیرون بکشید. سپس با یک دستور case بررسی کنید که تیکت به Alice، Bob یا Charlie واگذار شده است یا نه؛ برای بیرون کشیدن اسم‌های کاربری آن‌ها از تطبیق الگوی بازگشتی و برای مطابقت دادنشان از تطبیق الگوی تحت‌اللفظی استفاده کنید.

assignedToDevTeam
    (Ticket
        { status = InProgress
        , createdBy = ( User "Bill", 2 )
        , assignedTo = Just (User "Alice")
        , comments = [ ( User "Bill", "What's an 'undefined'?" ) ]
        }
    )
-- => True

4. واگذار کردن تیکت‌ها به کارمندان فناوری اطلاعات

گاهی لازم است شماری از تیکت‌ها به کارمندان دیگری از فناوری اطلاعات دوباره واگذار شوند.

برای این کار تابعی به اسم assignTicketTo تعریف کنید. این تابع دو آرگومان می‌گیرد: کاربری که باید تیکت به او واگذار شود و یک تیکت. اگر وضعیت تیکت New باشد، آن را به کاربر جدید واگذار کنید و وضعیتش را به InProgress تغییر دهید. برای بقیه‌ی وضعیت‌ها، تیکت را فقط به کاربران جدید دوباره واگذار کنید؛ به‌جز تیکت‌هایی با وضعیت Archived که نباید اصلاً تغییری در آن‌ها داده شود.

با ساختارشکنی در آرگومان تابع، رکورد را از نوع Ticket و همچنین فیلد موردنیازتان بیرون بکشید و از کلیدواژه‌ی as هم استفاده کنید تا کل رکورد را همان‌طور که هست نگه دارید. با یک دستور case وضعیت را تطبیق الگو کنید و تیکت مناسب را برگردانید؛ تیکتی که از تغییر دادن رکورد اصلی نگه‌داشته‌شده با کلیدواژه‌ی as ساخته می‌شود.

assignTicketTo (User "Danny")
    (Ticket
        { status = New
        , createdBy = ( User "Jesse", 3 )
        , assignedTo = Just (User "Alice")
        , comments = [ ( User "Jesse", "I've been waiting for 6 months!!" ) ]
        }
    )
-- => Ticket
--        { status = InProgress
--        , createdBy = ( User "Jesse", 3 )
--        , assignedTo = Just (User "Danny")
--        , comments = [ ( User "Jesse", "I've been waiting for 6 months!!" ) ]
--        }
ویرایش از طریق GitHub این لینک در پنجره یا زبانه‌ی جدیدی باز می‌شود
Elm Exercism

آماده‌اید بلیت، لطفاً! را شروع کنید؟

در Exercism ثبت‌نام کنید تا Elm را همراه با 28 مفهوم110 تمرین و مربی‌گری انسانی واقعی یاد بگیرید و در آن استاد شوید، همه‌ی این‌ها رایگان.