تتيح مطابقة الأنماط كتابة كود تفريعي معبّر، ويوفّر التفكيك ربطًا أنيقًا للقيم بالمتغيرات.
تستطيع مطابقة الأنماط ربط القيم بالمتغيرات، أو تجاهلها باستخدام المحرف البديل _، وذلك بالاستعانة بجملة 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
أنت جزء من مكتب مساعدة تقنية المعلومات، وتريد تحسين نظام التذاكر ليكون أكثر كفاءة وتوفير إحصاءات لمديرك.
للتذكرة حالة (جديد، قيد التنفيذ...)، ومنشئ (يُعرَّف باسم مستخدم ومعرّف موظف)، ويمكن إسنادها إلى موظف في تقنية المعلومات، وتحتوي على سجل من التعليقات.
إليك أربع مهام ستحسّن نظام التذاكر الحالي.
التعليقات الفارغة تزدحم بها الواجهة ولا تقدّم أي معلومات، لذلك تريد تصفيتها.
عرّف دالة مساعدة emptyComment تأخذ زوجًا من المستخدم والتعليق وتُرجع True للتعليقات الفارغة.
استخدم التفكيك لاستخراج المستخدم والتعليق مباشرةً في وسيط الدالة. تجاهل المستخدم لأنك لا تحتاج هذه المعلومة.
emptyComment ( User "Alice", "" )
-- => True
مديرك يريد الحصول على إحصاءات عن مشاركة المستخدمين في عملية التذاكر. وهي تطلب منك التحقق من عدد التعليقات التي يضيفها منشئ التذكرة.
عرّف numberOfCreatorComments التي تأخذ تذكرة وتُرجع عدد التعليقات التي أضافها منشئ التذكرة.
استخدم التفكيك في وسيط الدالة لاستخراج السجل من نوع Ticket، في الوقت نفسه الذي تستخرج فيه الحقول التي تحتاجها من السجل.
ثم فكّك createdBy في ارتباط let حتى تتمكن من عدّ التعليقات ذات الصلة.
استخدم دوال List لإجراء العدّ، واستخدم التفكيك في وسيط الدالة لدالة مجهولة لفصل زوج المستخدم والتعليق.
numberOfCreatorComments
numberOfCreatorComments
(Ticket
{ status = Closed
, createdBy = ( User "Chiaki", 1 )
, assignedTo = Nothing
, comments = [ ( User "Chiaki", "Never mind, fixed it." ) ]
}
)
-- => 1
بعض التذاكر يجب تصعيدها إلى 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
أحيانًا يلزم إعادة إسناد مجموعة من التذاكر إلى موظفي تقنية معلومات آخرين.
عرّف دالة 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!!" ) ]
-- }
سجّل في Exercism لتتعلّم وتتقن Elm عبر 28 مفهومًا110 تمارين، وإرشاد بشري حقيقي، وكل ذلك مجانًا.