• F#柯里化和递归


    柯里化和局部函数应用看上去也许并没有那么强大,但他们能提高我们代码的质量,也就是说看上去将更优雅。考虑一下printf函数,如果想只使用局部函数提供一个参数"%d",应该怎么做呢,看下面的例子:
    这个例子展示了如何使printf局部版本来代替一个lambda表达式:

    >//没有柯里化,使用lambda表达式
    List.iter (fun i -> printfn "%d" i) [1 .. 3];;
    1
    2
    3
    val it : unit = ()

    >
    //使用printfn 柯里化
    List.iter (printfn "%d") [1 .. 3];;
    1
    2
    3
    val it : unit = ()


    这个例子我们让我们看到了如何充分利用局部函数应用。
    函数返回函数
    我们都知道,函数式编程像处理数据一个处理函数,也就是函数可以作为另外一个函数的返回值。关于这一点,当我们用值的角度去考虑的时候会有一些有趣的结果。
    例如下面我们定义一个函数PowerFunc,让我们看看是怎么回事:

    >let PowerFunc temp = (fun i -> temp ** i);;//求几的几次方函数
    val PowerFunc : float -> float -> float

    >
    let power1 = PowerFunc 2.0;; //调用PowerFunc返回一个函数
    val power1 : (float -> float)
    >power1
    3.0;; //求3的2次方
    val it : float = 8.0;;

    >
    let power2 = PowerFunc 3.0;; //调用PowerFunc返回一个函数
    val power2 : (float -> float)
    >power2
    2.0;; //求3的2次方
    val it : float = 9.0;;


    如果仔细看PowerFunc函数,会注意到他的temp参数是用了两个lambdas的返回值,也就是temp ** i。当PowerFunc最初把2.0作为参数时,那么2.0是存储在哪儿?这个有意思的特性我们在这里叫做团包。这里先不涉及它,或者它是如何工作的。只要知道如果一个值在作用域内,它就可以被使用并可以被函数返回。以后的章节会详细讲解这个闭包。
    函数的递归
    一个函数能够调用他自身我们称作递归,并函数式编程里,这是非常有用的。
    定义一个递归函数,我们需要有一个rec关键字。下面的代码片段字义了一个计算阶乘的函数。

    >//定义一个递归函数
    let rec factorial x =
    if x <= 1 then
    1
    else
    x * factorial ( x -
    1);;
    val factorial : int -> int
    >
    //调用
    factorial 5;;
    val it : int = 120


    这个rec关键字可能会引起我们的注意,因为其它语言没有这样的关键字来明确表示这是一个递归函数。rec关键字的实际用途是告诉类型推断系统,允许函数被当作类型推断进程的一部分。rec允许我们在类型推断系统确定函数类型之前调用此函数。

    使用递归和高阶函数,我们能够在不需要改变值的情况下,可以很容易的实现命令式语言的排序,循环等等这些设计。下面的例子创建了一个普通函数的for和while循环/

    >//for 循环函数
    let rec forLoop body times =
    if times <=0 then
    ()
    else
    body()
    forLoop body (times -
    1)
    //while loop
    let rec whileLoop predicate body =
    if predicate() then
    body()
    whileLoop predicate body
    else
    ();;
    val forLoop : (unit -> unit) -> int -> unit
    val whileLoop : (unit -> bool) -> (unit -> unit) -> unit

    > forLoop (
    fun () -> printfn "Looping...") 3;;//调用for loop
    Looping...
    Looping...
    Looping...
    val it : unit = ()

    >
    open System
    whileLoop
    (
    fun () -> DateTime.Now.DayOfWeek <> DayOfWeek.Saturday)
    (
    fun () -> printfn "I wish it were the weekend...");;
    I wish it were the weekend...
    I wish it were the weekend...
    val it : unit = ()



    下一篇介绍相互递归

  • 相关阅读:
    内存
    TCP/IP
    安装
    linux常用命令
    linux文本处理三剑客之 grep
    tail命令:显示文件结尾的内容
    less命令:查看文件内容
    head命令:显示文件开头内容
    改进Zhang Suen细化算法的C#实现
    【转】在VS2010上使用C#调用非托管C++生成的DLL文件(图文讲解)
  • 原文地址:https://www.cnblogs.com/carsickcars/p/2171714.html
Copyright © 2020-2023  润新知