سؤال

أردت أن يكون لديك نسخة تكريس الذيل من List.map, ، لذلك كتبت بلدي. ها هو:

let rec list_map f l ?(accum=[])=
  match l with
      head :: tail -> list_map f tail ~accum:(head :: accum)
    | [] -> accum;;

كلما أرادت هذه الوظيفة، أحصل على:

File "main.ml", line 69, characters 29-31:
Warning X: this optional argument cannot be erased.

ال الدورة التعليمية يقول أن هذا يعني أنني أحاول إنشاء وظيفة بدون حجج غير اختيارية. ولكن الوظيفة أعلاه تأخذ بوضوح حجج غير اختيارية.

ربما أفعل شيئا غبي حقا، لكن ماذا؟

هل كانت مفيدة؟

المحلول

الحلول السابقة تجميعها، ولكن لن تعطي النتيجة المتوقعة. الوظيفة f لا يتم تطبيقه أبدا على الحجج. الرمز الصحيح هو:

let rec list_map f ?(accum = []) l = match l with
    | head :: tail -> list_map f ~accum:(f head :: accum) tail
    | [] -> accum;;

النوع الذي يستنتج هو:

val list_map : ('a -> 'b) -> ?accum:'b list -> 'a list -> 'b list = <fun>

... على النقيض من الخطأ الخطأ:

val list_map : 'a -> ?accum:'b list -> 'b list -> 'b list = <fun>

يرجى ملاحظة أنه يتم عكس قائمة النتائج:

# list_map ( ( ** ) 2.) [1.;2.;3.;4.];;
- : float list = [16.; 8.; 4.; 2.]

... ويساوي الوظيفة Rev_List من وحدة القائمة:

# List.rev_map ( ( ** ) 2.) [1.;2.;3.;4.];;
- : float list = [16.; 8.; 4.; 2.]

لذلك قد ترغب في تغيير وظيفتك إلى:

let rec list_map f ?(accum = []) l = match l with
    | head :: tail -> list_map f ~accum:(f head :: accum) tail
    | [] -> List.rev accum;;

... والتي يجب أن تكون Tax-Recursive أيضا (وفقا للدليل) وإرجاع القائمة في الترتيب الأصلي:

# list_map ( ( ** ) 2.) [1.;2.;3.;4.];;
- : float list = [2.; 4.; 8.; 16.]

نصائح أخرى

نعم لا يمكن أن تكون الوسيطة غير الاختيارية الخاصة بك أخيرة، لأنه نظرا لأن OCAML يدعم التطبيقات الجزئية، فإن الوظيفة التي تفتقد أن الوسيطة الاختيارية الأخيرة ستبدو تماما مثل وظيفة تطبيقها جزئيا لا تزال تبحث عن الوسيطة الاختيارية. الطريقة الوحيدة لذلك لمعرفة أنه لا تنوي تقديم الوسيطة الاختيارية هي أنه يرى أنك قد قدمت حجة بعد ذلك.

إذا كان عليك أن تستمر، فيمكنك وضع دمية unit حجة بعد ذلك:

let rec list_map f l ?(accum=[]) () =
  match l with
      head :: tail -> list_map f tail ~accum:(head :: accum) ()
    | [] -> accum;;

ولكن في هذه الحالة نعم تغيير النظام سيكون أفضل.

تحتاج إلى حجة غير اختيارية بعد واحد اختياري. ما عليك سوى تغيير ترتيب حجج وظيفتك:

let rec list_map f ?(accum=[]) l=
  match l with
    head :: tail -> list_map f  ~accum:(head :: accum) tail
  | [] -> accum;;
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top