تحويل رمز C# إلى F# (إذا بيان)
سؤال
أود أن أعرف كيفية تحويل هذا الرمز خط تلو الآخر من C# إلى F#. أنا لا أتطلع إلى استخدام أي نوع من تعابير F#أو شيء من هذا القبيل. أحاول أن أفهم كيف خريطة مباشرة C #'s بنيات F#.
هنا رمز C#:
//requires l.Length > 0
int GetMinimumValue(List<int> l) {
int minVal = l[0];
for (int i = 0; i < l.Length; ++i) {
if (l[i] > minValue) {
minVal = l[i];
}
}
return minVal;
}
وهنا محاولتي f#:
let getMinValue (l : int list) =
let minVal = l.Head
for i = 0 to (l.Length-1) do
if (l.Item(i) > minVal) then
minVal = col.Item(i)
minVal
الآن ، هذا لا يعمل. يبدو أن المشكلة مرتبطة بـ minVal = col.Item(i)
خط:
This expression was expected to have type unit but here has type bool
ما هي المشكلة حقًا؟
المحلول
إذا كنت ترغب في تحويله سطرًا سطراً ، فحاول ما يلي
let getMinValue (l:System.Collections.Generic.List<int>) =
let mutable min = l.Item(0)
for i = 0 to (l.Count-1) do
if l.Item(i) < min then min <- l.Item(i)
min
الآن لسبب حصولك على هذا الخطأ المعين. ألق نظرة على السطر التالي
minVal = col.Item(i)
في f# هذه ليست مهمة بل مقارنة. لذلك هذا تعبير ينتج قيمة منطقية ولكن داخل for
حلقة يجب أن تكون جميع التعبيرات void
/unit
عودة. وبالتالي تتلقى خطأ.
الواجب في F# لديه ما لا يقل عن نموذجين على علم به.
// Assigning to a mutable value
let mutable v1 = 42
v1 <- 13
// Assigning to a ref cell
let v1 = ref 0
v1 := 42
وبالطبع ، يجب عليك قراءة مقالة براين حول هذا الموضوع. إنه مفصل للغاية ويتجاوز العديد من النقاط الدقيقة للترجمة بين اللغتين
نصائح أخرى
هناك بعض المشكلات في ترجمك الحرفي. بادئ ذي بدء ، هناك مشكلة فورية تسبب خطأ البرمجيات: كما لاحظ الآخرون ، دع الروابط غير قابلة للتغيير افتراضيًا. ومع ذلك ، هناك مشكلة كبيرة واحدة على الأقل: System.Collections.Generic.List<T>
يختلف تمامًا عن F# 't list
. نوع BCL عبارة عن قائمة قابلة للتغيير مدعومة بمصفوفة ، والتي توفر وقتًا عشوائيًا ثابتًا إلى العناصر ؛ نوع F# هو قائمة مرتبطة منفردة ، لذا فإن الوصول إلى العنصر التاسع يستغرق وقتًا (ن). إذا أصرت على إجراء ترجمة التعبير عن طريق التعبير ، فقد تجد منشور المدونة هذا من قبل براين ذو قيمة.
أوصي بشدة أن تتبع نصيحة الآخرين ومحاولة تأقلم نفسك للتفكير في Idiomatic F# بدلاً من ترجمة C# حرفيًا. فيما يلي بعض الطرق لكتابة بعض الوظائف ذات الصلة في F#:
// Given an F# list, find the minimum element:
let rec getMinList l =
| [] -> failwith "Can't take the minimum of an empty list"
| [x] -> x
| x::xs ->
let minRest = getMin xs
min x minRest
لاحظ أن هذا يعمل على قوائم من أي نوع عناصر (مع التحذير الذي يجب أن يكون نوع العنصر comparable
من منظور F#أو تطبيق الوظيفة سيؤدي إلى خطأ في وقت الترجمة). إذا كنت تريد إصدارًا سيعمل على أي نوع من التسلسل بدلاً من فقط على القوائم ، فيمكنك أن تبنيه على Seq.reduce
الوظيفة ، التي تطبق الوظيفة المقدمة كوسيطة أولها لكل زوج من العناصر في تسلسل حتى تبقى قيمة واحدة.
let getMin s = Seq.reduce min s
أو أفضل ما في الأمر ، يمكنك استخدام المدمج Seq.min
وظيفة ، وهو ما يعادل.
اجابة قصيرة: =
ليست (قابلة للتغيير) مهمة في F#.
سؤال: هل تقصد حقًا col
?
الاقتراحات: حاول كتابة هذا دون أي مهام. هناك عودية ووظائف مدمجة تحت تصرفك :-)
يجب أن تقرأ
كيف يبدو رمز C# هذا في F#؟ (الجزء الأول: التعبيرات والبيانات)
أشعر بخيبة أمل لأن أيا من الإجابات الأخرى قد ربطتها بالفعل ، لأن الناس يسألون "كيفية تحويل C# إلى F#" كثيرًا ، وقد نشرت رابط الإجابة هذا كثيرًا ، والآن يجب على بعض المستجلين الآخرين معرفة هذا قون
هذه هي الترجمة الأكثر حرفية ممكنة:
let getMinimumValue (l: List<int>) =
let mutable minVal = l.[0]
for i=0 to l.Length-1 do
if l.[i] > minVal then
minVal <- l.[i]
minVal