다음을 통해 공유


F에서 함수 사용#

간단한 함수 정의 는 다음과 유사합니다.

let f x = x + 1

앞의 예제에서 함수 이름은 f이고, 인수는 x이고 그 형식은 int이며, 함수 본문은 x + 1이고, 반환 값의 형식은 int입니다.

F#의 특징은 함수에 일류 상태 있다는 것입니다. 비슷한 수준의 노력으로 다른 기본 제공 형식의 값으로 수행할 수 있는 모든 작업을 함수로 수행할 수 있습니다.

  • 함수 값 이름을 지정할 수 있습니다.

  • 목록과 같은 데이터 구조에 함수를 저장할 수 있습니다.

  • 함수 호출에서 함수를 인수로 전달할 수 있습니다.

  • 함수 호출에서 함수를 반환할 수 있습니다.

값에 이름 지정

함수가 일류 값인 경우 정수, 문자열 및 기타 기본 제공 형식의 이름을 지정할 수 있는 것처럼 이름을 지정할 수 있어야 합니다. 이를 기능 프로그래밍 문헌에서 식별자를 값에 바인딩하는 것으로 지칭합니다. F#에서는 바인딩을 사용하여 let 이름을 값에 바인딩합니다let <identifier> = <value>. 다음 코드에서는 두 가지 예를 보여 줍니다.

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

함수의 이름을 쉽게 지정할 수 있습니다. 다음 예제에서는 식별자를 squareIt 람다 식fun n -> n * n에 바인딩하여 명명 squareIt 된 함수를 정의합니다. 함수 squareIt 에는 하나의 매개 변수 n가 있으며 해당 매개 변수의 제곱을 반환합니다.

let squareIt = fun n -> n * n

F#에서는 입력을 줄여 동일한 결과를 얻기 위해 다음과 같은 보다 간결한 구문을 제공합니다.

let squareIt2 n = n * n

다음 예제에서는 주로 첫 번째 스타일을 let <function-name> = <lambda-expression>사용하여 함수 선언과 다른 형식의 값 선언 간의 유사성을 강조합니다. 그러나 명명된 모든 함수는 간결한 구문을 사용하여 작성할 수도 있습니다. 일부 예제는 두 가지 방법으로 작성됩니다.

데이터 구조에 값 저장

일류 값은 데이터 구조에 저장할 수 있습니다. 다음 코드는 목록 및 튜플에 값을 저장하는 예제를 보여 줍니다.

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

튜플에 저장된 함수 이름이 실제로 함수로 평가되는지 확인하기 위해 다음 예제에서는 및 snd 연산자를 사용하여 fst 튜플funAndArgTuple에서 첫 번째 및 두 번째 요소를 추출합니다. 튜플 squareIt 의 첫 번째 요소는 이고 두 번째 요소는 .입니다 num. 식별자는 num 이전 예제에서 함수의 유효한 인수인 정수 10에 squareIt 바인딩됩니다. 두 번째 식은 튜플의 첫 번째 요소를 튜플 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))

마찬가지로 식별자 num 및 정수 10과 마찬가지로 서로 바꿔서 사용할 수 있으므로 식별자와 squareIt 람다 식을 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))

값을 인수로 전달

값에 언어의 첫 번째 클래스 상태 있는 경우 함수에 인수로 전달할 수 있습니다. 예를 들어 정수 및 문자열을 인수로 전달하는 것이 일반적입니다. 다음 코드는 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)

함수에 첫 번째 클래스 상태 있는 경우 동일한 방식으로 인수로 전달할 수 있어야 합니다. 이것이 상위 함수의 첫 번째 특성입니다.

다음 예제에서 함수 applyIt 에는 두 개의 매개 변수 oparg. 매개 변수 op 가 하나 있고 함수에 적절한 인수가 있는 함수를 arg보내면 함수는 적용 결과를 반환합니다 oparg. 다음 예제에서는 함수 인수와 정수 인수가 모두 이름을 사용하여 동일한 방식으로 전송됩니다.

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

함수를 인수로 다른 함수에 보내는 기능은 지도 또는 필터 작업과 같은 함수 프로그래밍 언어의 일반적인 추상화의 기초가 됩니다. 예를 들어 맵 작업은 목록을 단계별로 실행하고 각 요소에 대해 작업을 수행한 다음 결과 목록을 반환하는 함수에서 공유하는 계산을 캡처하는 상위 함수입니다. 정수 목록의 각 요소를 증가하거나 각 요소를 정사각형으로 지정하거나 문자열 목록의 각 요소를 대문자로 변경할 수 있습니다. 계산에서 오류가 발생하기 쉬운 부분은 목록을 단계별로 실행하고 반환할 결과 목록을 작성하는 재귀 프로세스입니다. 해당 부분은 매핑 함수에서 캡처됩니다. 특정 애플리케이션에 대해 작성해야 하는 것은 각 목록 요소에 개별적으로 적용하려는 함수입니다(대/소문자 추가, 제곱, 변경). 이 함수는 이전 예제에서 보낸 것처럼 매핑 함수에 applyIt 대한 인수로 squareIt 전송됩니다.

F#은 목록, 배열 및 시퀀스를 포함하여 대부분의 컬렉션 형식에 대한 맵 메서드를 제공합니다. 다음 예제에서는 목록을 사용합니다. 구문은 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

자세한 내용은 목록을 참조 하세요.

함수 호출에서 값 반환

마지막으로, 함수에 언어의 일류 상태 있는 경우 정수 및 문자열과 같은 다른 형식을 반환하는 것처럼 함수 호출의 값으로 반환할 수 있어야 합니다.

다음 함수 호출은 정수 반환 및 표시를 호출합니다.

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

다음 함수 호출은 문자열을 반환합니다.

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

인라인으로 선언된 다음 함수 호출은 부울 값을 반환합니다. 표시되는 값은 .입니다 True.

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

함수 호출의 값으로 함수를 반환하는 기능은 상위 함수의 두 번째 특성입니다. 다음 예제 checkFor 에서는 하나의 인수 item를 사용하고 새 함수를 해당 값으로 반환하는 함수로 정의됩니다. 반환된 함수는 목록을 인수 lstitem 로 사용하고 검색합니다lst. 있는 경우 item 함수는 .를 반환합니다 true. 이 함수가 없으면 item 함수가 반환됩니다 false. 이전 섹션에서와 같이 다음 코드는 제공된 목록 함수인 List.exists를 사용하여 목록을 검색합니다.

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

다음 코드는 하나의 인수, 목록을 사용하고 목록에서 7을 검색하는 새 함수를 만드는 데 사용합니다 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)

다음 예제에서는 F#에서 함수의 첫 번째 클래스 상태 사용하여 두 함수 인수의 컴퍼지션을 반환하는 함수compose를 선언합니다.

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

참고 항목

더 짧은 버전은 다음 섹션인 "Curried Functions"를 참조하세요.

다음 코드는 두 함수를 인수 compose로 보냅니다. 둘 다 동일한 형식의 단일 인수를 사용합니다. 반환 값은 두 함수 인수의 컴퍼지션인 새 함수입니다.

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

참고 항목

F#은 함수를 >>구성하는 두 연산자와 두 개의 연 << 산자를 제공합니다. 예를 들어 이전 let squareAndDouble2 = doubleIt << squareIt 예제와 동일합니다 let squareAndDouble = compose doubleIt squareIt .

함수 호출의 값으로 함수를 반환하는 다음 예제에서는 간단한 추측 게임을 만듭니다. 게임을 만들려면 누군가가 추측target할 값을 사용하여 호출 makeGame 합니다. 함수의 반환 값은 하나의 인수(추측)를 사용하고 추측이 올바른지 여부를 보고하는 함수 makeGame 입니다.

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

다음 코드는 에 대한 값을 7 전송하여 호출makeGame합니다target. 식별자는 playGame 반환된 람다 식에 바인딩됩니다. 따라서 playGame 하나의 인수로 값을 사용하는 함수입니다 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!

Curried 함수

이전 섹션의 많은 예제는 F# 함수 선언에서 암시적 커리를 활용하여 보다 간결하게 작성할 수 있습니다. Currying은 둘 이상의 매개 변수가 있는 함수를 각각 단일 매개 변수가 있는 일련의 포함된 함수로 변환하는 프로세스입니다. F#에서는 매개 변수가 두 개 이상 있는 함수는 기본적으로 커리가 됩니다. 예를 들어 이전 compose 섹션의 세 가지 매개 변수를 사용하여 다음 간결한 스타일에 표시된 대로 작성할 수 있습니다.

let compose4 op1 op2 n = op1 (op2 n)

그러나 결과는 한 매개 변수의 함수를 반환하는 한 매개 변수의 함수로, compose4curried한 매개 변수의 다른 함수를 반환합니다.

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

이 함수는 여러 가지 방법으로 액세스할 수 있습니다. 다음 예제 각각은 18을 반환하고 표시합니다. 어떤 예제에서도 바꿀 compose4compose4curried 수 있습니다.

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

참고 항목

튜플에 매개 변수를 묶어 커리를 제한할 수 있습니다. 자세한 내용은 매개 변수 및 인수"매개 변수 패턴"을 참조하세요.

다음 예제에서는 암시적 커리를 사용하여 더 짧은 버전의 을 작성합니다 makeGame. 함수를 구문 및 반환 game 하는 방법에 makeGame 대한 세부 정보는 이 형식에서 덜 명시적이지만 원래 테스트 사례를 사용하여 결과가 동일한지 확인할 수 있습니다.

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'

커리에 대한 자세한 내용은 Functions의 "인수 부분 적용" 을 참조하세요.

식별자 및 함수 정의는 서로 교환할 수 있습니다.

이전 예제의 변수 이름은 num 정수 10으로 계산되며 유효한 위치 num , 10도 유효하다는 것은 놀라운 일이 아닙니다. 함수 식별자와 해당 값도 마찬가지입니다. 함수의 이름을 사용할 수 있는 모든 곳에서 바인딩된 람다 식을 사용할 수 있습니다.

다음 예제에서는 호출isNegative된 함수를 Boolean 정의한 다음 함수의 이름과 함수 정의를 서로 바꿔서 사용합니다. 다음 세 가지 예제는 모두 반환되고 표시됩니다 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)

한 단계 더 나아가려면 바인딩된 applyIt 값을 대체합니다 applyIt.

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

함수는 F의 첫 번째 클래스 값입니다.#

이전 섹션의 예제에서는 F#의 함수가 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

F#에 대한 자세한 내용은 F# 언어 참조를 참조하세요.

예제

설명

다음 코드에는 이 항목의 모든 예제가 포함되어 있습니다.

코드

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

참고 항목