说三道四技术文摘-感悟人生的经典句子
说三道四 > 文档快照

在F#中将函数作为一等对象的值

HTML文档下载 WORD文档下载 PDF文档下载
在编程语言中,我们常常把那些将函数作为一等对象的函数称为一等函数(first-class functions)。具体地说,就是编程语言支持在程序执行过程中构造新的函数,并将它们存储在数据结构中作为其它函数的参数的传入参数,并在函数返回时将它们作为函数值返回。

 

本文中将First-Class翻译为“一类”,容易产生歧义,容易理解为这一类。因此笔者翻译为一等。
本文原标题是“作为一类值的函数 (F#)” Functions as First-Class Values (F#),笔者认为应该翻译为
“在F#中将函数作为一等对象的值”更容易理解,如果您有异议,可以在我的专栏 http://www.okbase.net/home/haobao 与我讨论。
再说说一等对象、一等函数的概念:
在编程语言中,我们常常把那些将函数作为一等对象的函数称为一等函数(first-class functions)。
具体地说,就是编程语言支持在程序执行过程中构造新的函数,并将它们存储在数据结构中作为其它函数的参数的传入参数,并在函数返回时将它们作为函数值返回。
函数编程语言的定义特征是将函数提升到一等状态。 您应当能够对函数执行可对其他内置类型的值执行的任何操作,并且只需一般程度的工作量就能够完成此操作。
一等状态的典型度量包括:
是否可以将标识符绑定到值? 也就是说,是否可以为它指定一个名称?
是否可以将值存储在诸如列表之类的数据结构中?
是否可以在函数调用中将值作为参数传递?
是否可以将值作为函数调用的值返回?
最后两个度量定义的对象称为高阶运算或高阶函数。 高阶函数接受作为参数的函数,并将函数作为函数调用的值返回。 这些操作支持将这种函数编程主体作为映射函数和函数组合。
为该值指定名称
如果函数是一等值,您必须能够对其进行命名,就像您可以对整数、字符串和其他内置类型命名一样。 这在函数编程语言中称为将标识符绑定到值。 F# 使用 let 表达式将名称绑定到值: let <identifier> = <value>。 以下代码显示了两个示例。

 

本文中将First-Class翻译为“一类”,容易产生歧义,容易理解为这一类。因此笔者翻译为一等。

本文原标题是“作为一类值的函数 (F#)” Functions as First-Class Values (F#),笔者认为应该翻译为

“在F#中将函数作为一等对象的值”更容易理解,如果您有异议,可以在我的专栏 http://www.okbase.net/home/haobao 与我讨论。

再说说一等对象、一等函数的概念:

在编程语言中,我们常常把那些将函数作为一等对象的函数称为一等函数(first-class functions)。

具体地说,就是编程语言支持在程序执行过程中构造新的函数,并将它们存储在数据结构中作为其它函数的参数的传入参数,并在函数返回时将它们作为函数值返回。

 

函数编程语言的定义特征是将函数提升到一等状态。 您应当能够对函数执行可对其他内置类型的值执行的任何操作,并且只需一般程度的工作量就能够完成此操作。

 

一等状态的典型度量包括:

 

是否可以将标识符绑定到值? 也就是说,是否可以为它指定一个名称?

 

是否可以将值存储在诸如列表之类的数据结构中?

 

是否可以在函数调用中将值作为参数传递?

 

是否可以将值作为函数调用的值返回?

 

最后两个度量定义的对象称为高阶运算或高阶函数。 高阶函数接受作为参数的函数,并将函数作为函数调用的值返回。 这些操作支持将这种函数编程主体作为映射函数和函数组合。

 

为该值指定名称

如果函数是一等值,您必须能够对其进行命名,就像您可以对整数、字符串和其他内置类型命名一样。 这在函数编程语言中称为将标识符绑定到值。 F# 使用 let 表达式将名称绑定到值: let <identifier> = <value>。 以下代码显示了两个示例。

 

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

您可以轻松地命名函数。 下面的示例通过将标识符 squareIt 绑定到 lambda 表达式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 * nlet 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 = 10let moreMixedTuple = ( num, "two", 3.3, squareIt )

为了验证元组中存储的函数名称的实际计算结果是否为函数,下面的示例使用 fst 和 snd 运算符提取 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 和 lambda 表达式 fun n -> n * n 也可以互换。

 

// 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))
将值作为参数传递
如果值在语言中具有一等状态,则可以将它作为参数传递给函数。 例如,常见的做法是将整数和字符串作为参数传递。 下面的代码演示 F# 中作为参数传递的整数和字符串。
// An integer is passed to squareIt. Both squareIt and num are defined in // previous examples.//let num = 10//let squareIt = fun n -> n * nSystem.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 有两个参数:op 和 arg。 如果发送到 arg 的函数中有一个对应于 op 的形参和该函数的一个相应实参,则该函数返回将 op 应用到 arg 的结果。 在下面的示例中,函数参数和整型参数都使用它们的名称以相同的方式发送。
// 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)
将一个函数作为另一个函数的参数发送的功能将常见抽象基于函数编程语言,例如映射操作或筛选操作。 例如,映射操作是一个高阶函数,它捕获由函数共享的计算,这些函数单步执行某个列表,对每个元素执行一些操作,然后返回结果列表。 您可能要递增整数列表中的每个元素,对每个元素求平方,或者将字符串列表中的每个元素更改为大写。 计算中易于出错的部分是单步执行列表并生成返回结果列表的递归过程。 该部分是在映射函数中捕获的。 必须为特定应用程序编写的全部内容就是要分别应用于每个列表元素的函数(添加、求平方、更改大小写)。 就像上例中将 squareIt 发送到 applyIt 一样,该函数作为参数发送到映射函数。
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 * nSystem.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,并返回一个新函数作为其值。 返回的函数采用列表作为其参数 lst,然后在 lst 中搜索 item。 如果存在 item,则函数返回 true。 如果不存在 item,则函数返回 false。 像在上一节中一样,下面的代码使用提供的列表函数 List.exists 来搜索列表。
let checkFor item =     let functionToReturn = fun lst ->                           List.exists (fun a -> a = item) lst    functionToReturn
下面的代码使用 checkFor 创建一个新函数,该函数带有一个参数(即一个列表)并在该列表中搜索 7。
// 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 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
下面的代码将两个函数作为参数发送给 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。
下面的示例将函数作为函数调用的值返回,它将创建一个简单的猜测游戏。 若要创建一个游戏,请调用 makeGame,并将希望某人猜测的值作为 target 发送。 从函数 makeGame 返回的值是一个函数,它带有一个参数 (guess),并报告 guess 是否正确。
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,并将值 7 作为 target 发送。 标识符 playGame 绑定到返回的 lambda 表达式。 因此,playGame 是一个函数,它采用 guess 的值作为它的一个参数。
let playGame = makeGame 7// Send in some guesses.playGame 2playGame 9playGame 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!
扩充函数
通过利用 F# 函数声明中的隐式扩充,可以更简洁地编写上一节中的许多示例。 扩充是将具有多个参数的函数转换为一系列嵌入式函数(每个嵌入式函数都具有一个参数)的过程。 在 F# 中,具有多个参数的函数都会被扩充。 例如,如以下简洁样式所示,可以使用三个参数编写上一节中的 compose。
let compose4 op1 op2 n = op1 (op2 n)
但是,结果是一个具有一个参数的函数,该参数又返回一个具有一个参数的函数,而这个参数又返回另一个具有一个参数的函数,如 compose4curried 中所示。
let compose4curried =    fun op1 ->        fun op2 ->            fun n -> op1 (op2 n)
可以通过多种方法访问此函数。 下面每个示例返回并显示 18。 在任一示例中,可以将 compose4 替换为 compose4curried。
// 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 的简短版本。 在该格式下,有关 makeGame 如何构造和返回 game 函数的详细信息不太明确,但您可以使用结果相同的原始测试用例进行验证。
let makeGame2 target guess =    if guess = target then       System.Console.WriteLine("You win!")    else        System.Console.WriteLine("Wrong. Try again.")let playGame2 = makeGame2 7playGame2 2playGame2 9playGame2 7let alphaGame2 = makeGame2 'q'alphaGame2 'c'alphaGame2 'r'alphaGame2 'j'alphaGame2 'q'
标识符和函数定义可以互换
上例中的变量名 num 的计算结果为整数 10,num 有效并不为奇,因为 10 也是有效的。 函数标识符和它们的值也是如此:在可以使用函数名称的任何位置,都可以使用函数绑定到的 lambda 表达式。
下面的示例定义一个称为 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 = 10System.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
示例
说明
下面的代码包含此主题中的所有示例。
代码
// ** GIVE THE VALUE A NAME **// Integer and string.let num = 10let str = "F#"let squareIt = fun n -> n * nlet 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 * nlet 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 = 10let 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 * nSystem.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 * nSystem.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.    gamelet playGame = makeGame 7// Send in some guesses.playGame 2playGame 9playGame 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 7playGame2 2playGame2 9playGame2 7let 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 = 10System.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 * nlet 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
本文来源于微软网站。

 

 

 

下一代Android深度前瞻 第18级API功能揭秘 Web开发者不容错过的20段CSS代码 8大核心要点:我们能用HTML5 Canvas做什么? 移动周报:直接拿来用!最火的Android开源项目 前MySQL CEO:云将重新定义开发者的每一件事 CIO必知六件事,至少必须想到的! PPT集萃(四):来自五位中外专家分享的虚拟化和云存储实践 Jolla和Sailfish OS,那些你应该知道的事儿 不仅保值还能升值:过时的苹果电脑创下67.1万美元售价 三十天完成跨平台办公套件Joeffice的开发 jQuery 1.10.0和2.0.1同时发布 软件初创公司招投的九个必备技巧 BYOD浪潮即将来袭 六大年轻杀手重塑企业软件 灵活运用AppFlood:提高APP eCPM的10个技巧 事半功倍:你应该知道的HTML5五大特性 创建API监视器的五大技巧 流量激增15倍+ 乐蜂网桃花节大促背后的技术事 Windows 8和IE 10:如何保障视频播放? 云计算大会讲师秀之13:梁家恩,12年积累,构建永久免费的语音云平台 众望所归:智能手机芯片将为服务器所用 没有学位,他通过以下四步进入Google 谈谈Google Polymer以及Web UI框架的未来 保密入髓:前苹果员工揭示公司是如此善于保守秘密 调查显示:软件开发公司出现“人才荒” 三星拟6月20日在伦敦召开新品发布会 推手机新品Galaxy和ATIV 历届中国云计算大会PPT集萃(五):数据安全隐患解析与应对 搞趣网创始人:做不了阳春白雪 就做下里巴人 CMDN Club 28期:创业公司一定不要浪费资源 浅谈Lean UX:我们到底该怎么设计? 张艺谋今日正式加盟乐视 作品专区落户超级电视 WebKit华丽转身:欧朋浏览器8.0新鲜出炉 救急:Win me开始菜单及Taskbar的小图标都变花了,如何解决?up有分 ############狂送分,附带一个小问题########### 在bc中怎样创建资源文件?? 请高手进入,急!在线等待 生活有你 更新后台數據,用試圖就可以,用代碼就不行? ★★★CFormView的大小,高手没必要进,低手就可以解决了! 不超过十行,但.....(C) 打到雍亲王 "准女朋友的胸太平了,我该如何取舍? " 准备结贴了,要顶的赶快顶呀,去晚了就没机会了 为什么我从数据采集仪采集到的数据是乱码? 请教:动态的下拉菜单怎样做?在线等待,答对就给分! 有谁知道用vb如何把bmp的文件转换为jpg格式?? sql server2000是不是不能在winxp 专业版下安装?? 请问大家 wait函数的使用问题(给100) 关于wait函数的使用问题(给100) 如何在xp下能够删除带子目录的文件夹? [求助]关于考试座位号随机分配问题! 无奈的我等你的帮助! 在delphi中如何建立一个doc文件? 有谁可以帮帮忙(在线等待) 请问大家如何防止DEDE的,我发现许多软件没有进行压缩也无法进行DEDE反编译,通常只能进行到一半 现代制造业企业管理系统的开发 (C++ builder) 线程设计,帮帮忙!!! 关于flash中的actionscript 如何做自动评分的考试系统?给点建议或意见! 告急!!!主从表的问题,怎样修改从表时,让主表的数据跟着变化? 刚刚在新闻组看到的东西, 让大家乐乐(转贴) 关于ASP.NET的讨论,欢迎大家指正. 再发:请教在Rave 报表中如何在每一页上都显示打印表头 关于视图的问题!!!很急,各位大哥帮帮忙!! CrystalReports(水晶报表)的版权问题 请看此贴!帮忙阿! 菜鸟问题,请问怎么让 点主from上的一个按钮就弹出另一个编好的窗体 请问能不能将网页页面内容保存为word文档输出?? 碰上大麻烦了,哥们们救救我吧!~ 请看此帖,帮忙啊! 中文打包问题 谁可以给我一个java的例子读excel的*.cvs文件,thanks 请看此帖,帮忙啊! 想请叫一个关于网站视频的问题 关于jre的2个问题 oracle错误 Memo字段(Access)的字符串搜索问题? 在线等待啊,高分!!对选题的判分。 请看此帖,帮忙啊! 我是新手 不知学习前端软件开发哪种好(vb.net / pb /?????????) 高手救急!win2000/xp安装棘手问题!在线等 我的小猫怎摸找不到了呢? 菜鸟一问:一个关于生成类似VC中WorkSpace的一个问题,救命用啊~~~请大家帮忙!! 品牌权益(brand equity)和品牌价值(brand value)有什麽不衕?有什麼不同点? 关于英雄形像和秋天景色的成语 思维北征,宜先入南中思的意思 国庆阅兵观后感的题目60周年的,别太俗了,像《 》有感;国庆 有感……之类的.30分钟内回答!60周年的,别太俗了,像《 》有感;国庆 有感……之类的不要。30分钟内回答! 急需英语单句改错题答案,并讲解理由, 臣受命之日 寝不安席 食不甘味 成长在现代汉语大辞典中的含义 2009年双子座流星雨在美国能看到么?加州.俄勒冈那里 “故五月渡泸,深入不毛”涉及到什么事件? 方言与现代汉语的意义相比较,有什么不同 请问、2010年的双子座流星雨在广东韶关能看到吗?几号能看到最多? 五月渡泸,深入不毛与什么战役有关 赋课金翻译成国语白话是什么意思? 2011英语作文改错试题 用‘小时’作‘单位时间’行吗? Plant Physiology 是不是SCI 2009国庆阅兵读后感,300字到400字之间.要300到400字之间 电功率的时间单位是秒吗?100W的时间单位是小时吗? Plant Diseases and Pests是什么级别的杂志 09国庆阅兵读后感急死了 机械表是用什么方式对应时间单位:小时,和分钟的?如果说:时针从一个数字走到下一个数字经过的这个格子对应的是时间单位(一小时),那么分针同时间走的一圈是什么意思?如果再说:分 但愿人长久千里共婵娟,其中婵娟指的是什么? tourist products在有关旅游的英语文章中什么意思 西班牙语cuidarte el 英语翻译一个字,词语,短语翻译就好,能整段整段翻译自然最佳 products什么意思啊,英语真的实在不通了 要求初二水平 ,正方形ABCD中,边长为4,BE=1,P是线段AC上的以动点,当P在AC上运动是,PB+PE的最小值是多少? 第五题,下面那题不用做,求解答第五题, 英语广告:“Brand new w/warranty.”中的“w/”是什么意思?类似的还有:“Brown w/ ice maker.Excel.cond.Reasonably priced.”中的“w/”是什么意思? c 如何实现画抛物线 “但愿人长久,千里共婵娟”中的“婵娟”指的是什么? 关于鲁滨逊漂流记的读后感字数500 急! 不讲诚信的人有什么危害? 但愿人长久,千里共婵娟中“婵娟”指什么 Brand products such as character是什么意思啊 求初2说明作文 帮我看看这改错题 One afternoon a girl set out in the coast in a small boat and was caught in a storm.答案说把in改成from,可这句话有另个in ,应该是该哪个呢? 2009国庆阅兵直播观后感600字要像初一写的 写事作文最好的方法是甚么?(初2作文)写实作文的最好方法是甚么?(初2作文) 求英语,这是道改错题,每条都有错, 求解一道高数的定积分题目 寻求初2英语短文解释In ten years,I think l’ll live in Shanghai,because l went to Shaihai last year and fell in love with it.I think it’s really a beautiful city.As a reporter,I think l will meet lost of interesting people.I think l’ll l sprout plant soil seed 哪个是与众不同的单词? 会议室座位安排领导10名,秘书1名,主持人1名,客人43名,大屏幕在门口那侧,如何安排座位? 因为男方连续多个月赌博,被女方发现赌博单据,并且事后还不承认错误,两人已经分居半年多,男方一直也没有诚意,以托时间为主,就是不同意离婚,还动手打人,辱骂女方,曾经说过:‘我就是不 什么牌子的微晶石好?超晶石和微晶石有什么区别? “第二故乡”英文怎么翻?、、RT、、 有一个与地面成30°角的斜坡,现要在斜坡上竖一电线杆,当电线杆与斜坡成( )度角时,电线杆与地面垂直.我同学都算得等于60°,我的疑惑是:为什么不能写120°?求大师解决 心驰神往 有一首英文歌曲,节奏很像凤凰传奇这首 心驰神往 叫什么名字 请帮解释一改错题 I was about to rush out of the train station when a well-dressed old man took me by my arm.“ Young lady,” said the gentleman,“Shouldn’t you find out the bus schedule before you rush out to catch the bus?”by my arm 出师表“五月渡泸,深入不毛”是三国演义中的什么故事 找一个符号【黑色的爱心】♥这个怎么打? 例:风景——流连忘返 问:英雄——( ) 五月渡泸,深入不毛,. 什么是Core_value_of_brand? If he hadn’t used his cellphone to make that SOS call ,all the passengers on boat would have left to die in the sea ,just like what happened to the people on the Titanic almost 100 years ago .would have left 改成would have been left为什么要 湿婆神发怒是什么意思 2009国庆阅兵观后感 取题目2009国庆阅兵的观后感~ 帮忙取个题目` 各位大哥大姐帮帮忙~ 急啊!10月9日要交啦、、谢 2009年双子座流星雨2009年的双子座流星雨大不大?我家在黑龙江黑河具体的观测时间和观测地点需不需要带什么?如果没有天文望远镜看得到嘛?我刚等完狮子座流星雨就感觉俩字:上当这次看 五月渡泸,深入不毛 指的是三国演义中的哪个故事 叙政府称:日内瓦会议旨在让总统下台则挪威一公交车遭持刀男子挟持 造成3人博尔特自爆在北京拒吃中餐 吃了100穆尔西拒穿囚服出庭高呼口号 庭审被迫温州三名年轻女子失联谜案 子女离家家浙江青田男子网络上扮富二代骗女子钱浙江体院:孙杨多次违纪 早就想处理他男子持刀入室抢劫女子 原是其前夫一手义乌一家箱包厂四楼着火 消防及时救出金东查获1000多万元假减肥药或引发义乌打工男子联合女友从其追求者处骗钱穆尔西出庭态度不屑拒受审 埃及部署2500元买了本\"巴基斯坦驾照\" 主城区小区停车日趋紧张 凤起立交边526岁小伙车祸后脑死亡 家属捐出他的16秒26 17岁高二女生单手玩魔方杭二中女生林心悦全国中学生物理竞赛第周日较强冷空气杀到彻底把杭州带入深秋浙医二院对抗菌药物管理动真格 有医生猪木在朝开设事务所 称愿为日朝关系做缅甸传奇双胞胎重聚 八岁即建“上帝军你耍你的大牌,我玩我的特色及时拨打67680000它们,是行业发展的推动力短短一个小时 撂倒三十二人诺维茨基幸福教育 秀外慧中专家荐号他撞死的竟是亲戚……夺命快递涉事化工厂多次寄1公斤毒样品货币市场利率闻声大幅回落买家具不花钱,引发全民疯抢我的爸爸孩子们用自己的方式欢度圣诞街舞,让每一个细胞都跳跃第一场雪郑州街头开圣诞送礼动员大会面对越来越离谱的早恋let\'s go!掘金财富“地一线2013中原家居风云人物独特课程 因材施教2014,你敢“二”吗
备案号:鲁ICP备13029499号-2 说三道四 www.s3d4.cn 说三道四技术文摘