يمكن لك عش "سلبيات ضعف" مباراة نمط؟
-
05-07-2019 - |
سؤال
وأريد أن تعزيز نمط لمطابقة أرقام فقط التي تمر وظيفة التحقق من صحة إضافية.
let (|IsValid|_|) n = ...
let (|Nil|One|Two|) (l : int list) =
match l with
| a :: b :: t -> Two(a + b)
| a :: t -> One(a)
| _ -> Nil
وهذه القضية 'واحد' من السهل:
| IsValid(a) :: t -> One(a)
وهذه القضية "اثنان" ليست واضحة بالنسبة لي. انها تحتاج للتحقق من مجموع الأرقام. يمكنني أن أفعل هذا دون استخدام عند الحرس؟
...
وتحرير: I يمكن استخدام عندما الحرس (مع وظيفة isValid العائدين منطقي) مثل هذا:
| a :: b :: t when isValid a + b -> Two(a + b)
وهذا هو أقل أناقة من مجرد مطابقة نمط. الأسوأ من ذلك، يتم تطبيق ب + مرتين.
لاحظ أيضا وهذا هو نسخة مبسطة من قانون بلدي الفعلي (أنا لا أسعى لمباراة ببساطة ضد أطوال مختلفة من القائمة على سبيل المثال) - السؤال هو حول مطابقة متداخلة على نمط سلبيات مزدوج.
المحلول
وبلدي الحل: إضافة "المساعد" recogniser مع قيمة إرجاع مصممة لاستخدامها في نمط الأم:
let (|MatchTwo|_|) = function
| a :: b :: t -> Some(a + b :: t)
| _ -> None
واستخدامه مثل ذلك:
let (|Nil|One|Two|) (l : int list) =
match l with
| MatchTwo(IsValid(a) :: t) -> Two(a)
| IsValid(a) :: t -> One(a)
| _ -> Nil
نصائح أخرى
وعند القيام:
| a :: b :: t -> ...
وأنت ليس بالضرورة مطابقة العنصرين في القائمة. فمن الأفضل لاستخدام []
بدلا من t
لتتناسب مع عنصرين بالضبط --t
يمكن أن تكون قائمة أكثر العناصر.
| a :: b :: [] -> Two (a+b)
وهذا سيضمن أن كنت مطابقة اثنين وعنصرين فقط --error فحص مجانا! أقترح القيام بذلك حتى ولو كنت تتوقع وظيفة لقبول سوى قائمة من 0 أو 1 أو 2 العناصر. لذا،
تحرير: م>
let (|MatchTwo|_|) = function
| a :: b :: t -> Some(a + b :: t)
| _ -> None
let (|Nil|One|Two|) (l : int list) = match l with
| MatchTwo(IsValid(a) :: t) -> Two(a)
| IsValid(a) :: t -> One(a)
| _ -> Nil
نعم، استخدم when
. هذه فوضى. نمط مطابقة ليست سوى ذلك، وتطبيق وظائف في المباراة حقا لا معنى له. ولكن تأخذ في الاعتبار ما ذكرته قبل. وبناء على المثال الخاص بك:
match l with
| a :: b :: t when isValid (a+b) -> Two (a+b)
| a :: t when isValid (a) -> One a
| _ -> Nil
والنمط الثاني سوف تتطابق قوائم طول أطول ثم واحد إذا isValid هي كاذبة عن النمط الأول --be حذر. أن تكون محددة في أنماط الخاص بك ممكن، إذا كنت تقصد لتتناسب مع عنصر واحد، أن تفعل ذلك.
إذا مهما العملية التي تستخدم للجمع بين أ و ب (في هذه الحالة +) ومكلفة حسابيا، ثم سيكون لديك لإسقاط when
واستخدام عبارة اسمحوا قبل اختبار isValid وإعادة نوع متغير.