Menggunakan fungsi di F#

Definisi fungsi sederhana menyerupai berikut ini:

let f x = x + 1

Di contoh sebelumnya, nama fungsi adalah f, argumennya adalah x, yang memiliki jenis int, bagian isi fungsi adalah x + 1, dan nilai yang ditampilkan berjenis int.

Karakteristik yang menentukan dari F# adalah bahwa fungsi tersebut memiliki status kelas satu. Anda dapat melakukan dengan fungsi apa pun yang dapat Anda lakukan dengan nilai jenis bawaan lainnya, dengan tingkat usaha yang sebanding.

  • Anda dapat memberikan nama pada nilai fungsi.

  • Anda dapat menyimpan fungsi dalam struktur data, misalnya dalam bentuk daftar.

  • Anda dapat meneruskan fungsi sebagai argumen dalam panggilan fungsi.

  • Anda dapat mengembalikan fungsi dari panggilan fungsi.

Beri Nama Nilai

Jika fungsi adalah nilai kelas satu, Anda seharusnya dapat menamainya, sama seperti Anda dapat memberi nama bilangan bulat, string, dan jenis bawaan lainnya. Ini disebut dalam literatur pemrograman fungsional sebagai pengikatan pengidentifikasi ke nilai. F# menggunakan let pengikatan untuk mengikat nama ke nilai: let <identifier> = <value>. Kode berikut menunjukkan dua contoh.

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

Anda dapat memberi nama fungsi dengan mudah. Contoh berikut mendefinisikan fungsi bernama squareIt dengan mengikat pengidentifikasi squareIt ke ekspresi lambdafun n -> n * n. squareIt Fungsi memiliki satu parameter, n, dan mengembalikan kuadrat dari parameter tersebut.

let squareIt = fun n -> n * n

F# menyediakan sintaks lebih ringkas berikut untuk mencapai hasil yang sama dengan pengetikan yang lebih sedikit.

let squareIt2 n = n * n

Contoh yang mengikuti sebagian besar menggunakan gaya pertama, let <function-name> = <lambda-expression>, untuk menekankan kesamaan antara deklarasi fungsi dan deklarasi dari jenis nilai lainnya. Namun, semua fungsi bernama juga dapat ditulis dengan sintaks yang ringkas. Beberapa contoh ditulis dengan kedua cara tersebut.

Menyimpan Nilai dalam Struktur Data

Nilai kelas satu dapat disimpan dalam struktur data. Kode berikut menunjukkan contoh penyimpanan nilai dalam daftar dan dalam tupel.

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

Untuk memverifikasi bahwa nama fungsi yang disimpan dalam tupel sebenarnya mengevaluasi ke fungsi, contoh berikut menggunakan operator fst dan snd untuk mengekstrak elemen pertama dan kedua dari tupel funAndArgTuple. Elemen pertama dalam tupel adalah squareIt dan elemen kedua adalah num. Pengidentifikasi num terikat dalam contoh sebelumnya ke bilangan bulat 10, argumen yang valid untuk fungsi squareIt. Ekspresi kedua menerapkan elemen pertama dalam tupel ke elemen kedua di dalam tupel: 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))

Demikian pula, sama seperti pengidentifikasi num dan bilangan bulat 10 dapat digunakan secara bergantian, begitu pula pengidentifikasi squareIt dan ekspresi 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))

Meneruskan Nilai sebagai Argumen

Jika nilai memiliki status kelas satu dalam bahasa pemrogram, Anda dapat meneruskannya sebagai argumen ke fungsi. Misalnya, adalah umum untuk meneruskan bilangan bulat dan string sebagai argumen. Kode berikut menunjukkan bilangan bulat dan string yang diteruskan sebagai argumen di 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)

Jika fungsi memiliki status kelas satu, Anda seharusnya dapat meneruskannya sebagai argumen dengan cara yang sama. Ingatlah bahwa ini adalah karakteristik pertama dari fungsi tingkat tinggi.

Dalam contoh berikut, fungsi applyIt memiliki dua parameter, op dan arg. Jika Anda mengirim fungsi yang memiliki satu parameter untuk op dan argumen yang sesuai untuk fungsi ke arg, fungsi mengembalikan hasil penerapan op ke arg. Dalam contoh berikut, argumen fungsi dan argumen bilangan bulat dikirim dengan cara yang sama, dengan menggunakan namanya.

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

Kemampuan untuk mengirim fungsi sebagai argumen ke fungsi lain mendasari abstraksi umum dalam bahasa pemrograman fungsional, seperti operasi peta atau filter. Operasi peta, misalnya, adalah fungsi tingkat tinggi yang menangkap komputasi yang dibagikan oleh fungsi yang menelusuri daftar, melakukan sesuatu pada setiap elemen, lalu mengembalikan daftar hasilnya. Anda mungkin ingin menambah setiap elemen dalam daftar bilangan bulat, atau untuk mengkuadratkan setiap elemen, atau mengubah setiap elemen dalam daftar string menjadi huruf besar. Bagian yang rawan kesalahan dari komputasi adalah proses rekursif yang menelusuri daftar dan menyusun daftar hasil yang akan dikembalikan. Bagian itu diambil dalam fungsi pemetaan. Yang harus Anda tulis untuk aplikasi tertentu adalah fungsi yang ingin Anda terapkan ke setiap elemen daftar satu per satu (menambahkan, mengkuadratkan, mengubah kasus). Fungsi tersebut dikirim sebagai argumen ke fungsi pemetaan, sama seperti squareIt yang dikirim ke applyIt pada contoh sebelumnya.

F# menyediakan metode peta untuk sebagian besar jenis koleksi, termasuk daftar, array, dan urutan. Contoh berikut menggunakan daftar. Sintaksnya adalah 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

Untuk informasi selengkapnya, lihat Daftar.

Mengembalikan Nilai dari Panggilan Fungsi

Terakhir, jika fungsi memiliki status kelas satu dalam bahasa pemrogram, Anda harus dapat mengembalikannya sebagai nilai panggilan fungsi, sama seperti saat mengembalikan jenis lain, seperti bilangan bulat dan string.

Fungsi berikut memanggil bilangan bulat yang kembali dan menampilkannya.

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

Panggilan fungsi berikut memanggil pengembalian string.

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

Panggilan fungsi berikut, yang dinyatakan sebaris, mengembalikan nilai Boolean. Nilai yang ditampilkan adalah True.

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

Kemampuan untuk mengembalikan fungsi sebagai nilai panggilan fungsi adalah karakteristik kedua dari fungsi tingkat tinggi. Dalam contoh berikut, checkFor didefinisikan sebagai fungsi yang mengambil satu argumen, item, dan mengembalikan fungsi baru sebagai nilainya. Fungsi yang dikembalikan mengambil daftar sebagai argumennya, lst, dan mencari item di lst. Jika item ada, fungsi mengembalikan true. Jika item tidak ada, fungsi mengembalikan false. Seperti pada bagian sebelumnya, kode berikut menggunakan fungsi daftar yang disediakan, List.exists, untuk mencari daftar.

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

Kode berikut menggunakan checkFor untuk membuat fungsi baru yang mengambil satu argumen, daftar, dan mencari 7 di dalam daftar.

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

Contoh berikut menggunakan status kelas satu dari fungsi di F# untuk mendeklarasikan fungsi, compose, yang mengembalikan komposisi dua argumen fungsi.

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

Catatan

Untuk versi yang lebih pendek, lihat bagian berikut, "Fungsi Curried".

Kode berikut mengirimkan dua fungsi sebagai argumen ke compose, yang keduanya mengambil satu argumen dari jenis yang sama. Nilai yang dikembalikan adalah fungsi baru yang merupakan komposisi dari dua argumen fungsi.

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

Catatan

F# menyediakan dua operator, << dan >>, yang menyusun fungsi. Misalnya, let squareAndDouble2 = doubleIt << squareIt setara dengan let squareAndDouble = compose doubleIt squareIt di contoh sebelumnya.

Contoh berikut mengembalikan fungsi sebagai nilai panggilan fungsi membuat permainan menebak sederhana. Untuk membuat game, panggil makeGame dengan nilai yang Anda ingin seseorang tebak dikirim untuk target. Nilai yang dikembalikan dari fungsi makeGame adalah fungsi yang mengambil satu argumen (tebakan) dan melaporkan apakah tebakan tersebut benar.

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

Kode berikut memanggil makeGame, mengirim nilai 7 untuk target. playGame Pengidentifikasi terikat ke ekspresi lambda yang dikembalikan. Oleh karena itu, playGame adalah fungsi yang mengambil sebagai satu argumennya nilai untuk 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!

Fungsi Curried

Banyak contoh di bagian sebelumnya dapat ditulis lebih ringkas dengan memanfaatkan implisit currying dalam deklarasi fungsi F#. Currying adalah proses yang mengubah sebuah fungsi yang memiliki lebih dari satu parameter menjadi serangkaian fungsi yang disematkan, yang masing-masing memiliki satu parameter. Dalam F#, fungsi yang memiliki lebih dari satu parameter secara inheren curried. Misalnya, compose dari bagian sebelumnya dapat ditulis seperti yang ditunjukkan dalam gaya ringkas berikut, dengan tiga parameter.

let compose4 op1 op2 n = op1 (op2 n)

Namun, hasilnya adalah fungsi dari satu parameter yang mengembalikan fungsi dari satu parameter yang pada gilirannya mengembalikan fungsi lain dari satu parameter, seperti yang ditunjukkan dalam compose4curried.

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

Anda dapat mengakses fungsi ini dengan beberapa cara. Setiap contoh berikut mengembalikan dan menampilkan 18. Anda dapat mengganti compose4 dengancompose4curried di salah satu contoh.

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

Untuk memverifikasi bahwa fungsi masih berfungsi seperti sebelumnya, coba lagi kasus pengujian asli.

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)

Catatan

Anda dapat membatasi currying dengan menutup parameter dalam tupel. Untuk informasi selengkapnya, lihat "Pola Parameter" di Parameter dan Argumen.

Contoh berikut menggunakan currying implisit untuk menulis versi yang lebih pendek dari makeGame. Detail tentang bagaimana makeGame mengonstruksi dan mengembalikan game fungsi kurang eksplisit dalam format ini, tetapi Anda dapat memverifikasi dengan menggunakan kasus pengujian asli bahwa hasilnya sama.

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'

Untuk informasi selengkapnya tentang currying, lihat "Aplikasi Parsial dari Argumen" di Fungsi.

Pengidentifikasi dan Definisi Fungsi Dapat Dipertukarkan

Nama variabel num dalam contoh sebelumnya mengevaluasi ke bilangan bulat 10, dan tidak mengherankan bahwa jika num valid, 10 juga valid. Hal yang sama berlaku untuk pengidentifikasi fungsi dan nilainya: di mana pun nama fungsi dapat digunakan, ekspresi lambda yang terikat dapat digunakan.

Contoh berikut mendefinisikan fungsi Boolean yang disebut isNegative, lalu menggunakan nama fungsi dan definisi fungsi secara bergantian. Tiga contoh selanjutnya semua mengembalikan dan menampilkan 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)

Untuk melangkah lebih jauh, ganti nilai yang applyIt terikat dengan applyIt.

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

Fungsi Adalah Nilai Kelas Satu di F#

Contoh di bagian sebelumnya menunjukkan bahwa fungsi di F# memenuhi kriteria untuk menjadi nilai kelas satu di F#:

  • Anda dapat mengikat pengidentifikasi ke definisi fungsi.
let squareIt = fun n -> n * n
  • Anda dapat menyimpan fungsi dalam struktur data.
let funTuple2 = ( BMICalculator, fun n -> n * n )
  • Anda dapat meneruskan fungsi sebagai argumen.
let increments = List.map (fun n -> n + 1) [ 1; 2; 3; 4; 5; 6; 7 ]
  • Anda dapat mengembalikan fungsi sebagai nilai panggilan fungsi.
let checkFor item =
    let functionToReturn = fun lst ->
                           List.exists (fun a -> a = item) lst
    functionToReturn

Untuk informasi selengkapnya tentang F#, lihat Referensi Bahasa Pemrogram F#.

Contoh

Deskripsi

Kode berikut berisi semua contoh dalam topik ini.

Kode

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

Lihat juga