Tracks
/
Elm
Elm
/
Übungen
/
Fahrkarte, bitte!
Fahrkarte, bitte!

Fahrkarte, bitte!

Lernübung

Einführung

Pattern Matching

Pattern Matching ermöglicht ausdrucksstarken Code mit Verzweigungen, und mit Destrukturierung bindest du Werte elegant an Variablen.

Einfaches Pattern Matching

Mit Pattern Matching kannst du Werte an Variablen binden oder sie mit dem Platzhalter _ verwerfen, indem du die case-Anweisung verwendest.

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!"

Destrukturierung

Destrukturierung kann Werte in let-Bindungen, in Funktionsargumenten und natürlich in case-Ausdrücken binden, wann immer die Daten nur eine mögliche Form haben.

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

Destrukturierung lässt sich auch für Records verwenden oder mit dem as-Schlüsselwort.

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

Anleitung

Du gehörst zum IT-Helpdesk und möchtest das Ticketsystem effizienter machen und deiner Managerin Statistiken liefern.

Ein Ticket hat einen Status (neu, in Bearbeitung ...) und einen Ersteller (gekennzeichnet durch einen Benutzernamen und eine Mitarbeiter-ID). Es kann einem IT-Mitarbeiter zugewiesen werden und enthält einen Verlauf von Kommentaren.

Hier sind vier Aufgaben, mit denen du dein aktuelles Ticketsystem verbesserst.

1. Leere Kommentare erkennen

Leere Kommentare überladen die Oberfläche und liefern keine Information, deshalb möchtest du sie herausfiltern.

Definiere eine Hilfsfunktion emptyComment, die ein Paar aus Benutzer und Kommentar entgegennimmt und für leere Kommentare True zurückgibt.

Nutze Destrukturierung, um den Benutzer und den Kommentar direkt im Funktionsargument zu extrahieren. Ignoriere den Benutzer, da du diese Information nicht brauchst.

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

2. Die Anzahl der Kommentare des Erstellers zählen

Deine Managerin möchte Statistiken darüber haben, wie stark sich die Nutzer am Ticketprozess beteiligen. Sie bittet dich zu prüfen, wie viele Kommentare vom Ersteller des Tickets stammen.

Definiere numberOfCreatorComments, die ein Ticket entgegennimmt und die Anzahl der Kommentare zurückgibt, die der Ersteller des Tickets hinzugefügt hat.

Nutze Destrukturierung im Funktionsargument, um das Record aus dem Typ Ticket zu extrahieren und gleichzeitig die Felder, die du aus dem Record brauchst. Destrukturiere dann createdBy in einem let-Binding, damit du die relevanten Kommentare zählen kannst. Nutze List-Funktionen zum Zählen und verwende Destrukturierung im Funktionsargument einer anonymen Funktion, um das Paar aus Benutzer und Kommentar zu trennen.

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

3. Tickets erkennen, die dem Dev-Team zugewiesen sind

Manche Tickets müssen an Alice, Bob oder Charlie aus dem Dev-Team eskaliert werden. Es ist wichtig, diese im Auge zu behalten, um sicherzustellen, dass sie vorankommen.

Definiere eine Hilfsfunktion assignedToDevTeam, die prüft, ob ein Ticket einem der Mitglieder des Dev-Teams zugewiesen ist.

Nutze Destrukturierung im Funktionsargument, um sowohl das Record aus dem Typ Ticket als auch das Feld zu extrahieren, das du brauchst. Verwende dann eine einzige case-Anweisung, um zu prüfen, ob das Ticket Alice, Bob oder Charlie zugewiesen ist, wobei du mit rekursivem Pattern Matching ihre Benutzernamen extrahierst und sie mit literalem Pattern Matching abgleichst.

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

4. Tickets IT-Mitarbeitern zuweisen

Manchmal muss eine ganze Reihe von Tickets anderen IT-Mitarbeitern neu zugewiesen werden.

Definiere eine Funktion assignTicketTo, die dir dabei hilft. Die Funktion erhält zwei Argumente: einen Benutzer, dem das Ticket zugewiesen werden soll, und ein Ticket. Wenn der Status des Tickets New ist, weise es dem neuen Benutzer zu und ändere den Status zu InProgress. Bei anderen Status weise das Ticket einfach dem neuen Benutzer neu zu, außer bei Tickets mit dem Status Archived: die dürfen überhaupt nicht verändert werden.

Nutze Destrukturierung im Funktionsargument, um das Record aus dem Typ Ticket sowie das Feld zu extrahieren, das du brauchst, und verwende außerdem das Schlüsselwort as, um das ganze Record so festzuhalten, wie es ist. Verwende eine einzige case-Anweisung, um den Status per Pattern Matching abzugleichen und das passende Ticket zurückzugeben, das durch Ändern des ursprünglichen Records entsteht, den du mit dem Schlüsselwort as festgehalten hast.

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!!" ) ]
--        }
Über GitHub bearbeiten Der Link öffnet sich in einem neuen Fenster oder Tab
Elm Exercism

Bereit, mit Fahrkarte, bitte! zu starten?

Melde dich bei Exercism an, um Elm mit 28 Konzepte110 Übungen und echtem menschlichen Mentoring zu lernen und zu meistern, alles kostenlos.