سؤال

أنا غير راضٍ عمومًا عن كتابة رمز مثل هذا:

let load_record_field cursor gets geti gett a = function
  | 0x01 -> let c, s = gets () in (a.a_record_uuid <- s; `More_record c)
  | 0x02 -> let c, s = gets () in (a.a_group <- s; `More_record c)
  | 0x03 -> let c, s = gets () in (a.a_title <- s; `More_record c)
  | 0x04 -> let c, s = gets () in (a.a_username <- s; `More_record c)
  | 0x07 -> let c, t = gett () in (a.a_creation_time <- t; `More_record c)
  .
  .
  .
  | 0xFF -> `End_of_record cursor

لقد قللت من الغلاية ، لكنني كنت أتساءل عما إذا كان هناك أي سحر OCAML من شأنه أن يتيح لي القضاء عليه تمامًا.

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

المحلول

هذا الأمر بسيط: ما عليك سوى استخدام الإغلاق للقيام بالإعداد ، واكتب وظيفة لتجريد من الغلاية

let load_record_field cursor gets geti gett a x =
  let frob get set =
     let (c,s) = get () in
     set s; `More_record c
  in
  function
  | 0x01 -> frob gets (fun s -> a.a_record_uuid <- s)
  | 0x02 -> frob gets (fun s -> a.a_group <- s)
  | 0x03 -> frob gett (fun s -> a.a_title <- s)
  ...

وهلم جرا.

يمكنك جعل هذا أفضل إذا كنت تستخدم حزمة الماكرو مثل Jane Street's Fieldslib. هذا يولد حقول من الدرجة الأولى ، جنبا إلى جنب مع المستوطنين و getters التي تم إنشاؤها تلقائيًا. هذا يعني أنه لن تضطر إلى بناء الإغلاق في كل مرة باليد.

نصائح أخرى

تطبيق وحدة التحكم لا يضيف تلقائيا مرجعا إلى system.windows.forms.dll.

انقر بزر الماوس الأيمن فوق مشروعك في Solution Explorer وحدد إضافة مرجع ... ثم ابحث عن System.windows.forms وإضافته.

أنا غير راضٍ عمومًا عن كتابة كود مثل هذا

علامة على الذوق الجيد ، إذا سألتني :-)


لا أعرف أي سحر ، لكنني أعتقد أن أفضل طريق هو تقسيم الغلاية:

  1. دالة STERTER واحدة لكل حقل قابل للتغيير. قد تكون مفيدة في سياقات مختلفة.

  2. بنية بيانات واحدة لتعيين رموز عدد صحيح إلى "ماذا تفعل مع هذا الحقل"

يمكنك تنفيذ ماسح التسجيل الخاص بك باستخدام جدول بدلاً من وظيفة. يظهر مثال موحي أدناه. الفرق بين gets و gett هو كيكر حقيقي هنا. في ما يلي،

  • sf تعني "حقل السلسلة"
  • tf تعني "حقل الوقت"
  • eor تعني "نهاية التسجيل"

لقد صنعت tabulate و lookup لتناسب مثالي ؛ استخدام أي بنية البيانات فعالة.

let sf set a c =     let c, s = gets() in (set a s; `More_record c)
let tf set a c =     let c, s = gett() in (set a t; `More_record c)
let eor    a c =     `End_of_record c

let fields = tabulate
  [ 0x01, sf a_record_uuid
  ; 0x02, sf a_group
  ; ...
  ; 0x07, tf a_creation_time
  ; ...
  ]

let load_record_field cursor gets geti gett a code = lookup fields code cursor a
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top