目录

介绍

函数编程定义

函数属性

纯度

头等函数

闭包的概念

成为函数式

函数式实用程序

纯度重要性

头等的重要性

函数编程和面向对象编程

集成函数编程

总结


  • 下载源码 - 7.9 KB

介绍

如今,函数性编程正在流行。我们应该问自己有两个问题:

  • 为什么这种变化发生在程序员和语言创造者身上?
  • 以及如何证明这一点?

有很多函数语言:

  • C#,C ++,Java。
  • Lisp,JavaScript,Python,Smalltalk,Ruby,OCaml,F#,Scala,Groovy,D,Erlang,Clojure,Go,Swift等。

我们还可以注意到有很多关于函数式编程的书籍:

还有另外两个重要问题:

  • 如何定义一种函数语言?
  • 什么是函数式编程?

函数编程定义

函数式编程是基于函数,它们的组合,以及也基于函数分解的编程。

组合/分解的这种影响是编程范例的标志(一种建模和构建解决方案的方式)。

作为例子引用的所有语言都具有函数概念。函数式编程包括使用具有特定属性的函数。

函数属性

函数有两种可能的属性:

  • 纯度:函数的结果取决于它们的参数而没有任何其他外部影响。
  • 头等:函数具有值的状态。

函数编程包括利用这些属性中的一个或两个。

函数式语言是一种让函数式编程更具优势的语言。

纯度

如果函数是纯函数,则意味着它将生成仅依赖于函数的参数而没有任何其他外部影响的结果。

函数纯度:

  • 拒绝副作用和状态。
  • 倡导数据结构的不变性。

例如,下面是一个纯函数:

int f(int i){return i + 4;
}f(1); // -> 5
f(1); // -> 5

以下是一个不纯的函数:

int j = 4;int g(int i){j = i + j;return j;
}g(1); // -> 5
g(1); // -> 6

作为其他示例,Log是纯函数。Random 是一个不纯的函数。

头等函数

要成为头等函数意味着函数具有与诸如整数或字符之类的值相同的状态:

  1. 函数可以被命名、影响和类型化。
  2. 可以根据需要定义和创建函数。
  3. 函数可以作为另一个函数的参数传递。
  4. 可以从另一个函数返回一个函数。
  5. 函数可以存储在数据结构中。

下面是一些例子:

1.被命名、影响和类型化的能力:

Func<double, double> f = Math.Sin;

2.按需定义和创建的能力:

Func<int, int> f = x => x + 1;

3.作为参数传递给函数的能力:

g(f, 1, 2);

其中g 定义如下:

double g(Func<double, double> f, double x, double d){return f(x) + d;
}

4. 作为函数结果的能力:

Func<double, double> f = g(10);

其中g 定义如下:

Func<double, double> g(double x){return y => x + y;
}

5.能够存储在数据结构中,例如列表:

var l = new List<Func<double, double>> { Math.Sin, Math.Cos, Math.Tan };

此外,C#允许将lambda表达式表示为称为表达式树的数据结构:

Expression<Func<int, int>> expression = x => x + 1;
var d = expression.Compile();
d.Invoke(2);

因此,它们可以被存储和传输。

闭包的概念

闭包和头等是两个独立的属性。但是,要成为纯粹和/或头等,必须将函数转换为闭包。

例如,当我们将以下函数关联到以下环境时,以下函数将转换为其他上下文中的纯函数:

int i = 0, j = 1;int f(int k){return k + i + j;
}

函数式语言的标志是自动将函数的定义转换为闭包。

成为函数式

以前的定义表明:

  • 纯度是编写函数的一门学科。
  • 为了提高函数状态,不必全部实现头等的五个特征。
  • 函数语言不需要专门使用。
  • 纯度和头等可以在最初没有的语言中受到青睐。

函数式实用程序

在开发和项目方面,纯度和头等函数的实际后果是什么?

纯度重要性

纯度引发以下主要特征:与函数的应用程序上下文无关。

每当子表达式被赋值时,每个子表达式都可以被赋值。这意味着函数组合的稳定性。

以下是纯度的重要性:

  1. 函数概念简化了手续。
  2. 更完整和更具代表性的函数行为类型。
  3. 自然并行化。
  4. 提高了可读性和可维护性。
  5. 简单的测试。
  6. 记住值(缓存)。
  7. 控制评估。

然而,纯度使一些事情变得复杂:

  1. 数据结构的管理。
  2. 显式内存管理。
  3. 输入/输出的定义和错误处理,

只能使用纯函数进行编码。Haskell是一种强加于此的语言。

C#允许注释函数以明确指示它们是纯的:

[Pure]
bool f(int i){return i + 4 > 0;
}Contract.Requires(f(0));

在C#的官方文档中:“锲约中调用的所有方法都必须是纯粹的;换句话说,它们不能更新预先存在的状态。”

头等的重要性

头等的函数是:

  1. 可以被命名、影响和类型化的。
  2. 可以按需定义和创建。
  3. 可以作为参数传递给函数。
  4. 可以是函数的结果。
  5. 可以存储在数据结构中。

如果函数可以作为参数传递给函数,那么它将意味着泛化/函数抽象的可能性。函数中代码的每个部分都可以用抽象(函数调用)代替。

一个简单的代码:

float M(int y){int x1 = [ ... ];int x2 = [ ... ];[ ... ][ ... some code ... ]; // some code using x1, x2 and y[ ... ]
}

函数抽象:

public delegate int Fun(int x, int y, int z);float MFun(Fun f, int x2, int y){int x1 = [ ... ];[ ... ]f(x1, x2, y);[ ... ]
}int z1 = MFun(F1, 1, 2);
int z2 = MFun(F2, 1, 2);

函数抽象的优点是没有局部重复,并且存在关注点分离。

函数抽象的简单有效应用是对数据的通用高阶迭代操作。

例如,内部迭代器(Maps):

IEnumerable<T2> Map<T1, T2>(this IEnumerable<T1> data, Func<T1, T2> f){foreach(var x in data)yield return f(x);
}someList.Map(i => i * i);

作为头等的另一个结果,我们对泛型函数类型进行了定义。C#为arity提供函数和程序通用委托预定义类型,最多16个:

delegate TResult Func<TResult >();
delegate TResult Func<T, TResult>(T a1);
delegate TResult Func<T1, T2, TResult>(T1 a1, T2 a2);
delegate void Action<T>(T a1);
[ ... ]

通过推理类型可以减轻头等的函数。C#提供了var关键字,但它对于函数类型来说太弱了。

要按需定义和创建,通过匿名函数完成,也称为lambdas:

delegate(string s) { return s + "some string"; };

匿名委托看起来更像lambda表达式:

(s => { return s + "some string"; });
s => s + "some string";

一个主要的例子是对数据结构的迭代处理的推广,它有三种类型的函数:map,reduce / folds和filters。

例如,内部迭代器(Maps):

IEnumerable<T2> Map<T1, T2>(this IEnumerable<T1> data, Func<T1, T2> f){foreach (var x in data)yield return f(x);
}someList.Map(i => i * i);

大多数函数式语言在其库中提供映射/简化/过滤器(在C#中是Select/ Aggregate/ Where)。

映射/简化/过滤器函数集也用于表示治疗的组成:

例如LINQ:

var q = programmers
.Where(p => p.Age > 20)
.OrderByDescending(p => p.Age)
.GroupBy(p => p.Language)
.Select(g => new{ Language = g.Key, Size = g.Count(), Names = g });

作为函数的结果,允许:

  • 适应函数。
  • 部分申请(currying)。

使用头等函数,每个n元函数都可以转换为n个一元函数的组合,即成为一个curried函数:

Func<int, int, int> lam1 = (x, y) => x + y;
Func<int, Func<int, int>> lam2 = x => (y => x + y);
Func<int, int> lam3 = lam2(3); // partial application

Currying:

public static Func<T1, Func<T2, TRes>> Curry<T1, T2, TRes>(this Func<T1, T2, TRes> f){return (x => (y => f(x, y)));
}Func<int, int> lam4 = lam1.Curry()(3); // partial application

要存储在数据结构中,允许:

  • 动态模块化:管理函数集,结构化列表,表格,树,图等。
  • 将参数作为函数集(而不是简单函数)传递。

此外,其中一个缺点是数据驱动编程。

一些函数式编程技术使用纯度和头等:

  • Mapreduce(C#中的Select+ Aggregate):广义迭代处理纯函数,便于并行化。
  • 通过函数仿真控制评估:封装在没有参数的函数中的纯表达式(这些函数的按需逐个调用评估)。

函数编程和面向对象编程

为什么函数式编程通常集成到面向对象的编程中?

主要的面向对象编程语言基于类作为模块:C#,C ++,Java。

面向对象编程中开发的强大思想之一:维护、扩展和适应操作可以通过继承和类组合(这避免了对现有代码的任何修改)。函数式编程是这个问题的解决方案。

例如,战略设计模式。

策略模式是让算法独立于使用它的客户端而变化:

策略:只是在方法级别抽象代码的情况(不需要面向对象的封装和新的类层次结构)。例如,在.NET Framework中:

public delegate int Comparison<T>(T x, T y);
public void Sort(Comparison<T> comparison);public delegate bool Predicate<T>(T obj);
public List<T> FindAll(Predicate<T> match);

其他设计模式,如命令,观察者,访问者和虚拟代理,可以使头等的函数受益:

集成函数编程

包含头等函数的语言应该促进函数编程并促进它。

总结

函数编程有利于开发:纯度和头等产生一定程度的稳定性、确定性、可测试性、分区、使用流动性、组合性、概括性、可扩展性等。

  • 函数式编程适用于模块化对象。
  • 函数式编程是可溶的:纯度和头等函数可以用任何语言来考虑,包含和促进。
  • 函数/方法级别的代码抽象。
  • 方便的通用迭代器/循环实现。
  • 操作组合,序列/查询理解。
  • 函数部分应用。
  • 对象/类定义数量的限制。
  • 在函数/方法级别命名抽象。
  • 架构简化。
  • 增加灵活性。

C#中的Nutshell函数式编程相关推荐

  1. 函数式编程基础_在收件箱中免费学习函数式编程的基础

    函数式编程基础 by Preethi Kasireddy 通过Preethi Kasireddy 在收件箱中免费学习函数式编程的基础 (Learn the fundamentals of functi ...

  2. 项目中使用 java函数式编程_函数式编程在Java8中使用Lambda表达式进行开发

    事情起因 如果不喜欢看故事的同学,请前往下一章节. 事情起因是我打算集成Redis缓存,配置了Redis以后,发现@Cacheable注解始终不生效,折腾了大半天以后,我的心态已经崩了,决定不使用@C ...

  3. 计算机科学中透明性概念,函数式编程 - 什么是参考透明度?

    "参照透明度"一词来自分析哲学,即分析自然语言结构,基于逻辑和数学方法的陈述和论证的哲学分支. 换句话说,它是计算机科学之外最接近我们称之为编程语言语义的主题. 哲学家Willar ...

  4. 在 Java 9 的JShell中 跟Kotlin 的REPL中尽情体验函数式编程乐趣吧

    Java 9 JShell : 螢幕快照 2017-09-25 22.58.02.png jshell> List<String> alphabet = List.of(" ...

  5. javascript函数式_如何以及为什么在现代JavaScript中使用函数式编程

    javascript函数式 by PALAKOLLU SRI MANIKANTA 通过PALAKOLLU SRI MANIKANTA In this article, you will get a d ...

  6. C#中面向对象编程中的函数式编程

    目录 介绍 面向对象编程中仿真的函数式编程技术 粒度不匹配 面向对象的函数式编程构造 相互关系函数式编程/面向对象程序设计 C#中的函数式编程集成 函数级别的代码抽象 操作组合 函数部分应用和局部套用 ...

  7. JavaScript 中的函数式编程实践

    为什么80%的码农都做不了架构师?>>>    基础知识 函数式编程简介 说到函数式编程,人们的第一印象往往是其学院派,晦涩难懂,大概只有那些蓬头散发,不修边幅,甚至有些神经质的大学 ...

  8. java和python中函数式编程

    本篇文章将基于java和python分别介绍Lambda表达式,包括定义,使用等 java函数式编程 自jdk1.8开始,java中引入了函数式编程,使编程更加简洁灵活.接下来通过详细的例子阐述 函数 ...

  9. 『 迷你教程 』Python中的函数式编程全方法详解

    Python 是一种很棒的编程语言,是开发机器学习或数据科学应用程序的首选.Python 也很有趣,因为是一种多范式编程语言,可用于面向对象和命令式编程.具有简单的语法,易于阅读和理解. 在计算机科学 ...

最新文章

  1. 《数据结构与算法》课程设计任务书——赫夫曼编码/译码器
  2. vim 命令模式 筛选_10个步骤的筛选器模式
  3. 云服务器布置_【阿里云ECS】(一)云服务器上安装RStudio-server
  4. 第五十四期:MongoDB与MySQL:如何选择
  5. ehcache memcache redis 三大缓存男高音
  6. java基础集合数组间的转换(java集合五)
  7. openssh服务以及基于ssh的双机互信配置
  8. 帝国cms如何域名html的专题,帝国cms怎么生成html网站地图
  9. 我的CSDN账号被偷了
  10. php 拼音搜索,通过拼音模糊搜索汉字的功能实现
  11. Proteus8.12无法仿真STC15系列单片机解决办法
  12. 【Bootstrap】选择折叠项collapse
  13. (附源码)springboot大学生竞赛管理平台 毕业设计 251522
  14. 如何将PC上的Word文档分享到朋友圈
  15. VisionPro如何引用VPP?
  16. ps、firewords在win78中无法直接拖入的问题解决方法
  17. Ubuntu20.04/22.04 安装vmware 教程
  18. 使用PySide2创建图形化Python程序时:Available platform plugins are: direct2d, minimal, offscreen, windows
  19. 移动硬盘在mac电脑上不能用的原因和解决方法
  20. 华硕电脑连接不上wifi_华硕电脑连不上无线网怎么办

热门文章

  1. oracle number对应java什么类型_JVM系列之数据类型
  2. python字符串_Python字符串格式化%s%d%f详解
  3. vue4 跳转外部链接_vue跳转到外部链接
  4. 潮流海报模板|2021渐变流体必备
  5. 国潮宫廷中国风文创包装品牌样机
  6. UI设计实用素材|线框套件 WRFRM
  7. 有了优秀的可临摹PSD分层模板|瞬间提升海报质感!
  8. 利用php百马百担_百鸡百钱===百马百担====for循环嵌套
  9. Python No Module name cv2解决方案
  10. 延迟和带宽:时延简介、最后一英里、核心网带宽、网络边缘