纯功能编程

Zac*_*ach 14 f# functional-programming

所以,我是一位经验丰富的OOP程序员(主要是C++),刚刚开始使用函数式编程.根据我的理解,在一个纯粹的功能范例中,函数不应该有条件,应该使用currying尽可能地分解.有人可以为我提供以下示例的"纯"功能版本吗?最好使用将成为功能范例一部分的每一种严格技术:

let rec greatestCommonFactor a b =
    if a = 0 then b
    elif a < b then greatestCommonFactor a (b - a)
    else greatestCommonFactor (a - b) b
Run Code Online (Sandbox Code Playgroud)

The*_*ght 16

您提供的示例函数已经完全可用.当我们谈论函数纯度时,我们实际谈论的是函数的属性是引用透明的.

如果表达式可以在不改变程序效果的情况下替换为其值,则表达式是引用透明的.举一个简单的例子,想象一下这个函数:

let add2 x = x + 2
Run Code Online (Sandbox Code Playgroud)

现在,add2 2在我们的程序中出现值的任何地方,我们可以替换该值4而不改变程序的行为.

现在想象一下,我们在打印到控制台的函数中添加了一些额外的行为:

let add2Print x =
    printfn "%d" x
    x + 2
Run Code Online (Sandbox Code Playgroud)

虽然该函数的结果与以前相同,但我们不能再使用该值执行值替换4而不更改程序的行为,因为我们的函数具有打印到控制台的附加副作用.

此功能不再是引用透明的,因此不是纯函数.


let rec greatestCommonFactor a b =
    if a = 0 then b
    elif a < b then greatestCommonFactor a (b - a)
    else greatestCommonFactor (a - b) b
Run Code Online (Sandbox Code Playgroud)

查看您提供的此功能,其执行不会产生任何副作用.对于给定的输入a,我们将始终获得相同的输出值b,因此这已经是纯函数.

需要明确的是,函数式编程中包含条件的函数绝对没有问题.然而,通常我们使用模式匹配而不是if/elif/else表达式,但在您所描述的示例中,这纯粹是风格.使用模式匹配的函数的替代表达式将是:

let rec greatestCommonFactor a b =
    match a with
    |0 -> b
    |a' when a' < b -> greatestCommonFactor a' (b - a')
    |a' -> greatestCommonFactor (a' - b) b
Run Code Online (Sandbox Code Playgroud)

  • @Zach不,条件绝对没关系.函数式编程中的条件通常是通过模式匹配而不是通过`if/elif/else`表达式来处理的,但是如果你在这里展示的话,那就是纯粹的风格. (5认同)
  • @Zach一些函数式语言倾向于简洁风格,但条件仍然存在.即使Haskell也有一个`if`关键字,但就像在F#中一样,你倾向于使用模式匹配而不是`if`和`then`. (4认同)
  • 条件无所谓?我的印象是在功能范例中首选消除条件.比如在他们的地方使用lambdas. (2认同)
  • @Zach我在这里没有看到的是,在函数式语言中我们通常有if-expression,即if和else(甚至是if-if)分支**必须在每个分支上返回相同的类型.这是一种限制,使参考透明度成为可能. (2认同)