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

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

 

 

 

【深入浅出Koa】常用工具分享 帮你降低编程难度 Relay: 全新的React数据获取框架 探索游戏开发面临的技术挑战——MDCC 2015游戏开发专场议程曝光 【SDCC讲师专访】易开发创始人潘俊勇:这些年我遇到的那些坑 【CTO讲堂】OpenStack行业实践和发展趋势探讨 万物互联,移动为先:MDCC 2015移动开发者大会盛大开幕! 【MDCC 2015】微软开发体验与平台事业合作部大中华区DX部门总经理Srikanth Raju:物联之上云+端 英雄会晚宴,Top开发者共聚“华山之巅” 【MDCC 2015】产品与设计专场(上):百度研究院、印象笔记等专家齐聚,以实例探讨如何打造好产品 【MDCC 2015】产品与设计专场(下):网易云音乐、在行、三节课、去哪儿网、野兽骑行大咖的产品之路 友盟:把数据用活 让开发者享受大数据红利 友盟:用活大数据 让精细化运营为移动开发者服务 携手世纪互联 IBM Bluemix云平台落地中国 【MDCC 2015】IoT峰会—硬件开发与技术专场(下):专家齐聚,共同打造联网新时代 【MDCC 2015】虚拟现实专场(下):虚拟现实的“困”与“竞” 【CTO讲堂】面对世界竞争对手,如何拿到Google PDF开源项目PDFium? 提升网站性能开发的10个技巧 SDCC 2015:顶尖技术精英云集 大会日程及首批讲师议题公布 《近匠》专访猿团创始人CEO谢恩明:梦想、未来、改变 《近匠》专访小熊尼奥:从软硬结合到IP合作,AR产品的机遇 W3C启动Web支付标准工作,推进在线结算流程 W3C中国区会员沙龙在京召开 W3C CEO Jeff分享W3C未来发展重点 【SDCC讲师专访】车轮互联总架构师韩天峰:PHP是最好的编程语言 SDCC 2015讲师专访精彩集锦(一):你想知道的,都在这! (入门篇)带你走进Erlang 【大神来了】Elixir语言设计者Jos&#233; Valim:释放Erlang VM的能量 【SDCC 2015讲师专访】刘小溪:Vert.x3的异步框架实战 【CTO讲堂】支付接入开发的陷阱有多深? 程序员界“香饽饽”、大神级别人物集体亮相——SDCC 2015编程语言专场议题曝光 【CTO沙龙】CDN在共享经济下的创新应用 深入浅出Fetch API 带你入解应用场景及适用问题 如何获取Dispatch接口中的事件? 小小问题:如何清空用ADO连接的数据库表中的记录 大家由没有碰到这样的问题? 100分请高手给澄清关于数据库引擎的几个概念 请问 ucs2编码如何转化成gb格式的? 在Ado2.1中如果已经Addnew,如何撤消而不引起错误? 打开新窗口的问题 谁知道那里有电子版的《C语言编程思想》 如何获得输入得BSTR 字符串得值? 帮我想想! 为什么我运行 ms-project2000会出错!错误内容在里面,请大家指教!!! 哈工大附近有卖3号足球(最小的那种,可以在室内玩)的吗? 修改?? 关于CPU 100%使用率的问题 如何使用VB访问MySQL数据库? 视图窗口的windows句柄和视图窗口的指针有什么区别? SQLServer出现问题,急!! 如何像Windows Form一样,弹出 .aspx的Web文件。 请教一个问题。急 请问如何才能链接到中文文件?谢谢。 初学者的一个很低级的问题! 未老先衰吗? 用什么方法可以把DBGrid查询的内容打印处理,查询是用sql语句的,有什么好控件? 怎样重烖 滚动条的滚动消息? 请问高手:IIS5.0+PHP4.0安装问题 怎么样取得数据窗口中所有的TEXT和计算字段的列表? 如何实现(单击一个下拉菜单,同时刷新另外一个下拉菜单中的值??) 我的Red Hat 7.3启动盘丢了。怎么办? 哪里有讲Object Pascal的书下载? vb里怎么调用vc写的dll,还有为什么vc的dll不好用regsvr32直接注册,老说dll enter point not found ★★★同志们好,我想在北京找工作,什么人才网站比较好? 怎样实现在一个窗体中控制另外一个窗体及其控件? 创建一个线程来接收串口数据,为什么正常收一段时间后(10多分钟)就不再收任何东西了? 关于设计一个防震系统!欢迎讨论! 请问各位高手!Win32 SDK里面有没有用来设置麦克风音量的函数? 用.Net技术实现:与扫描仪直接连接,将扫描图像保存为文件,其他子内容保存到数据库中? 请大虾介绍一款好用的web报表打印控件,最好有说明文档,谢谢 CString类型怎样转换成unsigned char * 关于使用System.Net.Sockets时的一些不明白的问题 关于.net编辑器操作的问题? 将main函数移动后出现的编译错误 请各位大佬帮忙,sql server是否有..start with..这样语句? 读"征集2001参加工作的程序员的工作感受和打算"有感! 我知道问提出在那里了,再问: 求职 怎么修改RTE控件的字体大小? 删除文件的问题 出大问题了?????!!!!! 有没有人用CORBA,JBUILER编写JSP? 请问有没有vc.net方面的好书呀 哪位大侠在使用JMAIL3。7来发送邮件时,出现,邮件成功发送但收件人收到的邮件没有内容???? 第三题为什么选A? 什么无色无味的化学品能让米变红色 稀有气体通电后发光是为什么?是因为通电后它自身发光,还是它把电子发的光加强了?为什么? 大学物理 3题 我想找一种无色无味无毒密度大流动性好无腐蚀性的化学试剂 知道的请留下化学名称 稀有气体通电发光是因为什么?是因为哪一层电子受激发而产生的? 用酵母粉发面要加入碱吗?什么时候加碱?加多少合适? 什么东西有毒无色无味能使人死亡 稀有气体通电发光为什么是物理变化 怎么样去除化纤地毯的有害物质,急求我被人家骗了,买了一批化纤地毯,家里人老是骂我,现在谁有办法帮我啊.去除有害有毒物质,比如甲全,等, 能用逻辑学分析下,为什么反证法一定能成立?怎么证明它一定成立? 无色无味可以漂白食品的有什么东西? 在电位法中作为指示电极,其电位应与被测离子浓度()A成反比B符合能斯特公式的关系C成正比D符合扩散电流公式的关系 问两个关于水解和电离化学题 不难滴~1PH相同的HCL H2SO4 CH3COOH 各100ml(1)三种溶液中物质的量浓度最大的是?(2)分别用0.1mol/L的NaOH中和 消耗NaOH最多的是?(3)分别与形状 质量相同的铁片反 反证法和归谬法的区别 莫尔法测氯时,为什么溶液的 pH 值须控制在 6.5 10.5 反证法是依据逻辑学的( )而来的一种证明方法A . 同一律B . 排中律C . 不矛盾律 什么是归谬法 1.空气污染来自于哪?用英文怎么说.2.The teachers are at work,()()the teachers.3.the chicken wing smells nice()()the chicken wing()?4.the smoke comes from the factory.()()the smoke ()from?1.where( ) 对称关系,非对称关系,反对称关系传递关系,给传递关系,反传递关系 什么叫做反证法? 英语翻译 1.相同物质的量浓度的下列溶液中 a.NH4Cl、b.CH3COONH4、c.NH4HSO4,c(NH4+)由大到小的顺序为___C>A>B____________为什么?2.Fe2(SO4)3溶液蒸干得到Fe2(SO4)3 ;灼烧得到 Fe2(SO4) .为什么?3.物质的量浓度相同的CH3COO 一道有关电离的化学题(高二)——好的有【附加分】已知电离度:H2CO3>H2S>HCO3-判断Na2S+H2O+CO2=== (是H2S还是NaHS,是Na2CO3还是NaHCO3?请【详细分析思考过程】,) 树能减少空气污染,使我们的城市更加美丽英语 炭粉、铁粉、FeS、CuS、CuO、MnO2、Fe3O4 由什么鉴别颜色都是黑色的,由化学试剂怎么鉴别.希望能写出方程式. 现有浓度为1 mol/L的五种溶液:①HCI,②H2SO4,③CH3COOH,④NH4Cl,⑤NaOH,由水电离出的C(H+)大小关系正确的是( )A.④>③>①=⑤>② B.①=②>③>④>⑤C.②>①>③>④>⑤ D.④>③>①>⑤>②为什么CH3COOH 电位滴定法对谷氨酸钠的测定计算公式滴定终点PH为9.6 逻辑学的案例 将0.1mol/L的醋酸钠溶液20mL与0.1mol/L盐酸10rnL混合后,溶液显酸性,则溶液中有关微粒的浓度关系正确的是A c (Ac-)>c (Cl-)>c (H+)>c (HAc)B c (Ac-)>c (Cl-)>c (HAc)>c(H+)C c (Ac-)=c (Cl+)>c 电位分析法 可以测定的离子有哪些? 关于化学 电离和水解的哪些是 电离大于水解哪些离子不能大量共存常见有色离子的颜色 求空气污染的原因和解决办法的六分钟英语小短文 酒精发酵前为什么要对固定化酵母细胞进行增殖培养 生活中应用逻辑学的例子 关于中国空气污染问题的英文初中生作文 直接电位分析法的测定依据是什么? 经常看到醋酸的电离大于醋酸根的水解,氨水的电离大于铵根离子的水解,那是不是说 弱酸弱碱的电离大于其根离子的水解呢? 关于空气污染的小文章空气污染是如何影响人的 一道化学电离方面的题二十五摄氏度时0.08mol/l二元酸h2a的溶液ph为一,则naha溶液中h2a的浓度与a负离子浓度的大小 世界上大部分地区人口集中分布于平原地区,但是在巴西,人口集中分布在巴西高原上, 关于治理空气污染的文章我们化学课上要用、【收集关于大气污染和保护治理空气污染的文章】最好要简练,不要太长. 如何检验黑色粉末是碳粉和氧化铜的混合物 巴西的城市多分布在巴西高原而不是在亚马逊平原的主要原因是? 一九二八二十伏一百瓦灯泡接到照明电路上,求,灯丝的电阻是多大 碳粉和氧化铜粉末都是黑色的,请设计两种方法将这两种粉末鉴别出来,并说明哪种方法更好 图中4. 照明电路上两灯泡灯丝电阻R1=1210欧 R2=484欧 求两灯正常工作时流经灯丝电流各是多大 鉴别碳粉,氧化铜,碳和氧化铜的混合粉末有三瓶黑色粉末,分别是碳粉,氧化铜,还有碳和氧化铜的混合物如何鉴别? 图是中间那个.大学物理! 硅谷迅速发展的区位因素? 已知某黑色粉末可能是氧化铜或碳粉或两者混合物.现向粉末通入二氧化碳且加热此粉末,形成可燃性气体,…问此处的黑色粉末是?…… 最上面那道,图如左 硅谷工业有什么特点?硅谷在微电子工业中占什么地位?它的兴起主要有那些条件? 什么是节点电流定律?请作详细介绍,该怎么用呢? :求解释(图中公式 ) 什么液体无色无味? 求大学物理题解释第三题 如图,求推导 什么农药无色无味剧毒
备案号:鲁ICP备13029499号-2 说三道四 www.s3d4.cn 说三道四技术文摘