F'de işlevleri kullanma#
Basit bir işlev tanımı aşağıdakine benzer:
let f x = x + 1
Önceki örnekte işlev adı , f
bağımsız değişkeninin x
türü int
, işlev gövdesi ise x + 1
ve dönüş değeri türündedir int
.
F# işlevinin tanımlayıcı bir özelliği, işlevlerin birinci sınıf durumuna sahip olmasıdır. Bir işlevle, diğer yerleşik türlerin değerleriyle yapabileceğiniz her şeyi, benzer bir çabayla yapabilirsiniz.
İşlev değerlerine ad verebilirsiniz.
İşlevleri bir listede olduğu gibi veri yapılarında depolayabilirsiniz.
İşlev çağrısında bir işlevi bağımsız değişken olarak geçirebilirsiniz.
İşlev çağrısından işlev döndürebilirsiniz.
Değere Bir Ad Verin
İşlev birinci sınıf bir değerse, tamsayıları, dizeleri ve diğer yerleşik türleri adlandırabildiğiniz gibi işleve de ad verebilmeniz gerekir. Bu, işlevsel programlama literatüründe bir tanımlayıcıyı bir değere bağlama olarak adlandırılır. F# bağlamaları kullanarak let
adları değerlere bağlar: let <identifier> = <value>
. Aşağıdaki kodda iki örnek gösterilmektedir.
// Integer and string.
let num = 10
let str = "F#"
bir işlevi aynı şekilde kolayca adlandırabilirsiniz. Aşağıdaki örnek, tanımlayıcıyı squareIt
lambda ifadesine fun n -> n * n
bağlayarak adlı squareIt
bir işlevi tanımlar. İşlevin squareIt
bir parametresi n
vardır ve bu parametrenin karesini döndürür.
let squareIt = fun n -> n * n
F# aynı sonucu daha az yazıyla elde etmek için aşağıdaki daha kısa söz dizimini sağlar.
let squareIt2 n = n * n
İzleyen örneklerde çoğunlukla işlevlerin bildirimi ile diğer değer türlerinin bildirimi arasındaki benzerlikleri vurgulayan ilk stil let <function-name> = <lambda-expression>
kullanılır. Ancak, tüm adlandırılmış işlevler kısa söz dizimi ile de yazılabilir. Örneklerden bazıları her iki yolla da yazılmıştır.
Değeri Bir Veri Yapısında Depolama
Birinci sınıf bir değer bir veri yapısında depolanabilir. Aşağıdaki kod, değerleri listelerde ve tanımlama listelerinde depolayan örnekleri gösterir.
// 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 )
Bir demette depolanan bir işlev adının aslında bir işlev olarak değerlendirdiğini doğrulamak için, aşağıdaki örnekte fst
ve snd
işleçleri kullanılarak tanımlama grubundan birinci ve ikinci öğeler funAndArgTuple
ayıklanır. Tanımlama grubundaki ilk öğe, squareIt
ikinci öğe ise şeklindedir num
. Tanımlayıcı num
, önceki bir örnekte işlev için geçerli bir bağımsız değişken olan 10 tamsayısına squareIt
bağlıdır. İkinci ifade, tanımlama grubundaki ilk öğeyi tanımlama grubundaki ikinci öğeye uygular: 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))
Benzer şekilde, tanımlayıcı num
ve tamsayı 10 birbirinin yerine kullanılabilir, bu nedenle tanımlayıcı squareIt
ve lambda ifadesi fun n -> n * n
kullanılabilir.
// 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ğeri Bağımsız Değişken Olarak Geçirme
Bir değerin bir dilde birinci sınıf durumu varsa, bunu işleve bağımsız değişken olarak geçirebilirsiniz. Örneğin, tamsayıları ve dizeleri bağımsız değişken olarak geçirmek yaygın bir durumdur. Aşağıdaki kod, F# dilinde bağımsız değişken olarak geçirilen tamsayıları ve dizeleri gösterir.
// 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)
İşlevlerin birinci sınıf durumu varsa, bunları aynı şekilde bağımsız değişken olarak geçirebilmeniz gerekir. Bunun yüksek sıralı işlevlerin ilk özelliği olduğunu unutmayın.
Aşağıdaki örnekte, işlevin applyIt
iki parametresi op
vardır ve arg
. için bir parametresi ve işlevi için op
uygun bağımsız değişkeni olan bir işlev gönderirseniz, işlevi arg
uygulamasına arg
uygulamanın op
sonucunu döndürür. Aşağıdaki örnekte, hem işlev bağımsız değişkeni hem de tamsayı bağımsız değişkeni, adları kullanılarak aynı şekilde gönderilir.
// 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)
Bir işlevi başka bir işleve bağımsız değişken olarak gönderebilme özelliği, eşleme veya filtre işlemleri gibi işlevsel programlama dillerinde yaygın soyutlamaların altını çizer. Örneğin bir eşleme işlemi, bir listede adım adım ilerleyen, her öğeye bir şey yapıp sonuçların listesini döndüren işlevler tarafından paylaşılan hesaplamayı yakalayan yüksek sıralı bir işlevdir. Bir tamsayı listesindeki her öğeyi artırmak veya her öğenin karesini almak ya da dize listesindeki her öğeyi büyük harfle değiştirmek isteyebilirsiniz. Hesaplamanın hataya açık bölümü, listede ilerleyip döndürülecek sonuçların listesini oluşturan özyinelemeli işlemdir. Bu bölüm eşleme işlevinde yakalanır. Belirli bir uygulama için yazmanız gereken tek şey, her liste öğesine ayrı ayrı uygulamak istediğiniz işlevdir (ekleme, çömelmeye, büyük/küçük harf değiştirme). Bu işlev, önceki örnekte olduğu gibi eşleme işlevine applyIt
bağımsız değişken olarak squareIt
gönderilir.
F# listeler, diziler ve diziler dahil olmak üzere çoğu koleksiyon türü için eşleme yöntemleri sağlar. Aşağıdaki örneklerde listeler kullanılır. Söz dizimi List.map <the function> <the list>
şeklindedir.
// 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
Daha fazla bilgi için bkz . Listeler.
İşlev Çağrısından Değer Döndürme
Son olarak, bir işlevin bir dilde birinci sınıf durumu varsa, tamsayılar ve dizeler gibi diğer türleri döndürdiğiniz gibi işlev çağrısının değeri olarak döndürebilmeniz gerekir.
Aşağıdaki işlev çağrıları tamsayıları döndürür ve görüntüler.
// 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şağıdaki işlev çağrısı bir dize döndürür.
// str is defined in a previous section.
//let str = "F#"
let lowercase = str.ToLower()
Satır içinde bildirilen aşağıdaki işlev çağrısı bir Boole değeri döndürür. Görüntülenen değer şeklindedir True
.
System.Console.WriteLine((fun n -> n % 2 = 1) 15)
İşlev çağrısının değeri olarak işlev döndürme özelliği, yüksek sıralı işlevlerin ikinci özelliğidir. Aşağıdaki örnekte, checkFor
bağımsız değişkenlerinden item
birini alan ve değeri olarak yeni bir işlev döndüren bir işlev olarak tanımlanmıştır. Döndürülen işlev bağımsız lst
değişkeni olarak bir liste alır ve içinde lst
öğesini araritem
. varsa item
, işlevi döndürür true
. yoksa item
, işlevi döndürür false
. Önceki bölümde olduğu gibi aşağıdaki kod, listede arama yapmak için sağlanan List.exists list işlevini kullanır.
let checkFor item =
let functionToReturn = fun lst ->
List.exists (fun a -> a = item) lst
functionToReturn
Aşağıdaki kod, bir bağımsız değişken, bir liste alan ve listede 7'yi arayan yeni bir işlev oluşturmak için kullanır checkFor
.
// 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)
Aşağıdaki örnek, compose
iki işlev bağımsız değişkeninin bileşimini döndüren bir işlevi bildirmek için F# içindeki işlevlerin birinci sınıf durumunu kullanır.
// 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
Not
Daha da kısa bir sürüm için aşağıdaki "Curried functions" bölümüne bakın.
Aşağıdaki kod, her ikisi de aynı türde tek bir bağımsız değişken alan iki işlevi bağımsız değişken compose
olarak gönderir. Dönüş değeri, iki işlev bağımsız değişkeninin bileşimi olan yeni bir işlevdir.
// 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)
Not
F# işlevi oluşturan iki işleç <<
ve >>
sağlar. Örneğin, let squareAndDouble2 = doubleIt << squareIt
önceki örnekteki ile let squareAndDouble = compose doubleIt squareIt
eşdeğerdir.
İşlev çağrısının değeri olarak işlev döndürmenin aşağıdaki örneği basit bir tahmin oyunu oluşturur. Bir oyun oluşturmak için, birinin için target
gönderildiğini tahmin etmelerini istediğiniz değerle çağrısında makeGame
bulunabilirsiniz. İşlevden makeGame
döndürülen değer, bir bağımsız değişken (tahmin) alan ve tahminin doğru olup olmadığını bildiren bir işlevdir.
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şağıdaki kod çağrısı yapar makeGame
ve değerini 7
target
gönderir. Tanımlayıcı playGame
, döndürülen lambda ifadesine bağlıdır. Bu nedenle, playGame
tek bağımsız değişkeni olarak değerini alan bir guess
işlevdir.
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 İşlevleri
Önceki bölümdeki örneklerin çoğu, F# işlev bildirimlerindeki örtük currying özelliğinden yararlanılarak daha kısa yazılabilir. Currying, birden fazla parametresi olan bir işlevi, her biri tek bir parametresi olan bir dizi eklenmiş işleve dönüştüren bir işlemdir. F# dilinde, birden fazla parametresi olan işlevler doğal olarak curried. Örneğin, compose
önceki bölümden üç parametreyle aşağıdaki kısa stilde gösterildiği gibi yazılabilir.
let compose4 op1 op2 n = op1 (op2 n)
Ancak, sonuç, içinde gösterildiği compose4curried
gibi bir parametrenin başka bir işlevini döndüren bir parametrenin işlevini döndüren bir parametrenin işlevidir.
let compose4curried =
fun op1 ->
fun op2 ->
fun n -> op1 (op2 n)
Bu işleve çeşitli yollarla erişebilirsiniz. Aşağıdaki örneklerin her biri döndürür ve 18 değerini görüntüler. öğesini, örneklerden herhangi birinde ile compose4curried
değiştirebilirsinizcompose4
.
// 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)
İşlevin daha önce olduğu gibi çalışmaya devam ettiğini doğrulamak için özgün test çalışmalarını yeniden deneyin.
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)
Not
Parametreleri tanımlama demetleri içine alarak currying'i kısıtlayabilirsiniz. Daha fazla bilgi için Bkz. Parametreler ve Bağımsız Değişkenler'deki "Parametre Desenleri".
Aşağıdaki örnek, daha kısa bir sürümünü makeGame
yazmak için örtük currying kullanır. yapılarının ve işlevin nasıl makeGame
döndürüldüğünün game
ayrıntıları bu biçimde daha az açıktır, ancak özgün test çalışmalarını kullanarak sonucun aynı olduğunu doğrulayabilirsiniz.
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 hakkında daha fazla bilgi için İşlevler'deki "Kısmi Bağımsız Değişkenlerin Uygulaması" bölümüne bakın.
Tanımlayıcı ve İşlev Tanımı Değiştirilebilir
Önceki örneklerde yer alan değişken adı num
10 tamsayısını değerlendirir ve 10'un geçerli olduğu durumlarda num
da geçerli olması şaşırtıcı değildir. Aynı durum işlev tanımlayıcıları ve değerleri için de geçerlidir: işlevin adının kullanılabildiği her yerde, bağlı olduğu lambda ifadesi kullanılabilir.
Aşağıdaki örnek adlı isNegative
bir Boolean
işlevi tanımlar ve ardından işlevin adını ve işlevinin tanımını birbirinin yerine kullanır. Sonraki üç örneğin tümü döndürür ve görüntüler 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)
Bunu bir adım ileriye götürmek için, için applyIt
bağlı olan değeri applyIt
değiştirin.
System.Console.WriteLine((fun op arg -> op arg) (fun n -> n < 0) 10)
İşlevler F'de Birinci Sınıf Değerlerdir#
Önceki bölümlerdeki örnekler, F# içindeki işlevlerin F# dilinde birinci sınıf değerler olma ölçütlerini karşıladığını göstermektedir:
- Bir tanımlayıcıyı işlev tanımına bağlayabilirsiniz.
let squareIt = fun n -> n * n
- Bir işlevi bir veri yapısında depolayabilirsiniz.
let funTuple2 = ( BMICalculator, fun n -> n * n )
- bir işlevi bağımsız değişken olarak geçirebilirsiniz.
let increments = List.map (fun n -> n + 1) [ 1; 2; 3; 4; 5; 6; 7 ]
- İşlev çağrısının değeri olarak işlev döndürebilirsiniz.
let checkFor item =
let functionToReturn = fun lst ->
List.exists (fun a -> a = item) lst
functionToReturn
F# hakkında daha fazla bilgi için bkz . F# Dil Başvurusu.
Örnek
Açıklama
Aşağıdaki kod bu konudaki tüm örnekleri içerir.
Kod
// ** 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