Aracılığıyla paylaş


İlk Sınıf Değerleri (F#) olarak İşlevler

Fonksiyonel programlama dillerinin özelliklerinin tanımlanması, işlevlerin ilk sınıf durumuna yükseltilmesidir. Diğer yerleşik türlerin değerleriyle ne yapabiliyorsanız bunları karşılaştırılabilir çaba ölçüsünde işlevle de yapabilmelisiniz.

İlk sınıf durumlarının tipik önlemleri şunları içerir:

  • Tanımlayıcıyı bir değere bağlayabilir misiniz? Yani, bir ad verebilir misiniz?

  • Değeri liste gibi bir veri yapısında saklayabilir misiniz?

  • Değeri bağımsız bir değişken olarak işleve verebilir misiniz?

  • Değeri işlev çağrısının değeri olarak dönebilir misiniz?

Son iki önlem daha yüksek sıralı işlemler veya daha yüksek sıralı işlevler olarak bilinenleri tanımlar. Daha yüksek sıralı işlevler, işlevleri bağımsız değişkenler olarak kabul eder ve işlevleri işlev çağrılarının değeri olarak döndürür. Bu işlemler fonksiyonel programlamanınnın başlıca dayanağı olan işlevleri eşleme ve işlevler oluşumunu destekler.

Değere bir ad verin

Eğer bir işlev ilk sınıf değeri ise tamsayıları, dizeleri ve diğer yerleşik türleri adlandırdığınız gibi bu işlevleri de adlandırmalısınız. Bu fonksiyonel programlamada bir tanımlayıcıyı değere bağlama olarak bilinir. F# değerlere isim bağlamak için let ifadeleri kullanır: let <identifier> = <value>. Aşağıdaki kod iki örnek gösterir.

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

Bir işleve kolayca ad verebilirsiniz. Aşağıdaki örnek squareIt isimli işlevi, squareIt tanımlayıcısını lambda ifadesi fun n -> n * n'e bağlayarak tanımlar. Işlev squareIt'in bir parametresi var, n, ve bu o parametrenin karesini döner.

let squareIt = fun n -> n * n

F# daha az sözdizimi ile aynı sonucu daha az yazarak elde etmek için aşağıdakileri sağlar.

let squareIt2 n = n * n

Örnekler işlevlerin ve diğer türlerin değerlerinin bildirimi arasındaki benzerlikleri vurgulamak için çoğunlukla ilk stili, let <function-name> = <lambda-expression> izliyor. Ancak, tüm adlandırılmış işlevler kısa sözdizimi ile de yazılabilir. Bazı örnekler her iki yolla da yazılmıştır.

Değeri Bir Veri Yapısında Saklayın

Bir ilk sınıf değeri veri yapısı içinde saklanabilir. Aşağıda değerleri listeler ve dizilerde saklayan kod örnekleri gösterilir.

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

Aşağıdaki örnek bir dizide saklanan işlev adının gerçekte bir işleve değerlendirildiğini doğrulamak için fst ve birinci ve ikinci öğeleri ayıklamak için funAndArgTuple dizisinden snd işleçlerini kullanır. Dizideki ilk öğe squareIt ve ikinci öğe ise num dir. Bir önceki örnekte tanımlayıcı num işlev squareIt için geçerli bir bağımsız değişken olan tamsayı 10'a bağlıdır. İkinci ifade kayıt düzenindeki ilk öğeyi kayıt düzenindeki 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'ın ve tamsayı 10'un birbirinin yerine kullanılabilmesi gibi tanımlayıcı squareIt ve lambda ifadesi fun n -> n * n de birbirinin yerine kullanılabilir.

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

Değeri Bir Değişken Olarak Geçirin

Eğer bir dilde değerin ilk sınıf durumu varsa bu değeri bir 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ındır. Aşağıdaki kod tamsayıların ve dizelerin F#'da bağımsız değişken olarak geçirilmesini 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)

Eğer işlevlerin ilk sınıf durumu varsa bunları aynı şekilde bağımsız değişken olarak geçirebilmeniz gerekir. Bunun daha yüksek sıralı işlevlerin ilk özelliği olduğunu unutmayın.

Aşağıdaki örnekte, işlev applyIt'in iki parametresi op ve arg vardır. Eğer op için tek parametresi olan bir işlev ve arg işlevi için uygun bir bağımsız değişken gönderirseniz, işlev op arg'a uygulanarak sonucu döner. Aşağıdaki örnekte, işlev bağımsız değişkeni ve tamsayı bağımsız değişkeni aynı şekilde, adları kullanılarak gönderilmiştir.

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

MAP veya filtre işlemleri gibi bir işlevi başka bir işleve bağımsız değişken olarak gönderme olanağı fonksiyonel programlama dillerinde bulunan ortak soyutlamaların önemini vurgular. MAP işlemi, örneğin, bir listeyi gözden geçirip, her öğeye bir şey yapan ve sonuçlar listesini dönen işlevler tarafından paylaşılan hesaplamaları yakalayan bir daha yüksek sıralı işlevdir. Bir listedeki tüm tamsayıları arttırmayı veya her öğenin karesini almayı veya dizelerin listesindeki her öğeyi büyük harfle değiştirmeyi isteyebilirsiniz. Hesaplamanın hataya yatkın olan kısmı listeyi baştan dolaşan ve dönülecek sonuçların listesini oluşturan özyinelemeli işlemdir. Bu bölüm eşleme işlevinde yakalanır. Tek yapmanız gereken belirli bir uygulama için listenin her öğesine tek tek uygulayacağınız bir işlev (ekleme, karesini alma, değiştirme, vb.) yazmak. Önceki örnekte, squareIt'in applyIt'e gönderildiği gibi o işlev bağımsız değişken olarak eşleme işlevine gönderilir.

F# listeler, diziler ve kümeler dahil olmak üzere çoğu koleksiyon türü için MAP yöntemlerini sağlar. Aşağıdaki örnekler listeleri kullanır. Sözdizimi 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. Listeleri (F#).

Işlev Çağrısı Değerini Döndür

Son olarak, eğer bir işlev bir dilde ilk sınıf durumunda ise, tamsayı ve dizeler gibi diğer türlerin döndüğü şekilde o işlevi bir işlevin çağrı sonucu olarak dönebilmeniz gerekir.

Aşağıdaki işlev çağrıları tamsayılar döner ve bunları 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()

Aşağıdaki satır içi tanımlanmış işlev çağrısı Boolean değeri döndürür. Görüntülenen değer True dur.

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

Bir işlevi, işlev çağrısının değeri olarak dönme yeteneği daha yüksek sıralı işlevlerin ikinci özelliğidir. Aşağıdaki örnekte, tek bir bağımsız değişken item alan checkFor işlevi tanımlanmış ve değerini yeni bir işlev olarak dönmüştür. Döndürülen işlev bağımsız değişkenlerini liste olarak alır, lst ve item için lst'te arama yapar. Eğer item varsa, işlev true döner. Eğer item yoksa, işlev false döner. Önceki bölümde olduğu gibi, aşağıdaki kod listeyi aramak için sağlanan liste işlevini List.exists kullanır.

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

Aşağıdaki kod checkFor bir bağımsız değişken, liste, alan bir işlev yaratır ve listede 7'yi arar.

// 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 F#'daki işlevlerin ilk sınıf durumlarını bir compose işlevi tanımlamak için kullanır ve iki bağımsız işlev değişkeninin birleşimini döndürür.

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

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

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

Not

Daha kısa bir sürüm için aşağıdaki bölüme bakınız: "Curried İşlevler"

Aşağıdaki kod, her ikisi de aynı türden tek bir bağımsız değişken alan iki işlevi, bağımsız değişken olarak compose'a gönderir. Dönüş değeri iki bağımsız işlev değişkeninin birleş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şlevleri birleştiren iki işleç sağlar, << ve >>.Örneğin, let squareAndDouble2 = doubleIt << squareIt önceki örnekteki let squareAndDouble = compose doubleIt squareIt'e eşdeğerdir.

İşlev çağrısının değeri olarak dönen aşağıdaki işlev örneği basit bir tahmin etme oyunu oluşturur. Oyunu oluşturmak için makeGame'i target birinin tahmin etmesini istediğiniz değer ile çağırın. Işlev makeGame'den dönen değer tek bir bağımsız değişken (tahmin) alan ve tahminin doğru olup olmadığını rapor eden 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 target için 7 değerini göndererek makeGame'i çağırır. Tanımlayıcı playGame döndürülen lambda ifadesine bağlıdır. Bu nedenle, playGame guess değerini bağımsız değişken olarak götüren bir 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 İşlevler

Önceki bölümdeki örneklerin çoğu, F# işlevi tanımlamalarında örtülü currying avantajı kullanılarak daha kısa yazılabilir. Currying birden fazla parametresi olan bir işlevi her biri tek bir parametreye sahip bir dizi katıştırılmış işlevlere dönüştüren bir işlemdir. F#'da birden çok parametre alan işlevler kendiliğinden curried haldedir. Örneğin, önceki bölümden compose aşağıda gösterildiği gibi üç parametre ile kısa stilde yazılabilir.

let compose4 op1 op2 n = op1 (op2 n)

Fakat, compose4curried'ta gösterildiği gibi

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

Bu işleve birçok yoldan erişebilirsiniz. Aşağıdaki her örnek 18 döner ve görüntüler. Herhangi bir örnekteki compose4'u compose4curried ile değiştirebilirsiniz.

// 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 hala önce olduğu gibi çalıştığını doğrulamak için orjinal test durumları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

Currying'i dizilerdeki parametreleri içine alarak sınırlayabilirsiniz.Daha fazla bilgi için bkz: "Parametre Desenleri" Parametreleri ve bağımsız değişkenler (F#)

Aşağıdaki örnek makeGame'in daha kısa bir sürümünü yazmak için örtülü currying kullanır. makeGame'in game işlevini nasıl oluşturduğunun ve döndürdüğünün detayları bu biçimde daha az açık fakat orjinal testleri kullanarak aynı sonucu verdiğini 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 bkz: "Değişkenlerin Kısmi Uygulaması" İşlevler (F#)

Tanımlayıcı ve İşlev Tanımı Birbiriyle Değiştirilebilir

Önceki örneklerde değişken adı num tamsayı 10'a değerlendirilir ve num'ın geçerli olması süpriz olmaz çünkü 10 da geçerli bir tamsayıdır. Aynısı işlev tanımlayıcıları ve onların değerleri için de geçerlidir: işlevin adının kullanabileceği herhangi bir yerde, bağlı olduğu lambda ifadesi de kullanılabilir.

Aşağıdaki örnek isNegative olarak adlandırılan bir Boolean işlevi tanımlar ve sonra işlevin adını ve tanımını birbirinin yerine kullanır. Sonraki tüm üç örnek False döner ve görüntüler.

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) 

Bir adım ileriye taşımak için bağlanan applyIt değerinin yerine applyIt'i koyun.

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

F#'da İlk Sınıf Değerleri İşlevleri

Önceki bölümlerdeki örnekler F#'daki işlevlerin, F#'da ilk sınıf değerleri olma ölçütlerini sağladığını göstermektedir:

  • İşlev tanımına bir tanımlayıcı bağlayabilirsiniz.

    let squareIt = fun n -> n * n
    
  • İşlevi bir veri yapısında saklayabilirsiniz.

    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 ]
    
  • İşlevi, bir işlev çağrısının değeri olarak dönebilirsiniz.

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

F# hakkında daha fazla bilgi için, bkz. Görsel F#, Visual Studio 2012 için yenilikler nelerdir? veya F# dil başvurusu

Örnek

Dd233158.collapse_all(tr-tr,VS.110).gifTanımlama

Aşağıdaki kod, bu konudaki tüm örnekleri içerir.

Dd233158.collapse_all(tr-tr,VS.110).gifKod


// ** GIVE THE VALUE A NAME **

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

let squareIt = fun n -> n * n

let squareIt2 n = n * n


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

// Lists.

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

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

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

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

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

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

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


// Tuples.

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

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

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

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

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

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

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

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


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

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

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

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

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

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

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

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

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

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

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

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


// ** CURRIED FUNCTIONS **

let compose4 op1 op2 n = op1 (op2 n)

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

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

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

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

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

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

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

let playGame2 = makeGame2 7
playGame2 2
playGame2 9
playGame2 7

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


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

let isNegative = fun n -> n < 0

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

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

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


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

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

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

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

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

Ayrıca bkz.

Başvuru

Dizilerini (F#)

İşlevler (F#)

Bağlar (F#) olanak sağlar

Lambda ifadeleri: Eğlenceli anahtar sözcüğü (F#)

Diğer Kaynaklar

Listeleri (F#)