您现在的位置:首页
--> 老赵点滴
谁都知道.NET(的大部分组件)是不开源的,但是我不止在一个场合不止一次地强调过,“不开源”不代表你没法看代码,不代表你没法知道里面发生了什么。这里我不是在说.NET Reflector或是ILSpy这类反编译工具,当然它们在平时开发中也起到了很大的作用,不过很多时候更直接的方式便是阅读代码本身,尤其是当你像我一样时不时要“抄”点代码的时候。由于最近我在Tmc中“大张旗鼓”地使用.NET中BCL的代码,因此也再次强调一下这部分经验。
最近的工作让我想到了一个对集合的元素进行并行聚合的案例,尽管这个需求还不存在,但最近却一直在我的脑海里挥之不去,尚未得出令人满意的结果。今天下班前我将这个问题辛苦地缩减为140字内的描述发到了微博上,得到了许多同学的回复,但可能是由于描述过于简单,得到的建议似乎都不能满足我的需求。于是在此我通过博客详细描述下这个问题的需求,还有我之前做过的尝试,这样讨论起来也可以更加有针对性一些。
在命令式编程中,我们解决一些问题往往可以使用循环来代替递归,这样便不会因为数据规模造成堆栈溢出。但是在函数式编程中,要实现“循环”的唯一方法便是“递归”,因此尾递归和CPS对于函数式编程的意义非常重大。了解尾递归,对于编程思维也有很大帮助,因此大家不妨多加思考和练习,让这样的方式为自己所用。
以前我也在博客上简单谈过“尾递归”及其优化方式方面的话题。前几天有同学在写邮件向我提问,说是否所有的递归算法都能改写为尾递归,改写成尾递归之后,是否在时间和空间复杂度方面都能有所提高?他以斐波那契数列为例,似乎的确是这样的情况。我当时的回答有些简单,后来细想之后似乎感觉有点问题,而在仔细操作之后发现事情并没有理论上那么简单,因此还是计划写篇文章来讨论下这方面的问题。 斐波那契数列 大家对于斐波那契数列(Fibonacci)的认识一定十分统一,唯一的区别可能仅在于n是从0开始还是从1开始算起。
相对于Java的假泛型(编译型泛型,类型擦除)来说,真泛型是.NET的一个亮点。Anders Heisenberg多次提到.NET的真泛型有利于编程语言的进一步发展,可以带来更丰富的编程模型。不过.NET支持的泛型是一方面,具体到语言本身则又涉及到编译器的实现,而编译器的实现又收到运行时的限制等等,所以要谈语言的设计缺陷的“原因”就会变得很复杂。不过这里我们就把C#作为一个“成品”来对待,谈下它不允许以void作为泛型参数的“后果”,“原因”则略为一提,不做深究。 泛型的限制 话说C#中泛型是很常用的特性,很多朋友都应该遇到过一些这方面令您不爽的地方。
其实使用C#这么多年,我时不时会遇到一些令人不爽的设计缺陷。这些缺陷大都是些限制,虽说无伤大雅,也很容易避免,但一旦遇到这些情况,总会令人心生不快,毕竟都是些无谓的限制。而且令人遗憾的是,虽说去除这些限制也不会带来什么问题,但我认为C#设计团队也基本不会去修复这些问题了,毕竟它们大都是些细枝末节。作为一名用C#的纯种码农,我突然一时兴起也要把这些设计缺陷记录下,也方便和大伙一起讨论下。那么这次就先从实现接口内的事件说起,当我们需要显式实现一个接口内的事件时,会发现我们必须提供add和remove访问器,这还会稍许影响到事件常用的使用模式。 强制add和remove访问器 这个问题听上去有些绕,不过看代码便一清二楚。
任何异步编程的类库要做的第一件事往往便是统一异步编程的模型,例如Jscex的异步模块自带一个类似于.NET中的异步任务模型。围绕统一的模型,开发人员便可以尽情地提供各种扩展,例如Jscex异步增强模块中的whenAll或whenAny一样。换句话说,假如要混用两种异步编程模型,往往需要将其中一种适配至另外一种,因此异步增强模块中也提供了fromCallback及fromStandard辅助,能够轻易地将最简单的(也是Node.js里使用的)两种异步函数接口绑定为异步任务。
最近有段十分流行的代码,是从江湖传闻“身怀八蛋”的铁道部发言人王勇平同志的一句名言:“不管你们信不信,反正我信了……这是生命的奇迹……它就是发生了”所引申出来的。这段代码虽然只是在调侃,但是围绕这段代码也产生了一些讨论(如代码风格,编程规范等等),在此顺手记录一下,就当无聊罢。
昨晚跟一位Node.js专家讲解了我的Wind.js类库。之前那位仁兄对Jscex(Wind.js的前身)的看法是“就是不喜欢”,也在微博上对Jscex冷嘲热讽,于是我私信他说建议看一下文档了解一下Jscex。昨天我们的争论主要围绕在eval的使用上,他认为更好的做法是像CoffeeScript那样使用一个额外的进程监听改变,这样更方便。我说CoffeeScript这么做是因为它没有像Wind.js那样借助eval实现完全动态的运行时转化,且生产环境中不会出现eval。最后他坚持认为“eval就是有性能问题”,因此开发时也不应该使用,否则Wind.js为什么要提供预编译器?虽然最后不欢而散,不过我忽然也打算验证一下eval生成的代码效率到底会差到什么样的地步,于是便有了这次试验。 测试代码 有人可能会问,eval每次动态的执行代码时需要重新分析代码,还不能进行优化,为什么会“不慢”?
我很喜欢编程语言,但我争论语言时有着基本的原则和必备的知识,没有这些在我看来就不应该参与讨论。讨论时我也会严格控制范围,因此我基本不会使用类比,因为类比其实就是在用外部知识来理解当前的话题,很容易把话题扯开出去。同理,我也不会像高级分析师们讲一些初级程序员们都懂——但往往我不怎么理解或赞同的大道理。我就是怎么没出息,就像今天早上还有人在IM上对我说“老赵怎么可能还在写程序,你是冒牌的吧?”。
今天早上一边出门一边在平板上读了左耳朵耗子的新文章《为什么我反对纯算法面试题》,略有想法。正逢外面暴雨如注,我就又回屋打开笔记本发了一些回复,特此整理一下。为了避免有人扭曲我的看法,我先声明我并不是反对这篇文章,相反我是基本同意其中的观点,只不过会加以一些补充,把其中一些我认为有些过头的地方按一按。您也可以认为我的观点是提交一些补丁,发了一些Pull Request(当然不是这种Pull Request)就行了。我当时吐的第一个槽,是说文章太鄙视搞学术研究的人,说他们是书呆子,不关心业务需求,认为那是应试教育不会思考的产物。这个么其实不是重点,只不过触到了我的学术研究情结罢了,接下来的才是我真正想说的。 耗子的文章以前两天的一个讨论引出话题,那是一道面试题:“找出无序数组的第2大的数”,而在当时的面试中,“排序”后再取数被判为不合格的答案。
最近一直在努力推广Jscex,补充了很多中文文档和示例,因此博客上都已经有两篇文章有了“上”而没有“下”,即使最复杂的图示也已经绘制完毕。在推广Jscex的过程中,我发现有个比较明显的问题是,许多使用JavaScript的程序员已经习惯旧有的编程方式,甚至推崇一些据他们说很“漂亮”的模式。但在我看来,这其实跟许多GoF模式是在修补OO语言的不足有些类似,很多异步模式都只是因为JavaScript语言特性不足而设计出来的“权宜之计”。我们在传统JavaScript编程环境下并没有其他选择,单纯地认为这是“美”,说实话只不过是一种安慰罢了。 Jscex的重头戏便是处理异步操作,但异步操作并不只是如Node.js中通过回调函数传回结果的那些方法,或者是网页上的AJAX请求等等。异步操作的定义其实可以概括成“会在未来某个时刻完成的操作”,就只是这么简单。什么事情会在未来发生,那么它对你来说就是个
JavaScript的包管理一直是个软肋,我很难想象,连这一基础功能都没有做好的语言,现在居然会如此流行。在我看来,其实JavaScript流行的最主要元素还是把持了浏览器,而Web应用在这几年掀起了一阵腥风血雨。任意一门语言,只要能像JavaScript般被标准采纳,被所有浏览器接受,它都能“成功”,真是所谓宿命。 当然,既然它流行了,既然人们想要用它做大事了,就要开始为它制定一些模块的约定。这几天我为Jscex实现AMD规范的时候,...
时不时听到一些C#程序员说,希望在C#里出现像Java匿名类一样的特性。以前我也觉得Java里的匿名类是个不错的特性,C#应该吸取进来。不过前段时间我仔细地理解了Java语言规范中关于内部类、匿名类的部分之后,一下子就被恶心到了。恶心过后,我忽然也意识到有些问题的确也是硬伤,也不能指责Java设计者的“品位”。例如,现在我想要谈的关于匿名类中this使用的问题――如果C#没法漂亮地实现这个特性,我宁愿它继续保持现状。 Java匿...
时不时听到一些C#程序员说,希望在C#里出现像Java匿名类一样的特性。以前我也觉得Java里的匿名类是个不错的特性,C#应该吸取进来。不过前段时间我仔细地理解了Java语言规范中关于内部类、匿名类的部分之后,一下子就被恶心到了。恶心过后,我忽然也意识到有些问题的确也是硬伤,也不能指责Java设计者的“品位”。例如,现在我想要谈的关于匿名类中this使用的问题――如果C#没法漂亮地实现这个特性,我宁愿它继续保持现状。 Java匿...
• IBM面试记
话说其实我很久没有被正经面试过了。一开始去微软实习自然经过了经典的笔试和几轮面试,然后去了朋友的创业公司并立即被激动集团收编――没有面试,接着从激动集团去合伙创业――没有面试,然后被朋友推荐去盛大创新院――面试更像是讨论及聊天。由于长久缺乏职场磨练,我虽然对自己能力有一定信心,但也怀疑自己如果通过“正经渠道”去面试的话能有多少机会成功。而这次面试IBM终于算是过足了面试瘾,记录一下。 大约一两个月前...
话说大家对于switch语句应该再熟悉不过了,各种类C语言都不例外,JavaScript自然也是如此。switch的逻辑很简单,根据switch内容的值执行对应的case项,否则执行default项即可。但是不同的语言在具体一些细节上面的处理却是不同的。例如在JavaScript里,每个case项都可以没有break,于是语句便会顺延到下个case或是default里面去――但某些语言设计者认为这种特性容易造成代码理解上的偏差,因此比如在C#里便要求每个非空的case都要...
用动画来观察排序算法是一件很酷的事情,例如有人便为各种排序算法提供了动画效果。只可惜这些效果都是实现准备好的gif图片,并非由代码写成。在大部分平台上编写这样的程序并没有太大困难,只要在绘制出图形之后短暂地阻塞线程就行了。可惜,在JavaScript中我们只能“一蹴而就”,要暂停的话,只能使用setTimeout进行回调了。不过,这也正是Jscex的用武之地,用Jscex编写的代码需要“暂停”,只需要简单地调用sleep异步方法,一切...
我一直在为Jscex寻找好用的JavaScript解析器,之前我用的是Narcissus,也写过相关文章。不过可惜的是,Narcissus使用了SpiderMonkey的扩展,因此它并不是用ECMAScript 3实现的,无法在IE 8等浏览器中使用。目前Jscex使用的是NarrativeJS中旧版的Narcissus,但是我并不喜欢它输出的AST结构,使用中也发现高级功能里的一些bug,有些食之无味弃之可惜的感觉,而改写新版Narcissus又必须大动干戈。最近我接触到了UglifyJS,发现它的解...
JavaScript压缩代码的重要性不言而喻,如今的压缩工具也有不少,例如YUI Compressor,Google Closure Compiler,以及现在比较红火的UglifyJS。UglifyJS的出名是由于它代替Closure Compiler成为jQuery项目的压缩工具。根据我的实测,jQuery Core的代码使用UglifyJS压缩后(节省62.5%)的确要比Closure Compiler压缩后(节省57.53%)更小一些。很显然,这是因为UglifyJS的压缩策略比Closure Compiler更“聪明”一些。
近3天十大热文
- [69] Twitter/微博客的学习摘要
- [64] find命令的一点注意事项
- [64] 如何拿下简短的域名
- [64] IOS安全–浅谈关于IOS加固的几种方法
- [63] android 开发入门
- [62] Go Reflect 性能
- [61] 流程管理与用户研究
- [59] Oracle MTS模式下 进程地址与会话信
- [58] 读书笔记-壹百度:百度十年千倍的29条法则
- [58] 图书馆的世界纪录
赞助商广告