65.9K
CodeProject 正在变化。 阅读更多。
Home

函数式编程

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.76/5 (9投票s)

2019 年 5 月 13 日

CPOL

2分钟阅读

viewsIcon

7234

函数式编程的优势

引言

软件工程的第一步是掌握编程语言,这引导我们根据特定场景选择合适的语言。 主要有两种范式:命令式和声明式。 命令式语言使用一系列语句来完成目的。

什么是函数式编程?

它们具有显式的初始化和值分配,而声明式语言仅使用表达式,没有任何详细的控制流。 函数式编程是声明式编程的一个子集,而面向对象编程是命令式语言的一个子集。 C# 和 Java 是面向对象编程语言,而 F# 和 Scala 是函数式编程语言。 虽然可以在函数式语言中使用面向对象编程的概念,例如类、接口和继承,反之亦然,例如在 C# 中使用 lambda 表达式,这是一种函数式语言的概念。

 //Imperative
        string[] stringList = new string[] { "Mahsa", "Kashi", "Hassankashi" };
        List oopList = new List();
        foreach (string str in stringList)
        {
            if (str.Length == 5)
            {
                oopList.Add(str);
            }
        }
        
//Declarative - Functional
        List functionalList = stringList.Where(s => s.Length == 5 ).ToList();

为什么选择函数式编程?

函数式编程成为技术前沿的最重要原因是,在处理多个处理器时,它具有高效且可靠的行为,换句话说,它在并行编程方面具有最佳性能。

通过尾调用优化避免堆栈溢出

另一个原因是,函数式语言中的循环和迭代将通过带有 TCO(尾调用优化)的递归来完成。 TCO 是一种在不使用单独的堆栈帧的情况下调用函数的方法,从而避免堆栈溢出。 例如,在下面的代码中,Factorial(4) 的计算需要 4 个单独的堆栈帧,而函数式语言中的下一个计算只需要一个堆栈帧。

这不是 TCO

  def factorial(n):
        if n == 0:
        return 1
        return n * factorial(n-1)

这是 TCO

       def factorial(n):
            return fact(n, 1)
        
        def fact(n, number):
            if n == 0:
            return number
            return fact(n-1, number*n)

借助不可变对象,作为线程安全的手段,避免竞争条件和死锁。

什么是竞争条件?

在多线程概念中,当两个或多个线程同时尝试获取共享资源或对象时。

什么是死锁?

在多线程概念中,当进程 1 持有并锁定资源 2 并等待资源 1 时,而此时进程 2 持有并锁定资源 1 并等待资源 2 时。

什么是线程安全?

在多线程概念中,线程安全确保每个线程可以在同时进行时正确执行,而不会产生意外的交互。

什么是不可变?

不可变对象的 state 或值在创建后无法更改。 a 是可变的,因为它的值会被更改

  • a = 1
  • b = 2
  • a = a + b

在创建时,a 应该定义为只读和不可变,以防止更改其值。

结论

由于不可变在函数式编程中是线程安全的,因此它对于无限循环或 foreach 循环(尤其是在数学函数中)非常有用,并可以防止竞争条件和死锁。

函数式编程 - CodeProject - 代码之家
© . All rights reserved.