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

在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
本文来源于微软网站。

 

 

 

【十问十答】对话Go语言开发团队 苹果要求、Android开始,64位时代真的来了! MDCC 2014产品与设计论坛:带你发现产品之美 Java开发者值得关注的7款新工具 助力国产移动产品出海,UCloud部署北美节点 Zack Parker:用EC2在Cotap上打桩 用卫生棉杀敌冲关!两个高中女生的创意游戏 专访《Java程序员修炼之道》作者Ben Evans:保守的设计思想是Java的最大优势 Google收购Firebase 帮助程序员快速开发出移动App和Web App 微信支付开发关键点技术解析 游戏任玩!开源虚拟现实头戴式设备Open DoVision MDCC大会召开倒数10天 看Twitter、Facebook和国内“BAT”三大巨头最新动态 《近匠》Wijmo 5 CTO:从Web到移动,我的25年编程生涯 重复充电、防丢失!多功能智能行李箱Bluesmart 【设计经验传承】图标设计初阶要先型 “光年”光纤路由 支持千兆网络的家居中心 MDCC 2014移动开发技术与平台峰会:知名应用技术大牛传授实战经验 Unity生态圈将变?EA前总裁接替创始人任新CEO 第九届中国Linux内核开发者大会在京举办 《近匠》爱拍SDK:手游录像分享 爱拍才会赢 Mark走起!iOS开发最常用的第三方库 【CTO俱乐部读书会】《人件》译者肖然:软件工程是社会学 错过就要等一年 深圳微信开发者大会不容错过的十大理由 【干货】国外程序员整理的 C++ 资源大全 一周消息树:被投资人“送”入看守所,创业人汪洁有罪还是无罪? 聚焦五大主题 Atlassian Summit 2014精华PPT下载 2014中国移动开发者大调查第四期获奖名单曝光 【问底】许鹏:使用Spark+Cassandra打造高性能数据分析平台(一) 【特惠倒计时两天】参加深圳微信开发者大会赠书及全套讲师讲义 《英雄联盟》支撑最高750万同时在线用户的聊天服务打造 深圳云软技术副总黄榕振:招行信用卡微信公众号开发高级篇 三台机器不用HUB如何实现互相访问? 请教通讯的问题 用accsee数据库 怎么不显示登陆的用户密码框? c,如何得到一个文件名中指定位置指定长度的字符串?? 服务器是否打开支持FileSystemObject对象的权限 我的数据表列宽为7个字符 , 而我只输入3个字符 , 当我输入4个字符后 , 再次运行程序却看不到所有数据 从新做人 求救:在NT Server下调用GetVolumeInformationA取分区序列号,返回结果为负数!!!怎么回事啊? 正式到新公司上班,送300分,感谢在我最困难的时候在“软件工程”版给过我帮助的朋友们!! 请问斑竹及所有人,怎样得到QuickReport的总页数? Websphere3.5的一个BUG.希望有人反对.多谢.. 什么是DAMAP的对象 哪里有 winpcap 或 libnet 及其他网络编程辅助包下载? 谁能提供PSP文档?最好是Humphrey的那本书! 代码出现bebug.请大家帮我找!!!! TO:net_lover(孟子E章),详情请入内! 有谁用过DEV express系列的dxdbgrid??它是如何把一个文本文件txt读到dxdbgrid1.columns[i]的picklist中去,作为picklist的内容的啊? 我想在Linux下做数据库开发,用什么数据好? 我的pws可能出了问题,那位高手能解决一下 关于控制winamp 各位同行你们有这个的源程序吗(Cacio DT-900数据采集器) Html Help 制作方法 luodi(无知者无畏), 请进: 我用shell(app.path+"\mdac.exe"),来调用微软数据访问控件2.0,提示出错:命令行语法错误, 求救:如何将剪贴板中的内容放到image控件上 how to get the sytax of customer user object ? jsp中的打印问题 pb中有没有类似iif之类的语句 大虾们,怎样将String 类型转换成float 请问在及时战略中,怎么实现寻路的 我想在状态栏显示时间,有没有属性可以让时间自动变化,而不用其它辅助控件? 不会没人愿意回答这个问题吧,都贴第二次了!! 吃西瓜 我在注冊自創構件時總是出錯,請各位幫忙解決. 关于ado连接sybase的问题,紧急求救!!!(我的最高分了) 29分:flexcell定位 请教一下,关于Delphi COM类型库的问题 大家来谈谈申奥成功对我们的影响吧,我想知道怎么利用这个契机大赚一笔 各位谁喜欢“后街男孩”??喜欢的给分! 请问在DBGRID中改变当前选定行的颜色? 我想在DataSourceDataChange()中实现。 客户端怎么与服务器端通信 为什么我在窗口里修改了一个记录的图片字段后,在数据窗口内不能正常显示? 我要在RedLinux71下安装WEB服务器软件,请部如何做? 如何计算某年某月的天数和每天对应的星期 help!!! 为什么我的D6在编译时出现错误:“Fatal Error QuickRpt.pas(23):File not found:'Dsgnintf.dcu' 帝国时代之农民搞笑版……哈哈 如何用DEBUG的命令取消cmos密码!!!急急急! 请教一个Redhat安装的问题 该死的创新virba128…… 急!!!给tripofdream(梦之旅)和能解决全文检索的高手! 有台WIN95机器启动是时出错缺文件mtrr.vxd,udf.vxd谁能帮我! 小学数学16*25+15*2简便算法 编写程序,计算圆柱体,球体,正方体和长方体的表面积和体积(提示:本题中,可先定义一 1.一个高10cm的圆柱,如果把高减少3cm,表面积就比原来减少18.84cm.这个圆柱的体积是多少立方厘米?2.把一个高8dm的圆柱体割拼成一个等底的近似长方体后,表面积增加了24dm²,圆柱体的体积是多 计算2008又2007分之1*2008分之2007 正方体、长方体、圆柱体的体积都可以用S乘以H来计算对吗? 一个圆柱体底面周长是18.84cm,高是10cm,这个圆柱体的占地面积是多少? 求底面半径为5厘米,侧面展开为正方形的圆柱体的侧面积、表面积和体积. 用正方体,长方体,圆柱体,球体的盒子可以拼什么东西 数学题一个圆柱体高减少4厘米,表面积减少125.6厘米,它的体积是多少? 一个圆柱体的底面直径是4厘米,它的侧面积是( )表面积是( ),体积是(一个圆柱体的底面直径是4厘米,它的侧面积是( )表面积是( ),体积是( ) 一个圆柱体如果它的高截短3厘米表面积减少94.2平方厘米它的底面半径减少多少体积减少多少 把一个圆柱体的高减少4厘米后,表面积减少50.24平方厘米,求减少部分的体积 一个圆柱体高10厘米,底面半径5分米,表面积是多少? 9、一个圆柱体,如果把它的高截短3厘米,表面积就减少94.2平方厘米.它的底面半径体积减少了( )立方厘米9、一个圆柱体,如果把它的高截短3厘米,表面积就减少94.2平方厘米.它的底面半径是( 一段圆柱体钢材,截去10cm长的一段后,表面积减少了314,体积减少了( ) 一个圆柱体底面半径是1分米,高是20厘米,它的体积是 表面积是 一个圆柱体,如果把它的高截短3厘米,表面积就减少94.2平方厘米.它的底面半径是多少厘米?体积减少了多少立方厘米? 把一个直径是10CM的圆柱体沿直径纵向切开以后,表面积增加了100CM,原来这个圆柱的体积是多少立方厘米?把一个直径是8CM的圆柱体沿直径纵向切开以后,表面积增加了112CM,原来这个圆柱的体积是 一个圆柱体的底面半径是1分米,他等侧面积是( )平方分米,表面积是( )平方分米,体积是( ) 一个圆柱体的底面半径是2cm,高5cm,它的侧面积是多少,表面积是多少,体积是多少列出算式 一个圆柱体的高是10CM,如果高减少4CM,则表面积减少125·6.原来圆柱的体积是()立方厘米.最好有算式 输入圆柱体的底面半径和高,求圆柱体的表面积和体积.请编写程序, 一个圆柱体的底面半径是4CM,高6CM,现在把这个圆柱体的高增加5CM,表面积和体积各增加多少? 一个圆柱体,如果把它的高截短3里厘米,表面积就减少94.2平方厘米,体积就减少了( )立方厘米? 编写程序,调用函数求一个圆柱体的表面积和体积.用c语言编写.谢谢啦. 一个圆柱体已知他的a=5cm h=2cm 求他的表面积和体积.(要有算式.) 一个圆柱体如果它的高截短3CM,表面积就减少94.2平方厘米,体积就减少了多少立方厘米 从键盘输入半径和高输出圆柱体的底面积和体积C语言 一个高为5CM的圆柱体,如果它的高增加3CM,那么它的表面积就增加18.84CM平方.原来的圆柱体的体积是多少? 一个圆柱体,如果把它的高截短2厘米,表面积就减少62.8平方厘米,体积就减少多少立方厘米?请把具体步骤都写一遍谢谢 c语言求圆柱体的表面积和体积求圆柱体的表面积和体积.从键盘输入圆柱体的半径和高,求它表面积和体积,保留到小数点后2位. 一个圆柱体的底面周长是31.4厘米,如果高增加2厘米 底面大小不变 那么表面积比原来增加了多少平方厘米一个圆柱体的底面周长是31.4厘米,如果高增加2厘米 底面大小不变 那么表面积比原来 把1张周长是80的圆柱体木柴锯成三段相等的圆柱,表面积增加了48平方厘米,原来的圆柱体木柴的体积是 c语言计算圆柱体的体积与表面积 要求保留三位小数为什么我的输出总是0000?#include#define pi 3.14int main(){float r,h,v,s;scanf("%f%f",&r,&h);v=Pi*r*r*h;s=Pi*2*r*(r+h);printf("%.3f%.3f",&v,&s);return 0;} 一个圆柱体的底面周长是31.4米,高增加2厘米,底面大小不变,则表面积增加了多少急用,明天就要 一个高5厘米的圆柱体,沿底面直径将圆柱体锯成两块,其表面积增加40平方厘米,原来这个圆柱的体积? C语言编程,求我错在哪里了,目标:求圆柱体表面积和体积.#includeint main(){\x05float r,h,S,V,pi;\x05pi = 3.14;\x05scanf("%f,%f",&r,&h);\x05S = pi*r*r*2+2*pi*r*h;\x05V = pi*r*r*h;\x05printf("%f\n%f\n",S,V);\x05return 0;}我编译 一个圆柱体的底面周长是3.14cm,如多高增加2cm,底面大小不变,那么表面积比原来增加了多少?讲一讲,【必须列算式】 一个高为5厘米的圆柱,沿底面直径将圆柱锯成两块,其表面积增加了40平方厘米,原来这个圆柱的体积是() c语言已知园半径r=1.5设圆半径r=1.5,圆柱高h=3,求圆周长,圆面积,圆球体积,圆柱体 一个圆柱体底面周长是31.4厘米表面积是 408.2平方厘米这个圆柱的高是多少厘米? 一个圆柱体的体积是125.6立方厘米,底面直径是4厘米,它的侧面积是多少平方厘米?2.把一个棱长是6分米的正方体木块,削成一个最大的圆柱体,这个圆柱体的体积是多少立方分米? 简算 2004+200.4+20.04+2.004 输入圆柱体底面的半径R,和高H,输出其表面积S和体积V 用VB输入圆柱体底面的半径R,和高H,输出其表面积S和体积V 一个圆柱体底面周长与高相等,若高减少3cm,表面积减少188.4平方厘米,求原来圆柱体体积. 2004+200.4+20.04+2.004等于多少? JAVA声明圆柱体类和圆锥体类,继承矩形类rectangle并实现volume借口,计算表面积和体积要代码哦~注意继承的不是圆~ 把一个长80厘米的圆柱体,沿与底面平行方向平均裁成4段,表面积增加了188.4平方厘米,求每段的体积.详细解说一下,看不懂. 9.05*2.01 怎样简算 java设计:问题是编写程序计算圆柱体的体积和表面积编写程序计算圆柱体的体积和表面积.提示:1.读入半径和高.2.表面积=半径×半径×π+2×半径×π×高.3.体积=底面积×高4.注意使用的数 把一个长80厘米的圆柱体,沿与底面平行方向平均截成4段表面积增加188.4平方厘米求每段的体积 递等式计算,用简便算法.要用乘法运算定律、加法运算定律、除法运算性质、减法运算性质.快,好的重分酬谢!(4.2-0.4×6)÷4== (15300÷600+67.5)×180==10500÷(10500÷25×1.25)==[(5.84- 输入圆柱体的底面半径和圆柱体的高,并计算圆柱体的表面积和体积,并输出结果 从一个圆柱体截下一段高为5CM的小圆柱后,表面积比原来减少188.4平方厘米,被截下的小圆柱的体积是多少 125*1.25*0.125*8*.08*0.008*4*0.4*0.004*25*0.25*2.5=?(用简便算法计算).08改成0.8 已知圆柱体的直径是4厘米和高6厘米求它的表面积和体积 圆柱的底面半径是2厘米,高是5厘米,圆柱体的底面积\表面积\体积,分别是多少? 桌上摆了两盘奶糖,共50块,如果从甲盘子里面拿走5块放到乙盘子里,那么两个盘子的奶糖一样多,原来两个盘子里各有多少奶糖. 把长方体、正方体、圆柱体、圆锥体、球体分为两类为什么?请具体说明。如果考试?怎么办? 个高是10cm的圆柱,如果它的高减少2cm,表面积就减少18.84cm²,原来圆柱的体积是多少?
备案号:鲁ICP备13029499号-2 说三道四 www.s3d4.cn