سؤال

ما هي أفضل طريقة / الكنسي لتعريف دالة مع الوسائط المسماة اختياري؟ لجعلها ملموسة، دعونا إنشاء foo وظيفة مع الوسائط المسماة a، b، وc، التي الافتراضية إلى 1، 2، و 3، على التوالي. وعلى سبيل المقارنة، وهنا نسخة من foo بحجج الموضعية:

foo[a_:1, b_:2, c_:3] := bar[a,b,c]

وهنا يتم إدخال عينة والإخراج لإصدار الوسائط المسماة من foo:

foo[]                  --> bar[1,2,3]
foo[b->7]              --> bar[1,7,3]
foo[a->6, b->7, c->8]  --> bar[6,7,8]

ووينبغي بالطبع أيضا أن يكون من السهل أن يكون الحجج الموضعية قبل الوسائط المسماة.

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

المحلول

ولقد وجدت طريقة قياسية للقيام بذلك في وثائق الرياضيات: HTTP: // المرجعية .wolfram.com / الرياضيات / تعليمي / SettingUpFunctionsWithOptionalArguments.html

Options[foo] = {a->1, b->2, c->3};  (* defaults *)
foo[OptionsPattern[]] := bar[OptionValue@a, OptionValue@b, OptionValue@c]

والكتابة "OptionValue" في كل مرة القليل مرهقة. لسبب ما لا يمكن جعل مجرد اختصار العالمي مثل ov = OptionValue لكن يمكنك أن تفعل هذا:

foo[OptionsPattern[]] := Module[{ov},
  ov[x___] := OptionValue[x];
  bar[ov@a, ov@b, ov@c]]

وأو هذا:

With[{ov = OptionValue},
  foo[OptionsPattern[]] := bar[ov@a, ov@b, ov@c]
]

وأو هذا:

$PreRead = ReplaceAll[#, "ov" -> "OptionValue"] &;

foo[OptionsPattern[]] := bar[ov@a, ov@b, ov@c]

نصائح أخرى

نعم، OptionValue يمكن أن تكون صعبة بعض الشيء لأنه لا يعتمد على قطعة من السحر بحيث

<اقتباس فقرة>   

وOptionValue[name] ما يعادل OptionValue[f,name]، حيث f هو رئيس الجانب الأيسر للقاعدة التحول الذي يبدو OptionValue[name].

ورمي في Automatic صريحة عادة لا حيلة، وذلك في قضيتك وأود أن أقول أن الحل هو:

Options[foo] = {a -> 1, b -> 2, c -> 3};
foo[OptionsPattern[]] := 
  bar @@ (OptionValue[Automatic, #] &) /@ First /@ Options[foo] 

وبالمناسبة، الخيارات المستخدمة ينبغي القيام به عن طريق مطابقة لopts:___?OptionQ، ومن ثم إيجاد القيم الخيار يدويا كما {a,b,c}/.Flatten[{opts}]. وOptionQ الاختيار نمط لا يزال حوالي (وإن لم يكن موثقة)، ولكن النهج OptionValue لديه ميزة أن تحصل تحذيرات من الخيارات غير موجودة (مثل foo[d->3]). وهذا من شأنه أيضا أن تكون الحال بالنسبة لاستجابة الثانية، ولكن ليس لاحد كنت قد قبلته.

وأنا رمي هذا حل ممكن في هذا المزيج:

foo[opts___Rule] := Module[{f},
  f@a = 1; (* defaults... *)
  f@b = 2;
  f@c = 3;
  each[a_->v_, {opts}, f@a = v];

  Return[bar[f@a, f@b, f@c]]
]

وأنا أحب ذلك لاختصارية ولكن لا اعتقد انها الطريقة القياسية. أي gotchas مع القيام به بهذه الطريقة؟

وPS، فإنه يستخدم وظيفة أداة يدوية التالية:

SetAttributes[each, HoldAll];                (* each[pattern, list, body]     *)
each[pat_, lst_, bod_] :=                    (*  converts pattern to body for *)
  Scan[Replace[#, pat:>bod]&, Evaluate@lst]  (*   each element of list.       *)
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top