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

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

 

 

 

非编程方式访问数据库-VB资料 VB用编程方式访问数据库 VB 5.0数据库设计技术讲座(4) VB5.0数据库编程经验小集 VB5在处理数据库时的几个“BUG” VB6.0中的几个新增数据库工具 VB处理数据库时求数据表记录总数的最佳方法 VB访问数据库的方案比较 VB数据库编程经验两则 VB数据库编空字段的处理 VB数据库多字段记录的录入 VB数据库记录查询四法 vb应用程序访问sql server方法探讨 VB中超长OLE数据库字段的操纵方法 VB中将数据转换为数据库文件 VB中远程数据库的访问 Visual Basic 的数据库编程 Visual Basic数据库数据的选项录入及选项增减与编辑 把资料输往Excel来列印-VB资料 报表中的滚动问题-VB资料 编写Connect Strings-VB资料 表或查询是否存在-VB资料 不创建DSN直接在程序中使用ODBC数据源-VB资料 不用 DATA 控件操作数据库文件 -VB资料 不用 EOF 以加快记录循环-VB资料 处理Select语句中的单引号 -VB资料 断开所有的数据连接 -VB资料 访问VB外来数据库 非access数据库在vb中的编程及应用 关闭程序中所有创建的数据库连接。 -VB资料 关闭所有的数据连接 -VB资料 有没有可以动态改变控件与控件之间宽度的控件 仙劍3 破落解文件下載,快下。快刪了。 保存bmp文件的时候,如何让保存对话框默认为.bmp?? 做程序员后最经常给自己找的借口、、、 如何向注册表写入REG_DWORD类型的值,谢谢指点! 怎样链接数据库?再就是运用b/s结构完美结合 我實在不知道怎麼改了,請各位大蝦幫幫忙! interbase数据库返回的错误信息的代码是什么?具体的含义是什么? <script language=javascript src="hp/count/counter.asp?referer="+escape(document.referrer)></script>有何不对? 工具条的运动问题 在等 各位前辈来指点小弟一次吧,小弟明天面试jsp程序员 Visual Basic宣告死亡了吗? JS 菜单如何才能位于 select 表单之上? ★★★★★给个意见★★★★★ 高手指导:编xml用什么工具最好?郁闷中1····· 如何实现在线播放多个文件?即如何处理在线播放列表??在线等..... 请问如何在状态栏中显示图片? unicode和utf8的文件格式、区别等学习资料?! 请问listview的排序问题!!!!!!!!!!???????????????????????????? 奇怪的问题,急!!!!!!!! 有没有客家人?进来报道一下。 帮忙看几行代码是什么错误? 请问listview的排序问题!!!!!!!!!!???????????????????????????? 其实如今的中国,一个字就可以概括 再VC7中加入对话框的问题 TCP连接发送数据如何限制一个连接的最大速度? win2003 cdk??? 机子无法启动,各位大虾帮帮忙! 在一个FORM里面绘制了GDI对象,怎样将FORM中的选定的区域转换为位图呢? 心情不好,放分。 安装win 98时,提示“没有足够的常规内存”,该如何解决?? 奇怪的查询问题,既没有出错,也没有正确结果。 一个很基础的指针问题,为什么非要转化为一个二级指针再转化为一级指针呀,才能 想自己动手写一个论坛,请大虾推荐几本asp入门书籍 想比较一下corba webservice dcom的异同,作为论文发表如何 如何编程实现对共享文件的进行访问监视? 如何改变select-sQl查询窗的名字啊,默认是“查询”,能否改成自已喜欢的? 求助:做程控滤波器(模拟)可以用哪些芯片??? 请问取整用 那个函数? 快 C# Builder 1.0 企业版BT下载! 很容易的问题,送分了模态对话框问题 这个API调用没胡有语 错误,但为什么在打印出来好多小四方格呀,我以前也遇到 过,不知什么原因 pb8.0与java VM安装问题请教! 请教高手,我将整个目录的文件写到一个ListBox1里,想按字母顺序写入!! 一个页转到另一个页后,另一个页的地址栏上将汉字转换成了%%%%类似的东西,如何解决? form 标签里的 enctype="multipart/form-data" 是什么意思? 哪有jsp的免费空间?最好支持ftp的 我在程序里写了insert语句也执行成功了,但在sql explorer的data里却找不到该条记录?但insert相同记录却也提示记录重复?interbase数据 求解一水晶报表打包后的问题? 我出差了,才回来看了一眼可用分大大的多了,可是信誉分才有56了,怎么办呀!! rh8的文本界面能不能显示中文啊 摩羯座时间观念!最近认识了摩羯座的女生,别人说摩羯座是很有时间观念的.但是每次她说赶时间的时候,我和她聊着聊着她就会忘记等下还有别的事情要做!很多人一起的时候她很少会有话和 yes,we 郭味蕖美术馆观后感 因为字错闹的笑话从中感受到什么的作文 把一条蛇和一只青蛙放在一起,一整天过去了,蛇也没有吃掉青蛙,这是为什么? 达摩面壁九年,到底是为什么? 敲边鼓是什么意思 空旷 卑鄙 敏捷 强健 从容不迫 公正无私的反义词 1.葡萄,2.桃子,3,西瓜,4.饭前要洗手,这些词语的英文和读音,读音标汉谢谢,哪位神人解决 THE FARMERS PROCESS THEM INTO BLACK TRA,OOLONG TEA ,GREEN TEA OR WHITE TEA.中PROCESS INTO翻?还有 BUT PEOPLE HAVE PROCESSED IT TO TAKE AWAY THE CAFFEINE.中的PROCESSED TO怎么翻译呢? 如果回答要是:Yes,we are. 那问题是什么?问题能是Are you going to--------?吗? 锯腿农民阻拦记者调查农村医保:不要管顾客超市停车场追尾 超市被判承担15快递员拒绝先验货后签收 买家扬言放狗金华女子偷肉被发现 脱光衣裤跳池塘劫匪一脚踩在温州姑娘脸上 逼其说出银前同事冒充海关中层干部承诺拍卖会搞定韩国称金正恩频繁观看气垫船登陆演习 朝将召开2万军官大会 韩称朝能未经中中国铺开周边外交新棋局 “问题”国家德国新一届联邦议院举行首次会议全国第3季度城市空气质量好排名 舟山老家具还能这么用?!简直惊艳瞎了!臭.婊.子,你想红是吗?哥们看到第四#美味的朋友#趣味热气球儿童餐会哭的韩国农民有奶吃◆ 未.满.18.岁不.要.看,看了西媒发起“一起为皮克鼓掌”活动机构内参曝光 7股股价望飙升巴萨高层:真要想签人不用太长时间日本:印度面临窘境 若打战支撑不过2你一定看过这些照片!可你不知道它是假贝克汉姆:在弗格森面前总像个小孩
备案号:鲁ICP备13029499号-2 说三道四 www.s3d4.cn 说三道四技术文摘