Lire en anglais

Partager via


Utilisation des fonctions en F#

Une définition de fonction simple se présente comme suit :

let f x = x + 1

Dans l’exemple précédent, le nom de la fonction est f, l’argument est x, dont le type est int, le corps de la fonction est x + 1, et la valeur de retour est de type int.

Une caractéristique de F# est que les fonctions ont un état de première classe. Avec une fonction, vous pouvez faire tout ce que vous pouvez faire avec les valeurs des autres types intégrés, avec un niveau d’effort comparable.

  • Vous pouvez donner des noms de valeurs de fonction.

  • Vous pouvez stocker des fonctions dans des structures de données, par exemple dans une liste.

  • Vous pouvez passer une fonction en tant qu’argument dans un appel de fonction.

  • Vous pouvez retourner une fonction à partir d’un appel de fonction.

Donner un nom à la valeur

Si une fonction est une valeur de première classe, vous devez être en mesure de la nommer, tout comme vous pouvez nommer des entiers, des chaînes et d’autres types intégrés. Dans la documentation de programmation fonctionnelle, il s’agit de la liaison d’un identificateur à une valeur. F# utilise des let liaisons pour lier les noms aux valeurs : let <identifier> = <value>. Le code suivant présente deux exemples.

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

Vous pouvez nommer une fonction tout aussi facilement. L’exemple suivant définit une fonction nommée squareIt en liant l’identificateur squareIt à l’expression fun n -> n * nlambda. La fonction squareIt a un paramètre, n, et elle retourne le carré de ce paramètre.

let squareIt = fun n -> n * n

F# fournit la syntaxe plus concise suivante pour obtenir le même résultat avec moins de saisie.

let squareIt2 n = n * n

Les exemples qui suivent utilisent principalement le premier style, let <function-name> = <lambda-expression>, pour mettre en évidence les similitudes entre la déclaration de fonctions et la déclaration d’autres types de valeurs. Toutefois, toutes les fonctions nommées peuvent également être écrites avec la syntaxe concise. Certains des exemples sont écrits des deux manières.

Stocker la valeur dans une structure de données

Une valeur de première classe peut être stockée dans une structure de données. Le code suivant montre des exemples qui stockent des valeurs dans des listes et des tuples.

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

Pour vérifier qu’un nom de fonction stocké dans un tuple s’évalue réellement à une fonction, l’exemple suivant utilise les opérateurs fst et snd pour extraire les premier et deuxième éléments du tuple funAndArgTuple. Le premier élément du tuple est squareIt et le deuxième élément est num. L’identificateur num est lié dans un exemple précédent à l’entier 10, un argument valide pour la fonction squareIt. La deuxième expression applique le premier élément dans le tuple au deuxième élément dans le tuple : 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))

De même, l’identificateur num et l’entier 10 peuvent être utilisés indifféremment, tout comme l’identificateur squareIt et l’expression lambda fun n -> n * n.

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

Passer la valeur en tant qu’argument

Si une valeur a l’état de première classe dans une langue, vous pouvez la passer en tant qu’argument à une fonction. Par exemple, il est courant de passer des entiers et des chaînes en tant qu’arguments. Le code suivant montre les entiers et les chaînes passés en tant qu’arguments en 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)

Si les fonctions ont un état de première classe, vous devez être en mesure de les passer en tant qu’arguments de la même manière. N’oubliez pas qu’il s’agit de la première caractéristique des fonctions d’ordre supérieur.

Dans l’exemple suivant, la fonction applyIt a deux paramètres, op et arg. Si vous envoyez une fonction qui a un paramètre pour op et un argument approprié pour la fonction à arg, la fonction retourne le résultat de l’application op à arg. Dans l’exemple suivant, l’argument de fonction et l’argument d’entier sont envoyés de la même manière, à l’aide de leurs noms.

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

La possibilité d’envoyer une fonction en tant qu’argument à une autre fonction est à la base des abstractions courantes dans les langages de programmation fonctionnels, tels que les opérations de mappage ou de filtre. Par exemple, une opération de mappage est une fonction d’ordre supérieur qui capture le calcul partagé par les fonctions qui parcourent une liste, effectuent quelque chose à chaque élément, puis retournent une liste des résultats. Vous pouvez incrémenter chaque élément dans une liste d’entiers, ou carrer chaque élément, ou modifier chaque élément d’une liste de chaînes en majuscules. La partie sujette aux erreurs du calcul est le processus récursif qui traverse la liste et génère une liste des résultats à retourner. Cette partie est capturée dans la fonction de mappage. Tout ce que vous avez à écrire pour une application particulière est la fonction que vous souhaitez appliquer à chaque élément de liste individuellement (ajout, quadrature, modification de cas). Cette fonction est envoyée en tant qu’argument à la fonction de mappage, tout comme squareIt est envoyé à applyIt dans l’exemple précédent.

F# fournit des méthodes de mappage pour la plupart des types de collection, y compris les listes, les tableaux et les séquences. Les exemples suivants utilisent des listes La syntaxe est 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

Pour plus d’informations, consultez Listes.

Retourner la valeur d’un appel de fonction

Enfin, si une fonction a l’état de première classe dans une langue, vous devez être en mesure de la renvoyer en tant que valeur d’un appel de fonction, tout comme vous retournez d’autres types, tels que des entiers et des chaînes.

Les appels de fonction suivants retournent des entiers et les affichent.

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

L'appel de fonction suivant retourne une chaîne.

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

L’appel de fonction suivant, déclaré inlined, retourne une valeur booléenne. La valeur affichée est True.

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

La possibilité de retourner une fonction en tant que valeur d’un appel de fonction est la deuxième caractéristique des fonctions d’ordre supérieur. Dans l’exemple suivant, checkFor est défini comme une fonction qui prend un argument, item, et retourne une nouvelle fonction comme sa valeur. La fonction retournée prend une liste comme son argument, lst, et recherche item dans lst. Si item est présent, la fonction retourne true. Si item n’est pas présent, la fonction retourne false. Comme dans la section précédente, le code suivant utilise une fonction de liste fournie, List.exists, pour effectuer une recherche dans la liste.

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

Le code suivant utilise checkFor pour créer une fonction qui prend un argument, une liste et recherche 7 dans la liste.

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

L’exemple suivant utilise l’état de première classe des fonctions en F# pour déclarer une fonction, compose, qui retourne une composition de deux arguments de fonction.

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

Notes

Pour une version encore plus courte, consultez la section suivante, « Fonctions curryfiées ».

Le code suivant envoie deux fonctions en tant qu’arguments à compose ; elles prennent toutes deux un seul argument du même type. La valeur de retour est une nouvelle fonction qui est une composition des deux arguments de fonction.

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

Notes

F# fournit deux opérateurs, << et >>, qui composent des fonctions. Par exemple, let squareAndDouble2 = doubleIt << squareIt est équivalent à let squareAndDouble = compose doubleIt squareIt dans l'exemple précédent.

L’exemple suivant de renvoi d’une fonction en tant que valeur d’un appel de fonction crée un jeu de devinette simple. Pour créer un jeu, appelez makeGame avec la valeur que vous souhaitez que quelqu’un devine envoyé pour target. La valeur de retour de la fonction makeGame est une fonction qui prend un argument (la devinette) et indique si la devinette est correcte.

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

Le code suivant appelle makeGame, en envoyant la valeur 7 pour target. L’identificateur playGame est lié à l’expression lambda retournée. Par conséquent, playGame est une fonction qui prend comme argument unique une valeur pour 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!

Fonctions curryfiées

La plupart des exemples de la section précédente peuvent être écrits de manière plus concise en tirant parti de la curryfication implicite dans les déclarations de fonction F#. La curryfication est un processus qui transforme une fonction qui a plus d’un paramètre en une série de fonctions incorporées, chacune ayant un seul paramètre. En F#, les fonctions qui ont plus d’un paramètre sont intrinsèquement curryfiées. Par exemple, à partir de la section précédente, vous pouvez écrire compose comme indiqué dans le style concis suivant, avec trois paramètres.

let compose4 op1 op2 n = op1 (op2 n)

Toutefois, le résultat est une fonction d’un paramètre qui retourne une fonction d’un paramètre qui retourne à son tour une autre fonction d’un paramètre, comme indiqué dans compose4curried.

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

Vous pouvez accéder à cette fonction de plusieurs manières. Chacun des exemples suivants retourne et affiche 18. Vous pouvez remplacer compose4 par compose4curried dans n’importe quel exemple.

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

Pour vérifier que la fonction fonctionne toujours comme avant, réessayez les cas de test d’origine.

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)

Notes

Vous pouvez restreindre la curryfication en enfermant les paramètres dans des tuples. Pour plus d’informations, consultez « Modèles de paramètres » dans Paramètres et arguments.

L’exemple suivant utilise la curryfication implicite pour écrire une version plus courte de makeGame. Les détails de la façon dont makeGame construit et retourne la fonction game sont moins explicites dans ce format, mais vous pouvez vérifier en utilisant les cas de test d’origine, que le résultat est identique.

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'

Pour plus d’informations sur la curryfication, consultez « Application partielle d’arguments » dans Fonctions.

L’identificateur et la définition de fonction sont interchangeables

Le nom de la variable num dans les exemples précédents est évalué à l’entier 10, et il n’est pas surprenant que lorsque num est valide, 10 l’est également. Il en va de même pour les identificateurs de fonction et leurs valeurs : partout où le nom de la fonction peut être utilisé, l’expression lambda à laquelle elle est liée peut être utilisée.

L’exemple suivant définit une fonction Boolean appelée isNegative, puis utilise le nom de la fonction et la définition de la fonction de manière interchangeable. Les trois exemples suivants retournent et affichent tous 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)

Pour aller plus loin, remplacez la valeur à laquelle applyIt est liée par applyIt.

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

Les fonctions sont des valeurs de première classe dans F#

Les exemples dans les sections précédentes montrent que les fonctions en F# répondent aux critères pour être des valeurs de première classe dans F# :

  • Vous pouvez lier un identificateur à une définition de fonction.
let squareIt = fun n -> n * n
  • Vous pouvez stocker une fonction dans une structure de données.
let funTuple2 = ( BMICalculator, fun n -> n * n )
  • Vous pouvez passer une fonction en tant qu’argument.
let increments = List.map (fun n -> n + 1) [ 1; 2; 3; 4; 5; 6; 7 ]
  • Vous pouvez retourner une fonction en tant que valeur d’un appel de fonction.
let checkFor item =
    let functionToReturn = fun lst ->
                           List.exists (fun a -> a = item) lst
    functionToReturn

Pour plus d’informations sur F#, consultez la Référence du langage F#.

Exemple

Description

Le code suivant contient tous les exemples de cette rubrique.

Code

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

Voir aussi