Functies gebruiken in F#
Een eenvoudige functiedefinitie lijkt op het volgende:
let f x = x + 1
In het vorige voorbeeld is f
de naam van de functie , het argument x
is , wat type heeft int
, de hoofdtekst van de functie is x + 1
en de retourwaarde is van het type int
.
Een definitiekend kenmerk van F# is dat functies de eersteklas status hebben. U kunt met een functie doen wat u kunt doen met waarden van de andere ingebouwde typen, met een vergelijkbare mate van inspanning.
U kunt functiewaardennamen geven.
U kunt functies opslaan in gegevensstructuren, zoals in een lijst.
U kunt een functie doorgeven als argument in een functieaanroep.
U kunt een functie retourneren vanuit een functie-aanroep.
Geef de waarde een naam
Als een functie een eersteklas waarde is, moet u deze een naam kunnen geven, net zoals u gehele getallen, tekenreeksen en andere ingebouwde typen kunt noemen. Dit wordt in functionele programmeerliteratuur aangeduid als binding van een id aan een waarde. F# maakt gebruik van let
bindingen om namen te binden aan waarden: let <identifier> = <value>
. In de volgende code ziet u twee voorbeelden.
// Integer and string.
let num = 10
let str = "F#"
U kunt een functie net zo eenvoudig een naam opgeven. In het volgende voorbeeld wordt een functie gedefinieerd die wordt benoemd squareIt
door de id squareIt
te binden aan de lambda-expressiefun n -> n * n
. De functie squareIt
heeft één parameter en n
retourneert het kwadraat van die parameter.
let squareIt = fun n -> n * n
F# biedt de volgende beknoptere syntaxis om hetzelfde resultaat te bereiken met minder typen.
let squareIt2 n = n * n
De volgende voorbeelden gebruiken meestal de eerste stijl let <function-name> = <lambda-expression>
, om de overeenkomsten tussen de declaratie van functies en de declaratie van andere typen waarden te benadrukken. Alle benoemde functies kunnen echter ook worden geschreven met de beknopte syntaxis. Sommige voorbeelden worden op beide manieren geschreven.
De waarde opslaan in een gegevensstructuur
Een eersteklas waarde kan worden opgeslagen in een gegevensstructuur. De volgende code toont voorbeelden waarin waarden worden opgeslagen in lijsten en 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 )
Om te controleren of een functienaam die in een tuple is opgeslagen, in feite een functie evalueert, worden in het volgende voorbeeld de fst
en snd
operators gebruikt om de eerste en tweede elementen uit de tuple funAndArgTuple
te extraheren. Het eerste element in de tuple is squareIt
en het tweede element is num
. De id num
is gebonden in een vorig voorbeeld aan geheel getal 10, een geldig argument voor de squareIt
functie. De tweede expressie past het eerste element in de tuple toe op het tweede element in de 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))
Op dezelfde manier kunnen id's num
en gehele getallen 10 door elkaar worden gebruikt, zodat de id squareIt
en lambda-expressie fun n -> n * n
kunnen worden gebruikt.
// 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))
De waarde doorgeven als argument
Als een waarde een eersteklas status in een taal heeft, kunt u deze als argument doorgeven aan een functie. Het is bijvoorbeeld gebruikelijk om gehele getallen en tekenreeksen als argumenten door te geven. De volgende code toont gehele getallen en tekenreeksen die als argumenten worden doorgegeven in 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)
Als functies een eersteklas status hebben, moet u deze op dezelfde manier als argumenten kunnen doorgeven. Houd er rekening mee dat dit het eerste kenmerk is van functies in hogere volgorde.
In het volgende voorbeeld heeft de functie applyIt
twee parameters en op
arg
. Als u een functie verzendt met één parameter voor op
en een geschikt argument voor de functie arg
, retourneert de functie het resultaat van het toepassen op
op arg
. In het volgende voorbeeld worden zowel het functieargument als het argument geheel getal op dezelfde manier verzonden met behulp van hun namen.
// 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)
De mogelijkheid om een functie als argument naar een andere functie te verzenden, komt ten grondslag aan algemene abstracties in functionele programmeertalen, zoals kaart- of filterbewerkingen. Een kaartbewerking is bijvoorbeeld een functie met een hogere volgorde waarmee de berekening wordt vastgelegd die wordt gedeeld door functies die een lijst doorlopen, iets doen aan elk element en vervolgens een lijst met de resultaten retourneren. Mogelijk wilt u elk element in een lijst met gehele getallen verhogen of elk element kwadrateren of elk element in een lijst met tekenreeksen wijzigen in hoofdletters. Het foutgevoelige deel van de berekening is het recursieve proces dat de lijst doorloopt en een lijst maakt met de resultaten die moeten worden geretourneerd. Dat deel wordt vastgelegd in de toewijzingsfunctie. Het enige wat u hoeft te schrijven voor een bepaalde toepassing is de functie die u afzonderlijk wilt toepassen op elk lijstelement (toevoegen, kwadratuur, veranderende hoofdletters). Deze functie wordt als argument naar de toewijzingsfunctie verzonden, net zoals squareIt
in het vorige voorbeeld wordt verzonden applyIt
.
F# biedt kaartmethoden voor de meeste verzamelingstypen, waaronder lijsten, matrices en reeksen. In de volgende voorbeelden worden lijsten gebruikt. De syntaxis is 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
Zie Lijsten voor meer informatie.
De waarde van een functieoproep retourneren
Als een functie een eersteklas status in een taal heeft, moet u deze kunnen retourneren als de waarde van een functie-aanroep, net zoals u andere typen retourneert, zoals gehele getallen en tekenreeksen.
Met de volgende functie aanroepen worden gehele getallen geretourneerd en weergegeven.
// Function doubleIt is defined in a previous example.
//let doubleIt = fun n -> 2 * n
System.Console.WriteLine(doubleIt 3)
System.Console.WriteLine(squareIt 4)
Met de volgende functieoproep wordt een tekenreeks geretourneerd.
// str is defined in a previous section.
//let str = "F#"
let lowercase = str.ToLower()
Met de volgende functieaanroep, gedeclareerd inline, wordt een Booleaanse waarde geretourneerd. De weergegeven waarde is True
.
System.Console.WriteLine((fun n -> n % 2 = 1) 15)
De mogelijkheid om een functie als de waarde van een functie-aanroep te retourneren, is het tweede kenmerk van functies in een hogere volgorde. In het volgende voorbeeld checkFor
wordt gedefinieerd dat het een functie is die één argument item
gebruikt en een nieuwe functie retourneert als waarde. De geretourneerde functie gebruikt een lijst als argument lst
en zoekt naar item
in lst
. Als item
deze aanwezig is, retourneert true
de functie . Als item
deze niet aanwezig is, retourneert false
de functie . Net als in de vorige sectie maakt de volgende code gebruik van een opgegeven lijstfunctie, List.exists, om de lijst te doorzoeken.
let checkFor item =
let functionToReturn = fun lst ->
List.exists (fun a -> a = item) lst
functionToReturn
De volgende code gebruikt checkFor
om een nieuwe functie te maken die één argument, een lijst en zoekt naar 7 in de lijst.
// 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)
In het volgende voorbeeld wordt de eersteklas status van functies in F# gebruikt om een functie te declareren, compose
waarmee een samenstelling van twee functieargumenten wordt geretourneerd.
// 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
Notitie
Zie de volgende sectie, 'Curried Functions', voor een nog kortere versie.
Met de volgende code worden twee functies als argumenten verzonden, compose
waarvan beide één argument van hetzelfde type hebben. De retourwaarde is een nieuwe functie die een samenstelling is van de twee functieargumenten.
// 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)
Notitie
F# biedt twee operators en <<
>>
, die functies opstellen. Is bijvoorbeeld let squareAndDouble2 = doubleIt << squareIt
gelijk aan let squareAndDouble = compose doubleIt squareIt
in het vorige voorbeeld.
In het volgende voorbeeld van het retourneren van een functie als waarde van een functie-aanroep wordt een eenvoudig radend spel gemaakt. Als u een game wilt maken, belt makeGame
u met de waarde waarvoor iemand moet raden target
. De retourwaarde van de functie makeGame
is een functie die één argument (de schatting) gebruikt en rapporteert of de schatting juist is.
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
Met de volgende code aanroepen makeGame
, wordt de waarde 7
voor target
verzonden. De id playGame
is gebonden aan de geretourneerde lambda-expressie. playGame
Daarom is een functie die als één argument een waarde voor 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!
Curriede functies
Veel van de voorbeelden in de vorige sectie kunnen beknopter worden geschreven door gebruik te maken van de impliciete kerrie in F#-functiedeclaraties. Currying is een proces waarmee een functie met meer dan één parameter wordt getransformeerd in een reeks ingesloten functies, die elk één parameter hebben. In F# worden functies met meer dan één parameter inherent gecureerd. Uit de vorige sectie kan bijvoorbeeld compose
worden geschreven zoals wordt weergegeven in de volgende beknopte stijl, met drie parameters.
let compose4 op1 op2 n = op1 (op2 n)
Het resultaat is echter een functie van een parameter die een functie retourneert van een parameter die op zijn beurt een andere functie van een parameter retourneert, zoals wordt weergegeven in compose4curried
.
let compose4curried =
fun op1 ->
fun op2 ->
fun n -> op1 (op2 n)
U kunt deze functie op verschillende manieren openen. Elk van de volgende voorbeelden retourneert en geeft 18 weer. U kunt vervangen door compose4
compose4curried
een van de voorbeelden.
// 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)
Als u wilt controleren of de functie nog steeds werkt zoals voorheen, probeert u de oorspronkelijke testcases opnieuw.
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)
Notitie
U kunt kerrie beperken door parameters in tuples in te sluiten. Zie Parameterpatronen in Parameters en Argumenten voor meer informatie.
In het volgende voorbeeld wordt impliciete kerrie gebruikt om een kortere versie van makeGame
. De details van hoe makeGame
de game
functie wordt samengesteld en geretourneerd, zijn minder expliciet in deze indeling, maar u kunt controleren met behulp van de oorspronkelijke testcases dat het resultaat hetzelfde is.
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'
Zie 'Gedeeltelijke toepassing van argumenten' in Functies voor meer informatie over kerrie.
Id en functiedefinitie zijn uitwisselbaar
De naam num
van de variabele in de vorige voorbeelden resulteert in het gehele getal 10 en het is geen verrassing dat num
waar geldig is, 10 ook geldig is. Hetzelfde geldt voor functie-id's en hun waarden: overal waar de naam van de functie kan worden gebruikt, kan de lambda-expressie waaraan deze is gebonden, worden gebruikt.
In het volgende voorbeeld wordt een Boolean
functie gedefinieerd die wordt aangeroepen isNegative
en wordt vervolgens de naam van de functie en de definitie van de functie door elkaar gebruikt. De volgende drie voorbeelden retourneren en weergeven 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)
Als u het nog een stap verder wilt doen, vervangt u de waarde die applyIt
is gebonden aan applyIt
.
System.Console.WriteLine((fun op arg -> op arg) (fun n -> n < 0) 10)
Functies zijn eersteklas waarden in F#
De voorbeelden in de vorige secties laten zien dat functies in F# voldoen aan de criteria voor het zijn van eersteklas waarden in F#:
- U kunt een id binden aan een functiedefinitie.
let squareIt = fun n -> n * n
- U kunt een functie opslaan in een gegevensstructuur.
let funTuple2 = ( BMICalculator, fun n -> n * n )
- U kunt een functie doorgeven als argument.
let increments = List.map (fun n -> n + 1) [ 1; 2; 3; 4; 5; 6; 7 ]
- U kunt een functie retourneren als de waarde van een functie-aanroep.
let checkFor item =
let functionToReturn = fun lst ->
List.exists (fun a -> a = item) lst
functionToReturn
Zie de F#-taalreferentie voor meer informatie over F#.
Opmerking
Beschrijving
De volgende code bevat alle voorbeelden in dit onderwerp.
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