Függvények használata az F-ben#

Egy egyszerű függvénydefiníció a következőhöz hasonlít:

let f x = x + 1

Az előző példában a függvény neve f, az argumentum a xtípus int, a függvény törzse x + 1, a visszatérési érték pedig típus int.

Az F# egyik meghatározó jellemzője, hogy a függvények első osztályú állapotban vannak. A függvényekkel bármilyen műveletet elvégezhet a többi beépített típus értékeivel, hasonló mértékű erőfeszítéssel.

  • Megadhat függvényértékeket.

  • A függvényeket adatstruktúrákban, például listában tárolhatja.

  • Függvényeket argumentumként is átadhat függvényhívásokban.

  • Függvényeket függvényhívásból is visszaadhat.

Adjon nevet az értéknek

Ha egy függvény első osztályú érték, el kell tudnia nevezni, ahogy egész számokat, sztringeket és más beépített típusokat is. Ezt a funkcionális programozási szakirodalom az azonosító értékhez kötéseként említi. Az F# let kötésekkel köti a neveket az értékekhez: let <identifier> = <value>. Az alábbi kód két példát mutat be.

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

A függvényeket egyszerűen nevezheti el. Az alábbi példa egy olyan függvényt határoz meg, amely úgy van elnevezve squareIt , hogy az azonosítót squareIt a lambda kifejezéshezfun n -> n * n köti. A függvény squareIt egy paramétert tartalmaz, nés a paraméter négyzetét adja vissza.

let squareIt = fun n -> n * n

Az F# a következő tömörebb szintaxist nyújtja, hogy ugyanazt az eredményt kevesebb gépeléssel érje el.

let squareIt2 n = n * n

Az alábbi példák többnyire az első stílust használják, let <function-name> = <lambda-expression>hogy hangsúlyozzák a függvények deklarálása és más típusú értékek deklarálása közötti hasonlóságokat. Az elnevezett függvények azonban tömör szintaxissal is írhatók. Néhány példa mindkét módon meg van írva.

Az érték tárolása adatstruktúrában

Az első osztályú értékek adatstruktúrában tárolhatók. Az alábbi kód olyan példákat mutat be, amelyek listákban és listákban tárolják az értékeket.

// 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 )

Annak ellenőrzéséhez, hogy egy rekordban tárolt függvénynév valóban kiértékeli-e a függvényt, az alábbi példa az első és a második elem kinyerésére használja az fstsnd operátorokat a rekordból funAndArgTuple. Az első elem a rekordban, squareIt a második pedig a num. Az azonosító num egy korábbi példában 10 egész számra van kötve, amely a függvény érvényes argumentuma squareIt . A második kifejezés a rekord első elemét alkalmazza a rekord második elemére: 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))

Hasonlóképpen, ahogyan az azonosító num és az egész szám 10 használható felcserélhetően, úgy az azonosító squareIt és a lambda kifejezés fun n -> n * nis.

// Make a tuple 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))

Az érték átadása argumentumként

Ha egy érték első osztályú állapotú egy nyelven, argumentumként átadhatja azt egy függvénynek. Gyakran előfordul például, hogy egész számokat és sztringeket adnak át argumentumként. Az alábbi kód az F#-ban argumentumként átadott egész számokat és sztringeket jeleníti meg.

// 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)

Ha a függvények első osztályú állapotban vannak, ugyanúgy kell tudnia argumentumként átadni őket. Ne feledje, hogy ez a magasabb rendű függvények első jellemzője.

Az alábbi példában a függvény applyIt két paramétert op és arg. Ha olyan függvényt küld, amelynek egy paramétere op és egy megfelelő argumentuma van a függvénynek arg, a függvény a függvényre való alkalmazás opargeredményét adja vissza. Az alábbi példában a függvényargumentum és az egész szám argumentum is ugyanúgy lesz elküldve a nevük használatával.

// 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)

A függvények argumentumként való elküldésének lehetősége a funkcionális programozási nyelvek gyakori absztrakcióinak, például a leképezési vagy szűrési műveleteknek az alapjául szolgál. A leképezési művelet például egy magasabb rendű függvény, amely rögzíti a függvények által megosztott számításokat, amelyek végiglépnek egy listán, végrehajtanak valamit az egyes elemeken, majd visszaadják az eredmények listáját. Előfordulhat, hogy az egész számok listájának minden elemét növelni szeretné, vagy az egyes elemeket négyzetre szeretné kerekíteni, vagy a sztringek listájának minden elemét nagybetűsre szeretné módosítani. A számítás hibalehetőségre hajlamos része a rekurzív folyamat, amely végiglép a listán, és összeállítja a visszaadandó eredmények listáját. Ezt a részt a leképezési függvény rögzíti. Egy adott alkalmazáshoz csak azt a függvényt kell írnia, amelyet az egyes listaelemekre külön-külön szeretne alkalmazni (hozzáadás, guggolás, eset módosítása). Ez a függvény argumentumként lesz elküldve a leképezési függvénynekapplyIt, ahogyan squareIt az előző példában is.

Az F# térképmetelyeket biztosít a legtöbb gyűjteménytípushoz, beleértve a listákat, tömböket és szekvenciákat. Az alábbi példák listákat használnak. A szintaxis a következő: 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

További információ: Listák.

Függvényhívás értékének visszaadása

Végül, ha egy függvény első osztályú állapotú egy nyelven, akkor képesnek kell lennie arra, hogy visszaadja egy függvényhívás értékeként, ugyanúgy, mint más típusokat, például egész számokat és sztringeket.

Az alábbi függvényhívások egész számokat adnak vissza, és megjelenítik őket.

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

A következő függvényhívás egy sztringet ad vissza.

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

A következő függvényhívás beágyazott deklarált értéke logikai értéket ad vissza. A megjelenített érték a következő True: .

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

A függvények függvényhívás értékeként való visszaadásának képessége a magasabb rendű függvények második jellemzője. Az alábbi példában egy olyan függvényt határozunk meg, checkFor amely egy argumentumot vesz igénybe, itemés egy új függvényt ad vissza értékként. A visszaadott függvény argumentumként egy listát vesz fel, lstés a függvényben lstkeresitem. Ha item jelen van, a függvény ad vissza true. Ha item nincs jelen, a függvény ad vissza false. Az előző szakaszhoz hasonlóan az alábbi kód egy megadott listafüggvényt használ, a List.exists függvényt a lista kereséséhez.

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

Az alábbi kód egy új függvény létrehozására szolgál checkFor , amely egy argumentumot, egy listát és 7-et keres a listában.

// 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)

Az alábbi példa az F# függvényeinek első osztályú állapotát használja egy függvény deklarálásához, composeamely két függvényargumentum összetételét adja vissza.

// Function compose takes two arguments. Each argument is a function
// that takes one argument of the same type. The following declaration
// uses lambda expression 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

Feljegyzés

A még rövidebb verzióért tekintse meg a következő, "Curried Functions" című szakaszt.

Az alábbi kód két függvényt küld argumentumként compose, amelyek mindegyike egyetlen, azonos típusú argumentumot vesz fel. A visszatérési érték egy új függvény, amely a két függvényargumentum összetétele.

// 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)

Feljegyzés

Az F# két operátort biztosít, << és >>amelyek függvényeket alkotnak. Ez például let squareAndDouble2 = doubleIt << squareIt egyenértékű let squareAndDouble = compose doubleIt squareIt az előző példával.

Az alábbi példa egy függvény függvényhívás értékeként való visszaadására egy egyszerű találgatásos játékot hoz létre. Játék létrehozásához hívja meg makeGame azt az értéket, amelyet valaki kitalálhat target. A függvény makeGame visszatérési értéke egy függvény, amely egy argumentumot (a becslést) használ, és azt jelenti, hogy a becslés helyes-e.

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

A következő kódhívások makeGameaz érték 7 elküldésével a következőhöz: target. Az azonosító playGame a visszaadott lambda kifejezéshez van kötve. Ezért egy függvény, playGame amely egyetlen argumentumaként a függvény guessértékét veszi figyelembe.

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

Az előző szakasz számos példája tömörebben írható, ha kihasználja az F# függvény deklarációiban az implicit currying előnyeit. A currying egy olyan folyamat, amely egynél több paraméterrel rendelkező függvényt beágyazott függvények sorozatává alakít át, amelyek mindegyike egyetlen paraméterrel rendelkezik. Az F#-ban az egynél több paramétert tartalmazó függvények eredendően curriáltak. Az előző szakaszból például compose az alábbi tömör stílusban, három paraméterrel írható.

let compose4 op1 op2 n = op1 (op2 n)

Az eredmény azonban egy paraméter függvénye, amely egy paraméter egy függvényét adja vissza, amely egy paraméter egy másik függvényét adja vissza, ahogyan az a .compose4curried

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

Ezt a függvényt többféleképpen is elérheti. Az alábbi példák mindegyike 18-at ad vissza és jelenít meg. Bármelyik példában lecserélheti a helyére compose4compose4curried .

// 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)

Ha ellenőrizni szeretné, hogy a függvény továbbra is ugyanúgy működik-e, mint korábban, próbálkozzon újra az eredeti teszteseteket.

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)

Feljegyzés

Korlátozhatja a curry-t úgy, hogy a paramétereket a tuplesbe zárja. További információt a Paraméterek és argumentumok "Paraméterminták" című témakörben talál.

Az alábbi példa implicit currying használatával ír egy rövidebb verziót makeGame. A függvény felépítésének makeGame és visszaadásának részletei ebben a game formátumban kevésbé explicitek, de az eredeti tesztesetekkel ellenőrizheti, hogy az eredmény ugyanaz-e.

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'

További információ a curryingről: "Az argumentumok részleges alkalmazása" a Functionsben.

Az azonosító és a függvénydefiníció felcserélhető

Az előző példákban szereplő változó neve num a 10 egész számot értékeli ki, és nem meglepő, hogy ahol num érvényes, a 10 is érvényes. Ugyanez igaz a függvényazonosítókra és azok értékeire is: bárhol, ahol a függvény neve használható, a lambda kifejezés, amelyhez kötődik, használható.

Az alábbi példa egy úgynevezett isNegativefüggvényt Boolean határoz meg, majd a függvény nevét és a függvény definícióját használja felcserélhetően. A következő három példa mind visszaadja és megjeleníti 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)

Ha egy lépéssel tovább szeretné vinni, cserélje le a függvényhez applyItkötött értéketapplyIt.

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

A függvények első osztályú értékek az F-ben#

Az előző szakaszokban szereplő példák azt mutatják be, hogy az F# függvényei megfelelnek az F#-ban az első osztályú értékek feltételeinek:

  • Egy azonosítót függvénydefinícióhoz köthet.
let squareIt = fun n -> n * n
  • A függvények adatstruktúrában tárolhatók.
let funTuple2 = ( BMICalculator, fun n -> n * n )
  • A függvényeket argumentumként is átadhatja.
let increments = List.map (fun n -> n + 1) [ 1; 2; 3; 4; 5; 6; 7 ]
  • Függvényt függvényhívás értékeként is visszaadhat.
let checkFor item =
    let functionToReturn = fun lst ->
                           List.exists (fun a -> a = item) lst
    functionToReturn

Az F#-ről további információt az F# nyelvi referenciában talál.

Példa

Leírás

Az alábbi kód a jelen témakör összes példáját tartalmazza.

Kód

// ** 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 expression 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

Kapcsolódó információk