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

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

 

 

 

或许很受用:苹果、谷歌和亚马逊等公司的14个怪异面试题 12款不容错过的新款jQuery插件 技术开发者如何看实时Web App开发框架? 高薪技术排行:大数据居首,苹果相关次之,Java、C等相去甚远 谷歌开发网络跟踪新技术:AdID将取代第三方Cookie 穿在脚上的苹果?苹果聘用Nike设计主管Ben Shaffer 七款Debug工具推荐:iOS开发必备的调试利器 六年亲历,见证中国大数据技术与应用时代的到来 Mailbox:日支撑过亿信息数据库的性能调优及集群迁移 PayPal前CTO 在美国改变世界的乌克兰犹太人 放弃Bootstrap&amp;amp;Foundation,迎接Semantic UI? 一键分享:iOS版Google+发布SDK InMobi杨娟:中国移动游戏如何挑战全球? Adobe再遭APT攻击:数十G源代码及290万用户信息失窃 程序员,如何在工作中崭露头角? 国内外三个不同领域巨头分享的Redis实战经验及使用场景 这是一场潜在的战争:谷歌与Facebook、苹果在搜索上的博弈 设计新闻类网站需要注意的关键点:移动友好、宽带…… 直接开始用:5个免费的在线思维组织工具 招聘开发者常见的九大误区 开源影响销售,维护赞助商? 盘点黑客攻击途径:最常用的7个策略及简单的防护方法 专访AngularJS框架创始人Misko Hevery:让Web开发更便捷 果粉的又一个节日:新iPad或于10月22日发布 新车间李大维:到集装箱里来看创客嘉年华 亚马逊推“登录与支付”功能 直接冲击PayPal Google编程之夏新里程碑:5000万行源代码 8500名学生开发者 非常实用的15款开源PHP类库 Runnable:一站式代码片段服务平台,打造编程界的YouTube 谷歌向所有开发者开放Google App Engine PHP Runtime “沟通”电子表格和矢量图形的“桥梁”:在线可视化工具Raw 关于如何设计一个服务器 如何释放指针所指的空间,但是仍然可以使用这个指针? 想嵌套使用javascript,和jsp 一个很菜的问题:UpdateData???? ※※ ¥8000 ~¥12000月薪能招到什么样的程序员? ※※ Java中字符串相等的判断! 各位高手请问VB.net里的ADO连接怎么做?请提供代码,谢谢? 我有一个DLL但是我不知道如何在Delphi中引用(不是COM),不过我有C++中的 ***.h文件 关于显示窗体的问题! 贡献500分或者更多,大家大讨论!! 为什么我的硬盘灯会一闪一闪的? sql 语句 错在哪儿??? 我调试了很久 什么样程序风格才最好的? 有关计算机方面的国标大家有列表吗,只要列表呀,我在论谈上找不到呀,谁给我一份了谢了! 如何知道串口上来数据了 在线等待:Windows启动时弹出“Exception EStackOverflow in moudle ...”的错误提示而无法运行Delphi的程序,why? 请高手指点一二。 简单问题:我却搞不定:--- vc7.0里面为什么不认cos、sin等数学函数? OracleOraHome81ManagementServer服务的启动问题。 activex 发布 用C#怎样得到一个dll文件的版本号呢? 问一个比较简单的问题! 关于msgbox的简单问题,才鸟求知,谢谢帮忙!!!!! 困惑。什么工作好啊,来者有分 大哥、大姐们,快拔刀吧! 如何取得SQL SERVER2000数据库某字段的空值? 如何用split分割纵向字符串?在线等候. 关于java workshop的问题(急) 向高手请教一个问题(硬编译),至少200分相送 为什么我用request.getPathInfo()取到的结果为空? c# 版的朋友们大家好!!新手登录,多多帮助! oracle触发1器 一个好多人问过的问题,可是我这里还是不能用,请在帮下忙 发布Applet出现的错误,帮忙撒 本人在PB开发中遇到莫名其妙的问题 强烈建议成立crack专栏,同意的请跟帖。 textbox的输入问题 我的98系统在重新启动后再进入系统时屏幕上会出现一闪闪的雪花点,这是为什么呀? 请教!谁会使用这个API函数(DbiPackTable),该函数在BDE32.HLP中。 一个循环问题,急急急!! mysql -h remotehost -u root连不上对方机子? 分布式应用中的服务器端访问当地窗口的问题 打印的问题,大家请看,得到你们的思路,马上给分! 我想做一个保存图片资源的dll文件,谁有这方面的文章和代码啊? 看一下这个ServiceApp.出错信息! 有专家吗?Cache问题 那里有linux原码下栽?不全也可以? 怎么用OPENCV?(50分) winsock下载FLASH动画的错误问题 好好看看这个妞,天机不可泄漏啊,哈哈哈哈 有内胎全钢载重子午线轮胎质量缺陷问题硫化工序中产生的废次品和返修胎有效控制问题.Please help me,thanks your help 描述一下或举例 中国面积有多大 催化剂(分析纯)能用来做什么水溶性反应——合格;杂质含量:澄清度——0.05%,水不溶物——0.001%,氯化物——0.01%,硫酸盐——0.002%,氮化合物——0.0005%,钾——0.0005%,铁——0.0005%,砷——0.000 一些物质的反应与条件(如温度,催化剂,反应介质等)密切相关,请举例 中国具体面积有多大? what kinds of jobs interest you most and least?英语怎么回答 下列各组物质发生时,生成物不因反应条件(浓度,温度或催化剂等)的不同而不同的是A Cu 与 HNO3B CO 与 O2C Na 与 O2D C2H5OH 与 O2 我觉得A肯定不对,铜有与稀浓硝酸反应,剩下的就不晓得了 铝壶怎样除水垢? 刮刀离心机下的料(12%水分)怎么往盘式干燥机输送,现在我们用的料斗料不能自动的放下来. 二氧化碳怎样在温度不明的情况下快速反应为一氧化碳?如果用催化剂,该用哪种物质为所谓的温度不明,指的是碳的温度处于300度以内,要让二氧化碳与碳快速反应(很少或没有氧气),可以加 某超市销售有甲、乙两种商品,甲商品每件进价10元,售价15元;乙商品每件进价30元,售(2008•遵义)某超市销售有甲、乙两种商品,甲商品每件进价10元,售价15元;乙商品每件进价30元,售价40 硫酸钾和锌反应,四氯化碳和锌反应方程式 《济南的冬天》作者从几个方面介绍济南的冬天1.《济南的冬天》作者描绘了几幅图画2.《济南的冬天》作者运用了哪些手法3.《济南的冬天》作者描绘济南的山,济南的水,流露出作者怎样的 铝壶上的水垢为什么除不去 聚苯乙烯原料价格走向?越快越好! 鸣音水壶水位多少才会鸣音 某超市销售甲乙两种商品.甲商品进价10元,售价15元;乙商品每件进价30元,售价40元.该超市为使甲乙两种商品共80件的总利润不少于600元,但又不超过610元,请你帮助该超市设计相应的进货方案. what place are you going to visit 改为同义句 鸣音水壶不会鸣音了怎么办?RT 某超市销售甲、乙两种商品,甲每件进价10元,售价15元,乙商品每件进价30元,售价40元.若该超市同时一次购进甲.乙两种商品共80件.两种商品获得的总利润恰好为500元,球该超市购进甲、乙,两种商 The place--you are going to visit is the ruin of a place为什么用which 随便翻译出来 鸣音水壶的壶盖安装顺序家里鸣音水壶,壶盖螺丝松了后,拆下来重新安装后就不响了,我想是我的安装顺序或者反正有问题,有了解具体如何安装的吗?帮个忙, 关于水的重要性的故事. what will you do when you are in a strange place?Suppose you are going to BWhat will you do when you are in a strange place?Suppose you are going to Boston and you have never visited the city before.If someone 21 you about the interesting places in t 关于碳循环的叙述,错误的是?A产生温室气体.B需要能量驱动.C不依赖水.D具有全球性.并求原因.你们在思考思考,我的老师说选A,你怎么看? 鸣音水壶为什么不鸣音 Be与浓NaOH反应化学反应方程式 软管怎样做气密性测试及有何设备 甲商品每件进价10元,乙商品每件进价30元,某超市同时一次购进甲、乙两种商品共80件,恰好用去1600元,销售时甲商品的售价是每件15元,乙商品的售价是每件40元,销售完这批商品后,该超市的利润 中国实际面积到底多大啊? 主量子数n、角量子数l、磁量子数ml以及自旋磁量子数ms分别表示什么 饱和湿度的计算已知空气中的温度和气压,怎么计算饱和湿度.以及怎么利用温度计算水蒸气饱和分压 关于曼珠沙华的说明文好的话,要400字以上 化学式反应条件等号上下有什么区别吗?比如一个反应有加热又有催化剂,该哪个写在上面? 具体事例说明学习的重要性请你举一个具体的事例说明学习的重要性跪求的啊..哥哥姐姐们谢谢了~~最好少一点的 因为我要写下来 亚硝酸钠中什么成分有毒用化学式表达 磁量子数是什么?是...取向?那这个...取向到底是什么意思? 信息对于管理重要性的例子 亚硝酸钠的成份是什么? 主量子数=2 角量子数=3 磁量子数=2 能成立吗 怎么改 He was the last one ( ) house when the earthqHe was the last one ( ) house when the earthquake happenedA leave B.left C.to leave D.leaves 车辆上主要使用什么交流发电机叉车上电动机 如何计算湿度 the time when village was you the were last in 连词成句 where等于which place还是等于what place急 子午胎 必须用 卤化丁基橡胶么 中国面积一共有多大? Where will you visit?what will you visit? 压力喷水壶的原理,最好有张那个喷水壶侧面的剖图,看情况适当追分 如何去除烧壶水锈 Where did you visit or what did you visit 全钢、半钢轮胎有用卤化丁基橡胶吗 为什么几家客户说不用丁基橡胶的? 不锈钢壶水锈怎么去除 ______ did you visit last Saturday? A.where B.what C.……(排除)我怎么区分这个东西,还有,假如它在地址上画上线,我究竟怎么回答!!! 无内胎子午线轮胎的气密性怎么检测? 电壶里的水垢怎么去除 小清去商店买牙膏,同一品牌两途中牙膏的售价情况如下:120克的,每支9元;160克 水位压力计算现在已知高度为9m,管径为25mm,求最底部压强为多少?并给出详细的计算公式,如果想要把底部压强增加到0.7兆帕,在不更改高度的情况下,更改水管的直径是否可以呢?或者有什么其它 When they got home,the seven dwarfs found Snow White _______A.die B.dead C.death D.dying ATI催化剂是做什么用的?
备案号:鲁ICP备13029499号-2 说三道四 www.s3d4.cn 说三道四技术文摘