سؤال

أود أن أعرف كيفية تحويل هذا الرمز خط تلو الآخر من 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
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top