일급 함수First-class functions

함수형 프로그래밍 언어의 특성을 정의 하는 것은 함수를 첫 번째 클래스 상태로 승격 하는 것입니다.A defining characteristic of functional programming languages is the elevation of functions to first-class status. 다른 기본 제공 형식의 값으로 수행할 수 있는 함수를 사용 하 여이 작업을 수행할 수 있어야 하 고, 비슷한 노력으로이 작업을 수행할 수 있어야 합니다.You should be able to do with a function whatever you can do with values of the other built-in types, and be able to do so with a comparable degree of effort.

첫 번째 클래스 상태의 일반적인 측정값은 다음과 같습니다.Typical measures of first-class status include the following:

  • 함수를 식별자에 바인딩할 수 있나요?Can you bind functions to identifiers? 즉, 이름을 지정할 수 있나요?That is, can you give them names?

  • 함수를 데이터 구조 (예: 목록)에 저장할 수 있나요?Can you store functions in data structures, such as in a list?

  • 함수 호출에서 함수를 인수로 전달할 수 있나요?Can you pass a function as an argument in a function call?

  • 함수 호출에서 함수를 반환할 수 있나요?Can you return a function from a function call?

마지막 두 측정값은 고차 작업 또는 고차 함수라고 하는 항목을 정의 합니다.The last two measures define what are known as higher-order operations or higher-order functions. 고차 함수는 함수를 인수로 받아들이고 함수 호출 값으로 함수를 반환 합니다.Higher-order functions accept functions as arguments and return functions as the value of function calls. 이러한 작업은 함수를 매핑하고 함수를 구성 하는 등의 함수형 프로그래밍 개체인 지원 합니다.These operations support such mainstays of functional programming as mapping functions and composition of functions.

값에 이름을 지정 합니다.Give the Value a Name

함수가 첫 번째 클래스 값 이면 정수, 문자열 및 기타 기본 제공 형식의 이름을 지정할 때와 마찬가지로 이름을 지정할 수 있어야 합니다.If a function is a first-class value, you must be able to name it, just as you can name integers, strings, and other built-in types. 이는 함수 프로그래밍 자료에서 값에 식별자를 바인딩하는 것으로 간주 됩니다.This is referred to in functional programming literature as binding an identifier to a value. F# let 바인딩을 사용 하 여 let <identifier> = <value>이름을 값에 바인딩합니다.F# uses let bindings to bind names to values: let <identifier> = <value>. 다음 코드에서는 두 가지 예를 보여 줍니다.The following code shows two examples.

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

함수 이름을 쉽게 지정할 수 있습니다.You can name a function just as easily. 다음 예제 squareIt 에서는 식별자 squareIt람다 식 fun n -> n * n에 바인딩하여 이라는 함수를 정의 합니다.The following example defines a function named squareIt by binding the identifier squareIt to the lambda expression fun n -> n * n. 함수 squareIt 는 하나의 n매개 변수를 포함 하며 해당 매개 변수의 제곱을 반환 합니다.Function squareIt has one parameter, n, and it returns the square of that parameter.

let squareIt = fun n -> n * n

F#에서는 입력이 적고 동일한 결과를 얻기 위해 다음과 같은 보다 간결한 구문을 제공 합니다.F# provides the following more concise syntax to achieve the same result with less typing.

let squareIt2 n = n * n

다음에 나오는 예제에서는 대개 첫 번째 스타일 let <function-name> = <lambda-expression>을 사용 하 여 함수 선언과 다른 형식의 값 선언 간의 유사성을 강조 합니다.The examples that follow mostly use the first style, let <function-name> = <lambda-expression>, to emphasize the similarities between the declaration of functions and the declaration of other types of values. 그러나 모든 명명 된 함수를 간결한 구문으로 작성할 수도 있습니다.However, all the named functions can also be written with the concise syntax. 일부 예제는 두 가지 방법으로 작성 됩니다.Some of the examples are written in both ways.

데이터 구조에 값 저장Store the Value in a Data Structure

데이터 구조에는 첫 번째 클래스 값을 저장할 수 있습니다.A first-class value can be stored in a data structure. 다음 코드에서는 목록 및 튜플에 값을 저장 하는 예제를 보여 줍니다.The following code shows examples that store values in lists and in tuples.

// Lists.

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

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

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

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

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

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

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


// Tuples.

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

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

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

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

튜플에 저장 된 함수 이름이 실제로 함수를 계산 하는지 확인 하기 위해 다음 예제에서는 fstsnd 연산자를 사용 하 여 튜플의 funAndArgTuple첫 번째와 두 번째 요소를 추출 합니다.To verify that a function name stored in a tuple does in fact evaluate to a function, the following example uses the fst and snd operators to extract the first and second elements from tuple funAndArgTuple. 튜플의 첫 번째 요소는이 squareIt 고 두 번째 num요소는입니다.The first element in the tuple is squareIt and the second element is num. 식별자 num 는 이전 예제에서 squareIt 함수에 대 한 유효한 인수인 정수 10에 바인딩됩니다.Identifier num is bound in a previous example to integer 10, a valid argument for the squareIt function. 두 번째 식은 튜플의 첫 번째 요소를 튜플의 squareIt num두 번째 요소에 적용 합니다.The second expression applies the first element in the tuple to the second element in the tuple: squareIt num.

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

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

마찬가지로 식별자 num 와 정수 10은 서로 바꿔 사용할 수 있으므로 식별자 squareIt 와 람다 식을 fun n -> n * n사용할 수 있습니다.Similarly, just as identifier num and integer 10 can be used interchangeably, so can identifier squareIt and lambda expression 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))

값을 인수로 전달 합니다.Pass the Value as an Argument

값이 언어의 첫 번째 클래스 상태 이면 해당 값을 함수에 인수로 전달할 수 있습니다.If a value has first-class status in a language, you can pass it as an argument to a function. 예를 들어 정수 및 문자열을 인수로 전달 하는 것이 일반적입니다.For example, it is common to pass integers and strings as arguments. 다음 코드에서는에서 F#인수로 전달 되는 정수 및 문자열을 보여 줍니다.The following code shows integers and strings passed as arguments in F#.

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

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

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

함수에 최고 수준의 상태가 있는 경우 동일한 방식으로 해당 함수를 인수로 전달할 수 있어야 합니다.If functions have first-class status, you must be able to pass them as arguments in the same way. 이는 고차 함수의 첫 번째 특징입니다.Remember that this is the first characteristic of higher-order functions.

다음 예제에서 함수 applyIt 에는 oparg라는 두 개의 매개 변수가 있습니다.In the following example, function applyIt has two parameters, op and arg. 에 대 op 한 매개 변수 하나를 포함 하는 함수 및에 arg함수에 대 한 적절 한 인수를 보내면 함수는에 arg적용 op 된 결과를 반환 합니다.If you send in a function that has one parameter for op and an appropriate argument for the function to arg, the function returns the result of applying op to arg. 다음 예제에서 함수 인수와 정수 인수는 모두 해당 이름을 사용 하 여 동일한 방식으로 전송 됩니다.In the following example, both the function argument and the integer argument are sent in the same way, by using their names.

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

함수를 다른 함수에 인수로 보내는 기능은 맵 또는 필터 작업과 같은 함수형 프로그래밍 언어의 일반적인 추상화를 기반으로 합니다.The ability to send a function as an argument to another function underlies common abstractions in functional programming languages, such as map or filter operations. 예를 들어, 맵 작업은 목록을 단계별로 실행 하는 함수에서 공유 하는 계산을 캡처하고 각 요소에 대 한 작업을 수행한 다음 결과 목록을 반환 하는 고차 함수입니다.A map operation, for example, is a higher-order function that captures the computation shared by functions that step through a list, do something to each element, and then return a list of the results. 정수 목록의 각 요소를 증가 시키거나 각 요소를 제곱 하거나 문자열 목록의 각 요소를 대문자로 변경 하는 것이 좋습니다.You might want to increment each element in a list of integers, or to square each element, or to change each element in a list of strings to uppercase. 오류의 발생 가능성이 가장 많은 부분은 목록을 단계별로 안내 하 고 반환할 결과 목록을 작성 하는 재귀 프로세스입니다.The error-prone part of the computation is the recursive process that steps through the list and builds a list of the results to return. 이 부분은 매핑 함수에서 캡처됩니다.That part is captured in the mapping function. 특정 응용 프로그램에 대 한 모든 쓰기는 각 목록 요소에 개별적으로 적용 하는 함수입니다 (대/소문자를 추가, 제곱, 변경).All you have to write for a particular application is the function that you want to apply to each list element individually (adding, squaring, changing case). 이 함수는 이전 예제의로 squareIt applyIt 전송 되는 것과 마찬가지로 매핑 함수에 인수로 전송 됩니다.That function is sent as an argument to the mapping function, just as squareIt is sent to applyIt in the previous example.

F#목록, 배열시퀀스를 비롯 한 대부분의 컬렉션 형식에 대 한 맵 메서드를 제공 합니다.F# provides map methods for most collection types, including lists, arrays, and sequences. 다음 예에서는 목록을 사용 합니다.The following examples use lists. 구문은 List.map <the function> <the list>입니다.The syntax is List.map <the function> <the list>.

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

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

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

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

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

자세한 내용은 목록을 참조 하십시오.For more information, see Lists.

함수 호출에서 값 반환Return the Value from a Function Call

마지막으로 함수에 언어의 첫 번째 클래스 상태가 있는 경우 정수 및 문자열과 같은 다른 형식을 반환 하는 것 처럼 함수 호출의 값으로이를 반환할 수 있어야 합니다.Finally, if a function has first-class status in a language, you must be able to return it as the value of a function call, just as you return other types, such as integers and strings.

다음 함수는 반환 정수를 호출 하 고 표시 합니다.The following function calls return integers and display them.

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

인라인으로 선언 된 다음 함수 호출은 부울 값을 반환 합니다.The following function call, declared inline, returns a Boolean value. 표시 되는 값 True은입니다.The value displayed is True.

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

함수 호출의 값으로 함수를 반환 하는 기능은 고차 함수의 두 번째 특징입니다.The ability to return a function as the value of a function call is the second characteristic of higher-order functions. 다음 예제 checkFor 에서는 하나의 item인수를 사용 하 고 새 함수를 해당 값으로 반환 하는 함수로 정의 됩니다.In the following example, checkFor is defined to be a function that takes one argument, item, and returns a new function as its value. 반환 된 함수는 목록을 인수로 lst사용 하 고 item 에서 lst을 검색 합니다.The returned function takes a list as its argument, lst, and searches for item in lst. 이 있으면이 함수는를 반환 true합니다. itemIf item is present, the function returns true. 가 없으면이 함수는를 반환 false합니다. itemIf item is not present, the function returns false. 이전 단원에서와 같이 다음 코드는 제공 된 목록 함수인 list. exists를 사용 하 여 목록을 검색 합니다.As in the previous section, the following code uses a provided list function, List.exists, to search the list.

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

다음 코드에서는를 checkFor 사용 하 여 하나의 인수를 사용 하 고 목록에서 7을 검색 하는 새 함수를 만듭니다.The following code uses checkFor to create a new function that takes one argument, a list, and searches for 7 in the list.

// 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함수 인수의 컴퍼지션을 반환 하는 함수를 선언 합니다.The following example uses the first-class status of functions in F# to declare a function, compose, that returns a composition of two function arguments.

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

참고

더 짧은 버전의 경우 "커리 된 함수" 섹션을 참조 하세요.For an even shorter version, see the following section, "Curried Functions."

다음 코드에서는 두 개의 함수를에 compose인수로 보내고, 둘 다 동일한 형식의 단일 인수를 사용 합니다.The following code sends two functions as arguments to compose, both of which take a single argument of the same type. 반환 값은 두 함수 인수의 컴퍼지션 인 새 함수입니다.The return value is a new function that is a composition of the two function arguments.

// 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#는 함수를 구성 <<>>는 및 라는 두 개의 연산자를 제공 합니다.F# provides two operators, << and >>, that compose functions. let squareAndDouble2 = doubleIt << squareIt 를 들어는 이전 예제 let squareAndDouble = compose doubleIt squareIt 에서와 동일 합니다.For example, let squareAndDouble2 = doubleIt << squareIt is equivalent to let squareAndDouble = compose doubleIt squareIt in the previous example.

함수 호출의 값으로 함수를 반환 하는 다음 예제에서는 간단한 추측 게임을 만듭니다.The following example of returning a function as the value of a function call creates a simple guessing game. 게임을 만들려면 다른 사람이 추측 makeGame target하려는 값을 사용 하 여를 호출 합니다.To create a game, call makeGame with the value that you want someone to guess sent in for target. 함수의 makeGame 반환 값은 한 인수 (추측)를 사용 하 여 guess가 정확한 지 여부를 보고 하는 함수입니다.The return value from function makeGame is a function that takes one argument (the guess) and reports whether the guess is correct.

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

다음 코드는를 makeGame호출 하 여에 7target한 값을 보냅니다.The following code calls makeGame, sending the value 7 for target. 식별자 playGame 가 반환 된 람다 식에 바인딩되어 있습니다.Identifier playGame is bound to the returned lambda expression. 따라서는 하나의 인수를에 대 guess한 값으로 사용 하는 함수입니다. playGameTherefore, playGame is a function that takes as its one argument a value for 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 Functions

이전 섹션의 많은 예제는 함수 선언에서 F# 암시적 currying 를 활용 하 여 더 간결 하 게 작성할 수 있습니다.Many of the examples in the previous section can be written more concisely by taking advantage of the implicit currying in F# function declarations. Currying는 둘 이상의 매개 변수를 포함 하는 함수를 일련의 포함 된 함수로 변환 하는 프로세스입니다. 각 함수에는 단일 매개 변수가 있습니다.Currying is a process that transforms a function that has more than one parameter into a series of embedded functions, each of which has a single parameter. 에서 F#둘 이상의 매개 변수가 있는 함수는 기본적으로 커리 됩니다.In F#, functions that have more than one parameter are inherently curried. 예를 들어 compose 이전 섹션에서는 다음의 간결한 스타일과 같이 세 개의 매개 변수를 사용 하 여 작성할 수 있습니다.For example, compose from the previous section can be written as shown in the following concise style, with three parameters.

let compose4 op1 op2 n = op1 (op2 n)

그러나 결과는에 compose4curried표시 된 것과 같이 한 매개 변수의 다른 함수를 반환 하는 하나의 매개 변수 함수를 반환 하는 하나의 매개 변수에 대 한 함수입니다.However, the result is a function of one parameter that returns a function of one parameter that in turn returns another function of one parameter, as shown in compose4curried.

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

이 함수는 여러 가지 방법으로 액세스할 수 있습니다.You can access this function in several ways. 다음의 각 예에서는를 반환 하 고 18을 표시 합니다.Each of the following examples returns and displays 18. 모든 예제에서 compose4compose4curried 로 바꿀 수 있습니다.You can replace compose4 with compose4curried in any of the examples.

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

함수가 이전과 동일 하 게 작동 하는지 확인 하려면 원래 테스트 사례를 다시 시도 합니다.To verify that the function still works as it did before, try the original test cases again.

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)

참고

튜플에 매개 변수를 포함 하 여 currying를 제한할 수 있습니다.You can restrict currying by enclosing parameters in tuples. 자세한 내용은 매개 변수 및 인수에서 "매개 변수 패턴"을 참조 하세요.For more information, see "Parameter Patterns" in Parameters and Arguments.

다음 예제에서는 암시적 currying를 사용 하 여 더 짧은 버전 makeGame의를 작성 합니다.The following example uses implicit currying to write a shorter version of makeGame. 함수를 makeGame game 생성 하 고 반환 하는 방법에 대 한 세부 정보는이 형식에서 더 명확 하지 않지만 원래 테스트 사례를 사용 하 여 결과가 동일한 지 확인할 수 있습니다.The details of how makeGame constructs and returns the game function are less explicit in this format, but you can verify by using the original test cases that the result is the same.

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에 대 한 자세한 내용은 함수에서 "인수 부분 적용"을 참조 하세요.For more information about currying, see "Partial Application of Arguments" in Functions.

식별자 및 함수 정의는 서로 바꿔 사용할 수 있습니다.Identifier and Function Definition Are Interchangeable

이전 예의 num 변수 이름은 정수 10으로 계산 되며 num ,가 유효한 경우 10도 유효 합니다.The variable name num in the previous examples evaluates to the integer 10, and it is no surprise that where num is valid, 10 is also valid. 함수 식별자와 해당 값의 경우에도 마찬가지입니다. 함수 이름을 사용할 수 있는 모든 위치에서는 바인딩되는 람다 식을 사용할 수 있습니다.The same is true of function identifiers and their values: anywhere the name of the function can be used, the lambda expression to which it is bound can be used.

다음 예제에서는 라는 Boolean isNegative함수를 정의한 다음 함수 이름과 함수 정의를 서로 바꿔 사용 합니다.The following example defines a Boolean function called isNegative, and then uses the name of the function and the definition of the function interchangeably. 다음 세 가지 예제는 모두를 반환 False하 고 표시 합니다.The next three examples all return and display 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바인딩되는 값을 대체 합니다.To take it one step further, substitute the value that applyIt is bound to for applyIt.

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

함수는 F의 First 클래스 값입니다.#Functions Are First-Class Values in F#

이전 섹션의 예제에서는의 F# 함수가의 F#첫 번째 클래스 값에 대 한 조건을 충족 하는 것을 보여 줍니다.The examples in the previous sections demonstrate that functions in F# satisfy the criteria for being first-class values in F#:

  • 식별자를 함수 정의에 바인딩할 수 있습니다.You can bind an identifier to a function definition.
let squareIt = fun n -> n * n
  • 데이터 구조에 함수를 저장할 수 있습니다.You can store a function in a data structure.
let funTuple2 = ( BMICalculator, fun n -> n * n )
  • 함수를 인수로 전달할 수 있습니다.You can pass a function as an argument.
let increments = List.map (fun n -> n + 1) [ 1; 2; 3; 4; 5; 6; 7 ]
  • 함수를 함수 호출의 값으로 반환할 수 있습니다.You can return a function as the value of a function call.
let checkFor item =
    let functionToReturn = fun lst ->
                           List.exists (fun a -> a = item) lst
    functionToReturn

에 대 한 F#자세한 내용은 F# 언어 참조를 참조 하세요.For more information about F#, see the F# Language Reference.

예제Example

DescriptionDescription

다음 코드는이 항목의 모든 예제를 포함 합니다.The following code contains all the examples in this topic.

코드Code

// ** GIVE THE VALUE A NAME **


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



let squareIt = fun n -> n * n



let squareIt2 n = n * n



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


// Lists.

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

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

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

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

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

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

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


// Tuples.

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

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

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

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



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

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



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

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



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


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

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

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



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

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

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



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

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

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

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

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



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


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


// The following function call returns a string:

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



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



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



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

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

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

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

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



// Function compose takes two arguments. Each argument is a function
// that takes one argument of the same type. The following declaration
// uses lambda 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

참고자료See also