惰性求值 php,详细介绍C#函数式编程的示例代码
public double MemoryUtilization()
{
//计算目前内存使用率
var pcInfo = new ComputerInfo();
var usedMem = pcInfo.TotalPhysicalMemory - pcInfo.AvailablePhysicalMemory;
return (double)(usedMem / Convert.ToDecimal(pcInfo.TotalPhysicalMemory));
}
public int BigCalculatationForFirstStep()
{
//第一步运算
System.Threading.Thread.Sleep(TimeSpan.FromSeconds(2));
Console.WriteLine("big calulation");
FirstStepExecuted = true;
return 10;
}
public void NextStep(double memoryUtilization,int firstStepDistance)
{
//下一步运算
if(memoryUtilization<0.8&&firststepdistance<100) {="" console.writeline("next="" step");="" }="" }
在执行NextStep的时候需要传入内存使用率和第一步(函数BigCalculatationForFirstStep)的计算结果,如代码所示,第一步操作是一个很费时的运算,但是由于C#的严格求值策略,对于语句if(memoryUtilization<0.8&&firststepdistance<100)来讲,即使内存使用率已经大于80%了,第一步操作还得执行,很显然,如果内存使用率大于80%,值firststepdistance已经不重要了,完全可以不用计算。
所以惰性求值是指:表达式或者表达式的一部分只有当真正需要它们的结果时才会对它们进行求值。我们尝试用高阶函数来重写这个需求:public void NextStepWithOrderFunction(Func memoryUtilization,Func firstStep)
{
if (memoryUtilization() < 0.8 && firstStep() < 100)
{
Console.WriteLine("Next step");
}
}
代码很简单,就是用一个函数表达式来代替函数值,如果if (memoryUtilization() < 0.8..这句不满足,后面的函数也不会执行。微软在.net4.0版本中加入了Lazy类,大家可以在有这种需求的场景下使用这个机制。
三、函数柯里化(Curry)
柯里化也称作局部套用。定义:是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数且返回结果的新函数的技术,ps:为什么官方解释这么绕口?
看到这样的定义估计大家也很难明白这是这么一回事,所以我们从curry的原理讲起:
写一个两个数相加的函数:
public Func AddTwoNumber()
{
return (x, y) => x + y;
}
ok, 如何使用这个函数?
var result= _curringReasoning.AddTwoNumber()(1,2);
1+2=3,调用很简单。需求升级,我们需要一个函数,这个函数要求输入一个参数(number),算出10+输入的参数(number)的结果。估计有人要说了,这需求上面的代码完全可以实现啊,第一个参数你传入10不就完了么,ok,如果你是这样想的,我也是无可奈何。还有人可能说了,再写一个重载,只要一个参数即可,实际情况是不容许,我们在调用别人提供的api,无法添加重载。可以看到局部套用的使用场景不是一种很普遍的场景,所以在合适的场景配合合适的技术才是最好的设计,我们来看局部套用的实现:
public Func AddTwoNumberCurrying()
{
Func addCurrying = x => y => x + y;
return addCurrying;
}
表达式x => y => x + y得到的函数签名为Func,这个函数签名非常清楚,接收一个int类型的参数,得到一个Func类型的函数。此时如果我们再调用:
//Act
var curringResult = curringReasoning.AddTwoNumberCurrying()(10);
var result = curringResult(2);
//Assert
result.Should().Be(12);
这句话:var curringResult = curringReasoning.AddTwoNumberCurrying()(10); 生成的函数就是只接收一个参数(number),且可以计算出10+number的函数。
同样的道理,三个数相加的函数:
public Func AddThreeNumber()
{
return (x, y, z) => x + y + z;
}
局部套用版本:
public Func> AddThreeNumberCurrying()
{
Func> addCurring = x => y => z => x + y + z;
return addCurring;
}
调用过程:
[Test]
public void Three_number_add_test()
{
//Arrange
var curringReasoning = new CurryingReasoning();
//Act
var result1 = curringReasoning.AddThreeNumber()(1, 2, 3);
var curringResult = curringReasoning.AddThreeNumberCurrying()(1);
var curringResult2 = curringResult(2);
var result2 = curringResult2(3);
//Assert
result1.Should().Be(6);
result2.Should().Be(6);
}
当函数参数多了之后,手动局部套用越来越不容易写,我们可以利用扩展方法自动局部套用:
public static Func Curry(this Func func)
{
return x => y => func(x, y);
}
public static Func> Curry(this Func func)
{
return x => y => z=>func(x, y,z);
}
同样的道理,Action签名的函数也可以自动套用
有了这些扩展方法,使用局部套用的时候就更加easy了
[Test]
public void Should_auto_curry_two_number_add_function()
{
//Arrange
var add = _curringReasoning.AddTwoNumber();
var addCurrying = add.Curry();
//Act
var result = addCurrying(1)(2);
//Assert
result.Should().Be(3);
}
好了,局部套用就说到这里,stackoverflow有几篇关于currying使用的场景和定义的文章,大家可以继续了解。
函数式编程还有一些重要的思想,例如:纯函数的缓存,所为纯函数是指函数的调用不受外界的影响,相同的参数调用得到的值始终是相同的。尾递归,单子,代码即数据(.net中的表达式树),部分应用,组合函数,这些思想有的我也仍然在学习中,有的还在思考其最佳使用场景,所以不再总结,如果哪天领会了其思想会补充。
四、设计案例
最后我还是想设计一个场景,把高阶函数,lambda表达式,泛型方法结合在一起,我之所以设计这样的例子是因为现在很多的框架,开源的项目都有类似的写法,也正是因为各种技术和思想结合在一起,才有了极富有表达力并且非常优雅的代码。
需求:设计一个单词查找器,该查找器可以查找某个传入的model的某些字段是否包含某个单词,由于不同的model具有不同的字段,所以该查找需要配置,并且可以充分利用vs的智能提示。
这个功能其实就两个方法:
private readonly List _conditions;
public WordFinder Find(Func expression)
{
Func searchCondition = word => expression(_model).ToString().Split(' ').Contains(word);
_conditions.Add(searchCondition);
return this;
}
public bool Execute(string wordList)
{
return _conditions.Any(x=>x(wordList));
}
使用:
[Test]
public void Should_find_a_word()
{
//Arrange
var article = new Article()
{
Title = "this is a title",
Content = "this is content",
Comment = "this is comment",
Author = "this is author"
};
//Act
var result = Finder.For(article)
.Find(x => x.Title)
.Find(x => x.Content)
.Find(x => x.Comment)
.Find(x => x.Author)
.Execute( "content");
//Assert
result.Should().Be(true);
}
该案例本身不具有实用性,但是大家可以看到,正是各种技术的综合应用才设计出极具语义的api, 如果函数参数改为Expression 类型,我们还可以读取到具体的属性名称等信息。
相关文章:

wowpve服务器优势,PVE服务器法师对本职业的一点看法
看过了各位高手的对法师的一些看法,其中被喷的也不在少数,其实大家公认的在魔兽世界里没有最强的职业,只有更强的玩家,所有流派的诞生都是各位玩家在不断的探索中发现的,我是一个休闲法师玩家在这里只谈谈自己的一些看…

安装Android SDK需要选择哪些,开始为Android开发,我应该选择安装哪些SDK?
我开始将我的开发人员技能扩展到Android开发.我安装了所有的工具和配置,每件事看起来都很棒,作为默认设置,我安装了3.2 SDK,但是没有太多的文档在那个,2.x SDK上的模式是什么.它是否像IOS,android有一个良好的向后可计算性?我可以继续使用3.x并依靠它(使用2.x SDK中…

oracle 分区使用情况,Oracle Hash分区的使用总结
近期项目需要用到分区表,但是分区键值有无法确定,因此只能使用hash分区(range、list分区以前常用,比hash分区简单),查询了文档,发现上面说的和实际使用时有点差距,就专门做实验验证下。官方文档(11g、12c的…

第四周工作总结
转载于:https://www.cnblogs.com/yuezhihao/p/6587333.html

VS2013\VS2017 使用git 总是需要输入账号密码
问题: VS2013\VS2017 使用git 总是需要输入账号密码 解决方案:删除原凭证,或者修改原凭证,重新输入一次账号和密码并且选择“记住凭证”即可! 转载于:https://www.cnblogs.com/zhaokunbokeyuan256/p/9583091.html

css炫酷标题,纯css3鼠标滑过图片炫酷标题显示特效
很多网站的图片鼠标滑过显示标题效果都是使用jQuery来完成的,现在,我们可以使用CSS3 animations来完成同样惊艳的效果。如果你对CSS3 animations还不了解,请先阅读CSS3 animations。HTML我们使用html5来制作这款插件。通过figure和figcaption…

学习成长就到鸿蒙思维,庆国庆,迎中秋,鸿蒙教育享双节99元开启思维之旅!!...
原标题:庆国庆,迎中秋,鸿蒙教育享双节99元开启思维之旅!!庆国庆,迎中秋,鸿蒙教育享双节99元开启思维之旅!!鸿蒙口才+绘画课推出99元体验课程!学1科…

String拼接字符串效率低,你知道原因吗?
面试官Q1:请问为什么String用""拼接字符串效率低下,最好能从JVM角度谈谈吗? 对于这个问题,我们先来看看如下代码: public class StringTest {public static void main(String[] args) {String a "abc&…

oracle01003,ORA-01003:nostatementparsed-Oracle
手贱,故意删除了一张表,在OGG同步数据的同时,删除之后立刻报错,如下:OCI Error ORA-12096: error in materialized view log on "JTINFO"."TBL_USERID"ORA-01003: no statement parsed (status 1…

笔记一:python安装和执行
一:学习内容 python安装python简介python执行二:python安装 1. 下载python,网地址:https://www.python.org/,进入地址后,点击下载downloads下的windows 2. 进入下载页后,选择要下载的版本和类型…

一个客户机-服务器系统使用了卫星网络,客户机/服务器体系结构可用于局域网、广域网和WWW。这三种用途迥异的网络的一个共同特点是工作负 - 试题答案网问答...
相关题目与解析关于客户机/服务器体系结构的错误说法是()A.曾经是一种流行的结构B.可用于广域网C.不可用于万●C/S(客户机/服务器)与B/S(浏览器服务器)体系结构的区别是:(57)。(57)A.B/S建立在局域网上,C/S●C/S(客户机/服务器)与…

android 初始化语言,3.4.1 Android初始化语言(1)
3.4 init.rc文件解析过程init.rc文件按照一定的格式组织,要分析init.rc文件的解析过程,首先要熟悉它的格式。init.rc的文件格式由Android初始化语言(Android Init Language)定义,所以这里首先分析Android初始化语言。3.4.1 Android初始化语…

[bzoj3673/3674可持久化并查集加强版]
n个集合 m个操作 操作: 1 a b 合并a,b所在集合 2 k 回到第k次操作之后的状态(查询算作操作) 3 a b 询问a,b是否属于同一集合,是则输出1否则输出0 0<n,m<2*10^5 强制在线。 这两题一题都一样,另一题比较水,nm只有2*10^4,允许…

[Manthan, Codefest 18][Codeforces 1037E. Trips]
题目链接:1037E - Trips 题目大意:有n个人,m天,每天晚上都会有一次聚会,一个人会参加一场聚会当且仅当聚会里有至少k个人是他的朋友。每天早上都会有一对人成为好朋友,问每天晚上最多能有多少人参加聚会。朋…

oracle 10g undo 管理,Oracle 10g undo表空间管理
一、oracle 9i起,有两种undo管理方式:AUM Automatic Undo ManagementMUN Manual Undo Management建议使用 AUM ,下面只讨论AUM一、Oracle 9i起,有两种undo管理方式:AUM Automatic Undo ManagementMUN Manual Undo Mana…

电子狗显示连接不上服务器,大家觉得我这样做得对吗?行车记录仪新名词:云狗...
“云”概念化已经成为新轮的市场趋势,些行车记录仪品牌已经加入云狗功能,云狗普通的电子狗有什么区别?“云”概念对于行车记录仪行业发展的意义何在?何谓“云电子狗”?云电子狗指通过无线互联网络具备实时与中…

织梦html引入html代码,织梦标签引入共html.doc
织梦标签引入共html1.无法在这个位置找到: {dede:include filename"织梦模板include插入非模板目录文件出现“无法在这个位置找到”错误的解决办法以下是dede V55_UTF8查dede include标签手册(3) include 引入一个文件,形式为:{dede:include file文…

AutoMapper用法
AutoMapper是对象到对象的映射工具。在完成映射规则之后,AutoMapper可以将源对象转换为目标对象。 作者:齐飞 原文:http://www.qeefee.com/article/automapper 配置AutoMapper映射规则 AutoMapper是基于约定的,因此在实用映射之前…

【洛谷习题】小A点菜
虽然也是一道dp的入门题,但就是想不到,或者说不会实现。dp还是要多做题。 链接:https://www.luogu.org/problemnew/show/P1164 我们可以设dp[i][j]表示以考虑完第i件,恰好消费j元的方案数。那么dp[i][j]dp[i-1][j]dp[i-1][j-a[i]]…

加载服务器版本信息,传奇服务器端启动加载错误的解决方法
1、启动服务端M2报错的类型2、错误分类,思路理清3、文字总结以下常见现象传奇服务器端启动加载错误解决方法Exception] 物品数据库加载错误![Exception] 魔法数据库加载错误!!! 地图数据加载错误.Code -1 加载Guardlist.txt时出现错误.Code -1 加载MakeItem.txt时出…

股票移动平均线matlab,股票的移动平均线 (图文)
股票的移动平均线【泸指】股票的移动平均线移动平均线是个强大的工具,能够更清晰地展示一系列无规律的数值变化 (比如股市波动)。此外,泸指移动平均线还可别除任何周期性变化(正常的季节性温度变化)的影响,便于我们观察到真正的趋势变化。移动…

htcd816+android密码,HTC Desire 816刷机解锁教程
一、解锁前的准备:1.解锁将会丢失所有数据,请先做好备份,如电话本、短信、照片、应用程序。2.下载并安装驱动程序HTC Driver。3.注册HTC Dev帐号,为提交解锁码做好准备。4.下载并解压 “Desire 816 解锁工具”:5.手机关…

BZOJ1058 [ZJOI2007]报表统计 set
原文链接https://www.cnblogs.com/zhouzhendong/p/BZOJ1058.html 题目传送门 - BZOJ1058 题解 考虑用两个 multiset 分别维护两个答案。 一个直接按照权值维护,另一个维护一下相邻位置的差。 比较容易想到如何维护的吧,不多讲,看代码吧。 代码…

扫描服务器端口信息工具,服务器端口扫描工具
服务器端口扫描工具 内容精选换一换2.3.2 端口扫描Internet上的大部分服务都使用一种基于TCP/IP协议的客户机/服务器的模式。在这种模式下,服务器端在某个TCP或UDP(User Datagram Protocol,用户数据报协议)的端口处于侦听状态,等待客户端程序…

python-Django-01基础配置
参考资料地址 http://www.ziqiangxuetang.com/django/django-install.html 官方文档 一: 1先下载Django源码包,下载地址https://www.djangoproject.com/download/ 然后下载自己想安装的版本 Django 1.5.x 支持 Python 2.6.5 Python 2.7, Python 3.2 和 3…

linux进程 网络占用率,linux CPU SI软中断比较占用率比较大(网络解决方案)
https://my.oschina.net/323148/blog/724408irq 默认linux自动启动的,但是往往它自己控制不是很好(CPU SI经常某个CPU占用大)通常碰到大流量的,通常我们会把自动启动的irqblance关闭,然后手动指定一下IRQ进行优化:看CPU的 si利用率…

android设备未指定怎么办,APKpath未指定为模块“示例 – 示例”
退出Android工作室 。 用pipe理员权限启动它。这解决了Windows 7中的 Android Studio v0.1的问题。我有同样的问题,我没有select 2个文件,然后收到错误"ERROR: APK path is not specified for module"我刚刚重新启动Android Studio并重新打开该…

链表 -- 双向循环链表(线性表)
1,双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱。所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。一般我们都构造双向循…

开发脚本自动部署及监控
1.编写脚本自动部署反向代理、web、nfs; 要求: I、部署nginx反向代理三个web服务,调度算法使用加权轮询; #!/bin/shngxStatusps aux | grep -v grep |grep -c nginxfunction ngxProxyInstall() { if [ -e /usr/sbin/nginx ];the…

服务器日志显示乱码,CentosOS 6.5 服务器 控制台输出中文乱码,日志打印中文也乱码...
系统是Centos 6.5使用localeLANGen_US.UTF-8LC_CTYPE"en_US.UTF-8"LC_NUMERICzh_CN.UTF-8LC_TIME"en_US.UTF-8"LC_COLLATE"en_US.UTF-8"LC_MONETARYzh_CN.UTF-8LC_MESSAGES"en_US.UTF-8"LC_PAPERzh_CN.UTF-8LC_NAMEzh_CN.UTF-8LC_ADDR…