C#中的Nutshell函数式编程
目录
介绍
函数编程定义
函数属性
纯度
头等函数
闭包的概念
成为函数式
函数式实用程序
纯度重要性
头等的重要性
函数编程和面向对象编程
集成函数编程
总结
- 下载源码 - 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.被命名、影响和类型化的能力:
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;
}
函数式语言的标志是自动将函数的定义转换为闭包。
成为函数式
以前的定义表明:
- 纯度是编写函数的一门学科。
- 为了提高函数状态,不必全部实现头等的五个特征。
- 函数语言不需要专门使用。
- 纯度和头等可以在最初没有的语言中受到青睐。
函数式实用程序
在开发和项目方面,纯度和头等函数的实际后果是什么?
纯度重要性
纯度引发以下主要特征:与函数的应用程序上下文无关。
每当子表达式被赋值时,每个子表达式都可以被赋值。这意味着函数组合的稳定性。
以下是纯度的重要性:
- 函数概念简化了手续。
- 更完整和更具代表性的函数行为类型。
- 自然并行化。
- 提高了可读性和可维护性。
- 简单的测试。
- 记住值(缓存)。
- 控制评估。
然而,纯度使一些事情变得复杂:
- 数据结构的管理。
- 显式内存管理。
- 输入/输出的定义和错误处理,
只能使用纯函数进行编码。Haskell是一种强加于此的语言。
C#允许注释函数以明确指示它们是纯的:
[Pure]
bool f(int i){return i + 4 > 0;
}Contract.Requires(f(0));
在C#的官方文档中:“锲约中调用的所有方法都必须是纯粹的;换句话说,它们不能更新预先存在的状态。”
头等的重要性
头等的函数是:
- 可以被命名、影响和类型化的。
- 可以按需定义和创建。
- 可以作为参数传递给函数。
- 可以是函数的结果。
- 可以存储在数据结构中。
如果函数可以作为参数传递给函数,那么它将意味着泛化/函数抽象的可能性。函数中代码的每个部分都可以用抽象(函数调用)代替。
一个简单的代码:
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函数式编程相关推荐
- 函数式编程基础_在收件箱中免费学习函数式编程的基础
函数式编程基础 by Preethi Kasireddy 通过Preethi Kasireddy 在收件箱中免费学习函数式编程的基础 (Learn the fundamentals of functi ...
- 项目中使用 java函数式编程_函数式编程在Java8中使用Lambda表达式进行开发
事情起因 如果不喜欢看故事的同学,请前往下一章节. 事情起因是我打算集成Redis缓存,配置了Redis以后,发现@Cacheable注解始终不生效,折腾了大半天以后,我的心态已经崩了,决定不使用@C ...
- 计算机科学中透明性概念,函数式编程 - 什么是参考透明度?
"参照透明度"一词来自分析哲学,即分析自然语言结构,基于逻辑和数学方法的陈述和论证的哲学分支. 换句话说,它是计算机科学之外最接近我们称之为编程语言语义的主题. 哲学家Willar ...
- 在 Java 9 的JShell中 跟Kotlin 的REPL中尽情体验函数式编程乐趣吧
Java 9 JShell : 螢幕快照 2017-09-25 22.58.02.png jshell> List<String> alphabet = List.of(" ...
- javascript函数式_如何以及为什么在现代JavaScript中使用函数式编程
javascript函数式 by PALAKOLLU SRI MANIKANTA 通过PALAKOLLU SRI MANIKANTA In this article, you will get a d ...
- C#中面向对象编程中的函数式编程
目录 介绍 面向对象编程中仿真的函数式编程技术 粒度不匹配 面向对象的函数式编程构造 相互关系函数式编程/面向对象程序设计 C#中的函数式编程集成 函数级别的代码抽象 操作组合 函数部分应用和局部套用 ...
- JavaScript 中的函数式编程实践
为什么80%的码农都做不了架构师?>>> 基础知识 函数式编程简介 说到函数式编程,人们的第一印象往往是其学院派,晦涩难懂,大概只有那些蓬头散发,不修边幅,甚至有些神经质的大学 ...
- java和python中函数式编程
本篇文章将基于java和python分别介绍Lambda表达式,包括定义,使用等 java函数式编程 自jdk1.8开始,java中引入了函数式编程,使编程更加简洁灵活.接下来通过详细的例子阐述 函数 ...
- 『 迷你教程 』Python中的函数式编程全方法详解
Python 是一种很棒的编程语言,是开发机器学习或数据科学应用程序的首选.Python 也很有趣,因为是一种多范式编程语言,可用于面向对象和命令式编程.具有简单的语法,易于阅读和理解. 在计算机科学 ...
最新文章
- php+mysql 大容量数据高效分页效果(弃用limit)
- before vue路由钩子_vue组件级路由钩子函数介绍,及实际应用
- java filereader blob_二进制学习——Blob,ArrayBuffer、File、FileReader和FormData的区别
- Linux学习:shell命令(查找和索引)
- elasticsearch 索引存储深入详解
- 请说说接口和抽象类的区别?
- 设计模式之Builder (创建者模式)的一些个人理解(转)
- MySQL8.0.19下载安装及配置详细步骤
- python标准库之fnmatch,dis,timeit
- 在mysql命令行下执行sql文件
- js map的get 和list比 那个快_js中let和var
- 2013年1月5号第一次事故
- 基于dpdk的用户态协议栈f-stack实现分析
- Win7系统桌面设置便签与备忘录的方法
- 多目标跟踪算法SOART
- Rope3d数据集分析
- 学大数据技术与应用的女生多吗?适合吗?
- python 乌龟绘图turtle模块的使用
- 【读书笔记】Linux内核完全注释第二章:微型计算机组成结构
- 百年包豪斯 (Bauhaus) 对当今 UX 设计的启发与影响
热门文章
- python8皇后不攻击问题_python 八皇后问题的解法(深度搜索)
- 装扮圣诞海报气氛,你需要这些小元素!
- 圣诞节平面设计师排版|首选手写字体素材,简单但非常好用。
- 美妆海报模板|来点创意的海报设计(立体剪纸风格)
- PSD分层模板素材|电商页面这样设计,转化率成倍提高!
- java volatitl_Java中的关键字volatitle
- js能调用c语言吗,如何从Javascript调用Object-C?
- C++设计模式详解之模板模式解析
- cuSPARSE库:(十一)cusparseCreateSolveAnalysisInfo()
- CPU的乱序执行、指令流水线技术