الدوال كـقيم فئة-أولى (#F )

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

المقاييس النموذجية لحالة فئة أولى تتضمن ما يلي:

  • يمكن ربط معرف بالقيمة ؟ هل يمكن إعطاءه إسم ؟

  • يمكن تخزين القيمة في بنية بيانات مثل قائمة ؟

  • هل يمكن تمرير القيمة كوسيطة في استدعاء الدالة ؟

  • يمكن إرجاع القيمة كقيمة استدعاء دالة ؟

أخر مقياسين يقومون بتعريف ما يعرف عمليات ذات رتبة أعلى أو دوال ذات رتبة أعلى . دوال ذات رتب أعلى تقو دوال كوسائط و تقوم بإرجاع دوال كقيمة. تدعم هذه العمليات مثل mainstays برمجة الوظيفية كتعيين دوال و إنشاء دوال.

إعطاء القيمة اسم

إذا كانت الدالة قيمة فئة أولى يجب أن تكون قادراً على إعطائها اسم, تماماً كما يمكنك تسمية أعداد صحيحة، سلاسل وأنواع المضمنة الأخرى. ويشار هذا في كتابات البرمجة الوظيفية بربط معرف بقيمة. F# يستخدم تعبيرات let لربط أسماء بالقيم: let <identifier> = <value>. إظهار التعليمة البرمجية التالية أمثلة الثاني.

// Integer and string.
let num = 10
let str = "F#"

يمكنك تسمية دالة تماماً بسهولة. يحدد المثال التالي دالة مسماه squareIt بواسطة ربط المعرفsquareItإلىالتعبير لامداfun n -> n * n دالة squareIt تحتوي على معلمة واحدة n ، وإرجاع مربع تلك المعلمة.

let squareIt = fun n -> n * n

#F توفر بناء الجملة بطريقة أكثر إيجازاً لتحقيق نفس النتيجة بواسطة كتابة أقل.

let squareIt2 n = n * n

تستخدم الأمثلة التي تتبع غالبًا نمط الأول let <function-name> = <lambda-expression> لإبراز أوجه التشابه بين تعريف وظائف و تعريف أنواع أخرى من القيم. ومع ذلك، كافة الدوال المسماه يمكن كتابتها بإستخدام بناء الجملة بإيجازاً. يتم كتابة بعض الأمثلة بالطريقتين.

تخزين القيمة في بنية بيانات

قيمة فئو أولى يمكن تخزينها في بنية بيانات. التعليمة البرمجية التالية تعرض أمثلة لتخزين قيم في قوائم وفي المجموعات.

// Lists.

// Storing integers and strings.
let integerList = [ 1; 2; 3; 4; 5; 6; 7 ]
let stringList = [ "one"; "two"; "three" ]

// You cannot mix types in a list. The following declaration causes a 
// type-mismatch compiler error.
//let failedList = [ 5; "six" ]

// In F#, functions can be stored in a list, as long as the functions 
// have the same signature.

// Function doubleIt has the same signature as squareIt, declared previously.
//let squareIt = fun n -> n * n
let doubleIt = fun n -> 2 * n

// Functions squareIt and doubleIt can be stored together in a list.
let funList = [ squareIt; doubleIt ]

// Function squareIt cannot be stored in a list together with a function
// that has a different signature, such as the following body mass 
// index (BMI) calculator.
let BMICalculator = fun ht wt -> 
                    (float wt / float (squareIt ht)) * 703.0

// The following expression causes a type-mismatch compiler error.
//let failedFunList = [ squareIt; BMICalculator ]


// Tuples.

// Integers and strings.
let integerTuple = ( 1, -7 )
let stringTuple = ( "one", "two", "three" )

// A tuple does not require its elements to be of the same type.
let mixedTuple = ( 1, "two", 3.3 )

// Similarly, function elements in tuples can have different signatures.
let funTuple = ( squareIt, BMICalculator )

// Functions can be mixed with integers, strings, and other types in
// a tuple. Identifier num was declared previously.
//let num = 10
let moreMixedTuple = ( num, "two", 3.3, squareIt )

للتحقق من اسم دالة تم تخزينه في المجموعة بالفعل ، يستخدم المثال التالي عوامل fst و snd لإستخراج عناصر الأول والثاني من مجموعة الأعضاء المراد البحث عنها funAndArgTuple. العنصر الأول في مجموعة الأعضاء المراد البحث عنهاsquareIt هو العنصر الثاني العنصر الأول في مجموعة الأعضاء المراد البحث عنها num. معرف num منضم في المثال السابق إلى عدد صحيح 10، وسيطة صالحة للدالة squareIt. التعبير الثاني يطبق العنصر الأول في مجموعة الأعضاء المراد البحث عنها فى العنصر الثاني في مجموعة الأعضاء المراد البحث عنها: squareIt num.

// You can pull a function out of a tuple and apply it. Both squareIt and num
// were defined previously.
let funAndArgTuple = (squareIt, num)

// The following expression applies squareIt to num, returns 100, and 
// then displays 100.
System.Console.WriteLine((fst funAndArgTuple)(snd funAndArgTuple))

وبشكل مماثل، فقط كمعرف num ويمكن استخدام العدد الصحيح 10 بشكل تبادلي لذا يمكن معرف squareIt و التعبير لامدا fun n -> n * n.

// Make a list of values instead of identifiers.
let funAndArgTuple2 = ((fun n -> n * n), 10)

// The following expression applies a squaring function to 10, returns
// 100, and then displays 100.
System.Console.WriteLine((fst funAndArgTuple2)(snd funAndArgTuple2))

تمرير القيمة كوسيطة

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

// An integer is passed to squareIt. Both squareIt and num are defined in 
// previous examples.
//let num = 10
//let squareIt = fun n -> n * n
System.Console.WriteLine(squareIt num)

// String.
// Function repeatString concatenates a string with itself.
let repeatString = fun s -> s + s

// A string is passed to repeatString. HelloHello is returned and displayed.
let greeting = "Hello"
System.Console.WriteLine(repeatString greeting)

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

في المثال التالي، دالة applyIt لديها معلمتينop و arg. إذا أرسلت في دالة لهه معلمة واحدة لop و وسيطة مناسبة للدالة ل arg ، تقوم الدالة بإرجاع ناتج تطبيق op إلى arg. في المثال التالي كلاً من وسيطة من نوع دالة و وسيطة من نوع عدد صحيح تم إرسالهم بالطريقة نفسها بإستخدام أسمائهم.

// Define the function, again using lambda expression syntax.
let applyIt = fun op arg -> op arg

// Send squareIt for the function, op, and num for the argument you want to 
// apply squareIt to, arg. Both squareIt and num are defined in previous 
// examples. The result returned and displayed is 100.
System.Console.WriteLine(applyIt squareIt num)

// The following expression shows the concise syntax for the previous function
// definition.
let applyIt2 op arg = op arg
// The following line also displays 100.
System.Console.WriteLine(applyIt2 squareIt num)

القدرة على إرسال دالة كوسيطة إلى دالة أخرى فى ظل تجريدات شائعة في لغات البرمجة الوظيفية مثل مخطط أو عمليات التصفيه . عملية مخطط ، على سبيل المثال، يكون دالة أعلى رتبة تلتقط احتساب مشترك بواسطة وظائف من خلال القائمة ، قم بإجراء شيء ما إلى كل عنصر ثم إرجاع قائمة النتائج. قد تحتاج إلى زيادة كل عنصر في قائمة الأعداد الصحيحة, أو مربع كل عنصر أو تغيير كل عنصر في قائمة سلاسل إلى الأحرف الكبيرة. الجزء الخطأ من عملية الحساب هو عملية عودية الخطوات من خلال القائمة ويقوم ببناء قائمة النتائج للعودة. التقاط هذا جزء في دالة التعيين. عليك كتابة لتطبيق معين الدالة التي تريد تطبيقها على كل عنصر فى القائمة بشكل فردي (إضافة أو تربيع أو تغيير حالة الأحرف). يتم إرسال هذه الدالة كوسيطة إلى دالة التعيين ، فقط كـsquareIt يتم إرسالها إلى applyIt في المثال السابق.

#F توفر أساليب مخطط لمعظم أنواع المجموعات بما في ذلك قوائم مصفوفات مجموعات . تستخدم الأمثلة التالية قوائم. بناء الجملة List.map <the function> <the list>

// List integerList was defined previously:
//let integerList = [ 1; 2; 3; 4; 5; 6; 7 ]

// You can send the function argument by name, if an appropriate function
// is available. The following expression uses squareIt.
let squareAll = List.map squareIt integerList

// The following line displays [1; 4; 9; 16; 25; 36; 49]
printfn "%A" squareAll

// Or you can define the action to apply to each list element inline.
// For example, no function that tests for even integers has been defined,
// so the following expression defines the appropriate function inline.
// The function returns true if n is even; otherwise it returns false.
let evenOrNot = List.map (fun n -> n % 2 = 0) integerList

// The following line displays [false; true; false; true; false; true; false]
printfn "%A" evenOrNot

لمزيد من المعلومات، راجع قوائم (F #).

إرجاع القيمة من إستدعاء دالة

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

إستدعائات الدوال الأتية تقوم بإرجاع أعداد صحيحة وعرضها.

// Function doubleIt is defined in a previous example.
//let doubleIt = fun n -> 2 * n
System.Console.WriteLine(doubleIt 3)
System.Console.WriteLine(squareIt 4)

يلي استدعاء الدالة يقوم بإرجاع سلسلة.

// str is defined in a previous section.
//let str = "F#"
let lowercase = str.ToLower()

يلي استدعاء دالة ، تعريف المضمنة، إرجاع قيمة Boolean. القيمة المعروضة True.

System.Console.WriteLine((fun n -> n % 2 = 1) 15)

القدرة بإرجاع دالة كقيمة استدعاء دالة هى الصفة المميزة الثانية في الدوال ذات الرتب الأعلى. في المثال التالي checkFor معرفة كدالة تأخذ وسيطة واحدة item ، وإرجاع دالة جديدة بإسم القيمة الخاصة بها. الدالة التى تم إرجاعها تأخذ قائمة كوسيطة خاصة بها lst ، ثم تبحث عن item في lst. إذا كان item موجود، تقوم الدالة بإرجاع true. إذا كان item غير موجود، تقوم الدالة بإرجاع false. كما هو موضح في القسم السابق، تستخدم التعليمة البرمجية التالية قائمة الدالة ، List.exists ، للبحث في القائمة.

let checkFor item = 
    let functionToReturn = fun lst ->
                           List.exists (fun a -> a = item) lst
    functionToReturn

تستخدم التعليمة البرمجية التالية checkFor لإنشاء دالة جديدة تأخذ وسيطة واحدة، قائمة وتبحث عن 7 في القائمة.

// integerList and stringList were defined earlier.
//let integerList = [ 1; 2; 3; 4; 5; 6; 7 ]
//let stringList = [ "one"; "two"; "three" ]

// The returned function is given the name checkFor7. 
let checkFor7 = checkFor 7

// The result displayed when checkFor7 is applied to integerList is True.
System.Console.WriteLine(checkFor7 integerList)

// The following code repeats the process for "seven" in stringList.
let checkForSeven = checkFor "seven"

// The result displayed is False.
System.Console.WriteLine(checkForSeven stringList)

يستخدم المثال التالي حالة فئة أولى للدوال في #F لتعريف الدالة و compose ، الذي يرجع إنشاء دالة جهازي الوسيطات.

// Function compose takes two arguments. Each argument is a function 
// that takes one argument of the same type. The following declaration
// uses lambda expresson syntax.
let compose = 
    fun op1 op2 ->
        fun n ->
            op1 (op2 n)

// To clarify what you are returning, use a nested let expression:
let compose2 = 
    fun op1 op2 ->
        // Use a let expression to build the function that will be returned.
        let funToReturn = fun n ->
                            op1 (op2 n)
        // Then just return it.
        funToReturn

// Or, integrating the more concise syntax:
let compose3 op1 op2 =
    let funToReturn = fun n ->
                        op1 (op2 n)
    funToReturn

ملاحظة

للحصول على إصدار أقصر ، راجع المقطع التالي "Curried Functions."

يرسل التعليمة البرمجية التالية دالتين كوسائط compose ، كل منهما يأخذ وسيطة مفردة من النوع نفسه. قيمة الإرجاع هي دالة جديدة مركبة من وسائط الدالتين.

// Functions squareIt and doubleIt were defined in a previous example.
let doubleAndSquare = compose squareIt doubleIt
// The following expression doubles 3, squares 6, and returns and
// displays 36.
System.Console.WriteLine(doubleAndSquare 3)

let squareAndDouble = compose doubleIt squareIt
// The following expression squares 3, doubles 9, returns 18, and
// then displays 18.
System.Console.WriteLine(squareAndDouble 3)

ملاحظة

#F يوفر عاملان << و >> ، لإنشاء الدوال. على سبيل المثال، let squareAndDouble2 = doubleIt << squareIt مكافئ let squareAndDouble = compose doubleIt squareIt في المثال السابق.

المثال التالي من إرجاع دالة كقيمة استدعاء دالة ينشئ لعبة تخمين بسيطة . لإنشاء لعبة قم باستدعاء makeGame بالقيمة التي تريد لشخص آخر تخمينها target. قيمة الإرجاع من دالة makeGame هى دالة تأخذ وسيطة واحدة (التخمين) والتقارير ما إذا كان التخمين صحيح.

let makeGame target = 
    // Build a lambda expression that is the function that plays the game.
    let game = fun guess -> 
                   if guess = target then
                      System.Console.WriteLine("You win!")
                   else 
                      System.Console.WriteLine("Wrong. Try again.")
    // Now just return it.
    game

التعليمات البرمجية التالية تقوم بإستدعاءmakeGame ، إرسال القيمة 7 لـ target. معرف playGame منضم للتعبير لامدا التي تم إرجاعه. لذلك، playGame هى دالة تأخذ كوسيطة واحدة قيمة guess.

let playGame = makeGame 7
// Send in some guesses.
playGame 2
playGame 9
playGame 7

// Output:
// Wrong. Try again.
// Wrong. Try again.
// You win!

// The following game specifies a character instead of an integer for target. 
let alphaGame = makeGame 'q'
alphaGame 'c'
alphaGame 'r'
alphaGame 'j'
alphaGame 'q'

// Output:
// Wrong. Try again.
// Wrong. Try again.
// Wrong. Try again.
// You win!

دالات curried

العديد من الأمثلة الموجودة في المقطع السابق يمكن كتابة بسهواة أكثر خلال الاستفادة من currying تعريفات الدالة. currying هو عملية تحويل دالة تحتوي على أكثر من معلمة إلى سلسلة دوال كل منها يحتوي على معلمة مفردة . في #F ، الدوال التي تحتوي على أكثر من معلمة واحدة curried بالأصل. على سبيل المثال، compose من المقطع السابق يمكن كتابتها كما هو موضح في نمط موجز بمعلمات ثلاثة.

let compose4 op1 op2 n = op1 (op2 n)

ومع ذلك، تكون النتيجة دالة بمعلمة واحدة تقوم بإرجاع دالة بمعلمة واحدة بدورها تقوم بإرجاع دالة آخرى بمعلمة واحدة كما هو موضح في compose4curried.

let compose4curried =
    fun op1 ->
        fun op2 ->
            fun n -> op1 (op2 n)

يمكنك الوصول إلى هذه الدالة بعدة طرق. كل ما يلي أمثلة إرجاع وعرض 18. يمكنك استبدال compose4مع compose4curriedفي أي من الأمثلة.

// Access one layer at a time.
System.Console.WriteLine(((compose4 doubleIt) squareIt) 3)

// Access as in the original compose examples, sending arguments for 
// op1 and op2, then applying the resulting function to a value.
System.Console.WriteLine((compose4 doubleIt squareIt) 3)

// Access by sending all three arguments at the same time.
System.Console.WriteLine(compose4 doubleIt squareIt 3)

للتحقق من أن الدالة لا تزال تعمل كما كانت من قبل ، حاول حالات الاختبار الأصلي مرة أخرى.

let doubleAndSquare4 = compose4 squareIt doubleIt
// The following expression returns and displays 36.
System.Console.WriteLine(doubleAndSquare4 3)

let squareAndDouble4 = compose4 doubleIt squareIt
// The following expression returns and displays 18.
System.Console.WriteLine(squareAndDouble4 3)

ملاحظة

يمكنك تقييد currying بواسطة إحاطة المعلمات في مجموعات. للحصول على المعلومات، راجع "نقش معلمة" في معلمات و وسيطات (F #).

يستخدم المثال التالي currying ضمني لكتابة إصدار أقصر من makeGame. تفاصيل كيف makeGame ووحدات إرجاع game صواب يتم صريحة أقل في هذا التنسيق ولكن يمكنك التحقق من استخدام حالات الاختبار الأصلي النتيجة هي نفس.

let makeGame2 target guess =
    if guess = target then
       System.Console.WriteLine("You win!")
    else 
       System.Console.WriteLine("Wrong. Try again.")

let playGame2 = makeGame2 7
playGame2 2
playGame2 9
playGame2 7

let alphaGame2 = makeGame2 'q'
alphaGame2 'c'
alphaGame2 'r'
alphaGame2 'j'
alphaGame2 'q'

للحصول على معلومات حول currying ، راجع "التطبيق الجزئي للوسيطات" في الدالات (F #).

معرف و تعريف دالة بطريقة تبادلية

إسم المتغير num في الأمثلة السابق يتم تقييمها إلى رقم صحيح 10 ، و ليس بمفاجئة أن يكون num صالح، 10 صالحة أيضاً. ونفس الشيء صحيح لمعرفات الدالة و قيمها: أي مكان إسم الدالة يمكن استخدامه، يمكن استخدام المنضم للتعبير لامدا .

يحدد المثال التاليBoolean دالة تسمى isNegative ، ثم تستخدم إسم الدالة و التعريف بالتبادل. الأمثلة الثلاثة التالية تقوم بإرجاع و عرض False.

let isNegative = fun n -> n < 0

// This example uses the names of the function argument and the integer
// argument. Identifier num is defined in a previous example.
//let num = 10
System.Console.WriteLine(applyIt isNegative num)

// This example substitutes the value that num is bound to for num, and the
// value that isNegative is bound to for isNegative.
System.Console.WriteLine(applyIt (fun n -> n < 0) 10) 

لأخذ خطوة واحدة إضافية ، إستبدل القيمة applyIt لـ applyIt.

System.Console.WriteLine((fun op arg -> op arg) (fun n -> n < 0)  10)

الدوال هى قيم فئة أولى في #F

الأمثلة الموجودة في المقاطع السابقة توضح أن الدوال في #F تقوم بإستيفاء معايير لتكون قيم فئة أولى في F#‎:

  • يمكنك ربط معرف إلى تعريف دالة.

    let squareIt = fun n -> n * n
    
  • يمكنك تخزين دالة في بنية بيانات.

    let funTuple2 = ( BMICalculator, fun n -> n * n )
    
  • يمكنك تمرير دالة كوسيطة.

    let increments = List.map (fun n -> n + 1) [ 1; 2; 3; 4; 5; 6; 7 ]
    
  • يمكنك إرجاع دالة كقيمة إستدعاء دالة.

    let checkFor item = 
        let functionToReturn = fun lst ->
                               List.exists (fun a -> a = item) lst
        functionToReturn
    

لمزيد من المعلومات حول #F ما هو الجديد في Visual F# 2010 انظر بمرجع لغة F # or .

المثال

الوصف

التعليمة البرمجية التالية تحتوي على كافة الأمثلة في هذا الموضوع.

الرمز


// ** GIVE THE VALUE A NAME **

// Integer and string.
let num = 10
let str = "F#"

let squareIt = fun n -> n * n

let squareIt2 n = n * n


// ** STORE THE VALUE IN A DATA STRUCTURE **

// Lists.

// Storing integers and strings.
let integerList = [ 1; 2; 3; 4; 5; 6; 7 ]
let stringList = [ "one"; "two"; "three" ]

// You cannot mix types in a list. The following declaration causes a 
// type-mismatch compiler error.
//let failedList = [ 5; "six" ]

// In F#, functions can be stored in a list, as long as the functions 
// have the same signature.

// Function doubleIt has the same signature as squareIt, declared previously.
//let squareIt = fun n -> n * n
let doubleIt = fun n -> 2 * n

// Functions squareIt and doubleIt can be stored together in a list.
let funList = [ squareIt; doubleIt ]

// Function squareIt cannot be stored in a list together with a function
// that has a different signature, such as the following body mass 
// index (BMI) calculator.
let BMICalculator = fun ht wt -> 
                    (float wt / float (squareIt ht)) * 703.0

// The following expression causes a type-mismatch compiler error.
//let failedFunList = [ squareIt; BMICalculator ]


// Tuples.

// Integers and strings.
let integerTuple = ( 1, -7 )
let stringTuple = ( "one", "two", "three" )

// A tuple does not require its elements to be of the same type.
let mixedTuple = ( 1, "two", 3.3 )

// Similarly, function elements in tuples can have different signatures.
let funTuple = ( squareIt, BMICalculator )

// Functions can be mixed with integers, strings, and other types in
// a tuple. Identifier num was declared previously.
//let num = 10
let moreMixedTuple = ( num, "two", 3.3, squareIt )

// You can pull a function out of a tuple and apply it. Both squareIt and num
// were defined previously.
let funAndArgTuple = (squareIt, num)

// The following expression applies squareIt to num, returns 100, and 
// then displays 100.
System.Console.WriteLine((fst funAndArgTuple)(snd funAndArgTuple))

// Make a list of values instead of identifiers.
let funAndArgTuple2 = ((fun n -> n * n), 10)

// The following expression applies a squaring function to 10, returns
// 100, and then displays 100.
System.Console.WriteLine((fst funAndArgTuple2)(snd funAndArgTuple2))


// ** PASS THE VALUE AS AN ARGUMENT **

// An integer is passed to squareIt. Both squareIt and num are defined in 
// previous examples.
//let num = 10
//let squareIt = fun n -> n * n
System.Console.WriteLine(squareIt num)

// String.
// Function repeatString concatenates a string with itself.
let repeatString = fun s -> s + s

// A string is passed to repeatString. HelloHello is returned and displayed.
let greeting = "Hello"
System.Console.WriteLine(repeatString greeting)

// Define the function, again using lambda expression syntax.
let applyIt = fun op arg -> op arg

// Send squareIt for the function, op, and num for the argument you want to 
// apply squareIt to, arg. Both squareIt and num are defined in previous 
// examples. The result returned and displayed is 100.
System.Console.WriteLine(applyIt squareIt num)

// The following expression shows the concise syntax for the previous function
// definition.
let applyIt2 op arg = op arg
// The following line also displays 100.
System.Console.WriteLine(applyIt2 squareIt num)

// List integerList was defined previously:
//let integerList = [ 1; 2; 3; 4; 5; 6; 7 ]

// You can send the function argument by name, if an appropriate function
// is available. The following expression uses squareIt.
let squareAll = List.map squareIt integerList

// The following line displays [1; 4; 9; 16; 25; 36; 49]
printfn "%A" squareAll

// Or you can define the action to apply to each list element inline.
// For example, no function that tests for even integers has been defined,
// so the following expression defines the appropriate function inline.
// The function returns true if n is even; otherwise it returns false.
let evenOrNot = List.map (fun n -> n % 2 = 0) integerList

// The following line displays [false; true; false; true; false; true; false]
printfn "%A" evenOrNot


// ** RETURN THE VALUE FROM A FUNCTION CALL **

// Function doubleIt is defined in a previous example.
//let doubleIt = fun n -> 2 * n
System.Console.WriteLine(doubleIt 3)
System.Console.WriteLine(squareIt 4)

// The following function call returns a string:
// str is defined in a previous section.
//let str = "F#"
let lowercase = str.ToLower()

System.Console.WriteLine((fun n -> n % 2 = 1) 15)

let checkFor item = 
    let functionToReturn = fun lst ->
                           List.exists (fun a -> a = item) lst
    functionToReturn

// integerList and stringList were defined earlier.
//let integerList = [ 1; 2; 3; 4; 5; 6; 7 ]
//let stringList = [ "one"; "two"; "three" ]

// The returned function is given the name checkFor7. 
let checkFor7 = checkFor 7

// The result displayed when checkFor7 is applied to integerList is True.
System.Console.WriteLine(checkFor7 integerList)

// The following code repeats the process for "seven" in stringList.
let checkForSeven = checkFor "seven"

// The result displayed is False.
System.Console.WriteLine(checkForSeven stringList)

// Function compose takes two arguments. Each argument is a function 
// that takes one argument of the same type. The following declaration
// uses lambda expresson syntax.
let compose = 
    fun op1 op2 ->
        fun n ->
            op1 (op2 n)

// To clarify what you are returning, use a nested let expression:
let compose2 = 
    fun op1 op2 ->
        // Use a let expression to build the function that will be returned.
        let funToReturn = fun n ->
                            op1 (op2 n)
        // Then just return it.
        funToReturn

// Or, integrating the more concise syntax:
let compose3 op1 op2 =
    let funToReturn = fun n ->
                        op1 (op2 n)
    funToReturn

// Functions squareIt and doubleIt were defined in a previous example.
let doubleAndSquare = compose squareIt doubleIt
// The following expression doubles 3, squares 6, and returns and
// displays 36.
System.Console.WriteLine(doubleAndSquare 3)

let squareAndDouble = compose doubleIt squareIt
// The following expression squares 3, doubles 9, returns 18, and
// then displays 18.
System.Console.WriteLine(squareAndDouble 3)

let makeGame target = 
    // Build a lambda expression that is the function that plays the game.
    let game = fun guess -> 
                   if guess = target then
                      System.Console.WriteLine("You win!")
                   else 
                      System.Console.WriteLine("Wrong. Try again.")
    // Now just return it.
    game

let playGame = makeGame 7
// Send in some guesses.
playGame 2
playGame 9
playGame 7

// Output:
// Wrong. Try again.
// Wrong. Try again.
// You win!

// The following game specifies a character instead of an integer for target. 
let alphaGame = makeGame 'q'
alphaGame 'c'
alphaGame 'r'
alphaGame 'j'
alphaGame 'q'

// Output:
// Wrong. Try again.
// Wrong. Try again.
// Wrong. Try again.
// You win!


// ** CURRIED FUNCTIONS **

let compose4 op1 op2 n = op1 (op2 n)

let compose4curried =
    fun op1 ->
        fun op2 ->
            fun n -> op1 (op2 n)

// Access one layer at a time.
System.Console.WriteLine(((compose4 doubleIt) squareIt) 3)

// Access as in the original compose examples, sending arguments for 
// op1 and op2, then applying the resulting function to a value.
System.Console.WriteLine((compose4 doubleIt squareIt) 3)

// Access by sending all three arguments at the same time.
System.Console.WriteLine(compose4 doubleIt squareIt 3)

let doubleAndSquare4 = compose4 squareIt doubleIt
// The following expression returns and displays 36.
System.Console.WriteLine(doubleAndSquare4 3)

let squareAndDouble4 = compose4 doubleIt squareIt
// The following expression returns and displays 18.
System.Console.WriteLine(squareAndDouble4 3)

let makeGame2 target guess =
    if guess = target then
       System.Console.WriteLine("You win!")
    else 
       System.Console.WriteLine("Wrong. Try again.")

let playGame2 = makeGame2 7
playGame2 2
playGame2 9
playGame2 7

let alphaGame2 = makeGame2 'q'
alphaGame2 'c'
alphaGame2 'r'
alphaGame2 'j'
alphaGame2 'q'


// ** IDENTIFIER AND FUNCTION DEFINITION ARE INTERCHANGEABLE **

let isNegative = fun n -> n < 0

// This example uses the names of the function argument and the integer
// argument. Identifier num is defined in a previous example.
//let num = 10
System.Console.WriteLine(applyIt isNegative num)

// This example substitutes the value that num is bound to for num, and the
// value that isNegative is bound to for isNegative.
System.Console.WriteLine(applyIt (fun n -> n < 0) 10) 

System.Console.WriteLine((fun op arg -> op arg) (fun n -> n < 0)  10)


// ** FUNCTIONS ARE FIRST-CLASS VALUES IN F# **

//let squareIt = fun n -> n * n

let funTuple2 = ( BMICalculator, fun n -> n * n )

let increments = List.map (fun n -> n + 1) [ 1; 2; 3; 4; 5; 6; 7 ]

//let checkFor item = 
//    let functionToReturn = fun lst ->
//                           List.exists (fun a -> a = item) lst
//    functionToReturn

راجع أيضًا:

المرجع

المجموعات (F #)

الدالات (F #)

يسمح الربط (F #)

التعبيرات لامدا: المتعة كلمة أساسية (F #)

موارد أخرى

قوائم (F #)