Lisp的永恒之道

Lisp的永恒之道

感谢 Todd投递本文 – 微博帐号:weidagang

Lisp之魅

长久以来,Lisp一直被许多人视为史上最非凡的编程语言。它不仅在50多年前诞生的时候带来了诸多革命性的创新并极大地影响了后来编程语言的发展,即使在一大批现代语言不断涌现的今天,Lisp的诸多特性仍然未被超越。当各式各样的编程语言摆在面前,我们可以从运行效率、学习曲线、社区活跃度、厂商支持等多种不同的角度进行评判和选择,但我特别看中的一点在于语言能否有效地表达编程者的设计思想。学习C意味着学习如何用过程来表达设计思想,学习Java意味着学习如何用对象来表达设计思想,而虽然Lisp与函数式编程有很大的关系,但学习Lisp绝不仅仅是学习如何用函数表达设计思想。实际上,函数式编程并非Lisp的本质,在已经掌握了lambda、高阶函数、闭包、惰性求值等函数式编程概念之后,学习Lisp仍然大大加深了我对编程的理解。学习Lisp所收获的是如何“自由地”表达你的思想,这正是Lisp最大的魅力所在,也是这门古老的语言仍然具有很强的生命力的根本原因。

Lisp之源

Lisp意为表处理(List Processing),源自设计者John McCarthy于1960年发表的一篇论文《符号表达式的递归函数及其机器计算》。McCarthy在这篇论文中向我们展示了用一种简单的数据结构S表达式(S-expression)来表示代码和数据,并在此基础上构建一种完整的语言。Lisp语言形式简单、内涵深刻,Paul Graham在《Lisp之根源》中将其对编程的贡献与欧几里德对几何的贡献相提并论。

Lisp之形

然而,与数学世界中简单易懂的欧氏几何形成鲜明对比,程序世界中的Lisp却一直是一种古老而又神秘的存在,真正理解其精妙的人还是少数。从表面上看,Lisp最明显的特征是它“古怪”的S表达式语法。S表达式是一个原子(atom),或者若干S表达式组成的列表(list),表达式之间用空格分开,放入一对括号中。“列表“这个术语可能会容易让人联想到数据结构中的链表之类的线形结构,实际上,Lisp的列表是一种可嵌套的树形结构。下面是一些S表达式的例子:

foo

()

(a b (c d) e)

(+ (* 2 3) 5)

(defun factorial (N)
    (if (= N 1)
        1
        (* N (factorial (- N 1)))
    )
)

阅读全文 Read More

好烂啊有点差凑合看看还不错很精彩 (27 人打了分,平均分: 4.33 )
Loading...
Javascript 中的 var

Javascript 中的 var

MelonCard发布了一篇文章——”how one missing var ruined our launch“(”少写了一个var毁了我的网站”),这篇文章是说MelonCard用Node.js做后台,因为出了一个小高峰——有50-100人注册,结果整个网站都不响应了,而且还出现了很多奇怪的问题。当他们调查到问题的要源的时候,他们发现下面的代码少写了一个var。

[javascript]app.all(‘/apps/:user_id/status’, function(req, res, next) {
// …
initial = extractVariables(req.body);
});[/javascript]

为什么inital少写一个var会引发这个问题呢?因为如果你不写var,这个局部的变量会被javascript当成全局变量,而这个变量又是一个函数,所以,当多用户并发的时候,这个本应该在不同用户下互不干扰的变量,成了各个用户共享的东西。试想,用户A的数据被用户B覆盖了,用户A和B的数据还没处理完,结果被新的C给搞乱了,程序的逻辑自然出现了问题。

在stackoverflow.com上有这么一个贴子说明了“有var”和“无var”的差别:

// These are both globals
var foo = 1;
bar = 2;

function test()
{
    var foo = 1; // Local
    bar = 2;     // Global

    // Execute an anonymous function
    (function()
    {
        var wibble = 1; // Local
        foo = 2; // Inherits from scope above (creating a closure)
        moo = 3; // Global
    }())
}

上面这个示例告诉我们,如果你不用var,那么这个js引擎会一层一层地向上找父作用域中的变量,如果找到了,就用,如果找不到了,就会帮你定义一个全局的变量。上面这个例子充分说明了这一点。所以,如果你想在当前的作用域用声明变量,你一定要用var。这对于一些乱写javascript代码的程序员要注意了。这里再给大家介绍一个工具——

阅读全文 Read More

好烂啊有点差凑合看看还不错很精彩 (16 人打了分,平均分: 3.94 )
Loading...
Huffman 编码压缩算法

Huffman 编码压缩算法

前两天发布那个rsync算法后,想看看数据压缩的算法,知道一个经典的压缩算法Huffman算法。相信大家应该听说过 David Huffman 和他的压缩算法—— Huffman Code,一种通过字符出现频率,Priority Queue,和二叉树来进行的一种压缩算法,这种二叉树又叫Huffman二叉树 —— 一种带权重的树。从学校毕业很长时间的我忘了这个算法,但是网上查了一下,中文社区内好像没有把这个算法说得很清楚的文章,尤其是树的构造,而正好看到一篇国外的文章《A Simple Example of Huffman Code on a String》,其中的例子浅显易懂,相当不错,我就转了过来。注意,我没有对此文完全翻译。

我们直接来看示例,如果我们需要来压缩下面的字符串:

 “beep boop beer!” 

首先,我们先计算出每个字符出现的次数,我们得到下面这样一张表 :

字符 次数
‘b’ 3
‘e’ 4
‘p’ 2
‘ ‘ 2
‘o’ 2
‘r’ 1
‘!’ 1


然后,我把把这些东西放到Priority Queue中(用出现的次数据当 priority),我们可以看到,Priority Queue 是以Prioirry排序一个数组,如果Priority一样,会使用出现的次序排序:下面是我们得到的Priority Queue:

阅读全文 Read More

好烂啊有点差凑合看看还不错很精彩 (24 人打了分,平均分: 4.17 )
Loading...
扎克伯格的一封信:关于Facebook IPO

扎克伯格的一封信:关于Facebook IPO

MENLO PARK, CA (The Borowitz Report) – 在Fackbook IPO前夕,Facebook的创始人兼CEO Mark Zuckerberg 给全球股民发表了封公开信:

亲爱的股民们:

    这么多年来,你们已经在Facebook上浪费了你们的时间 ,接下来,你们会得到浪费你们金钱的机会。

   明天是Facebook的IPO,并且我知道你们一定在想,Facebook怎么就和2000年的.COM泡沫不一样啦?

首先,我想告诉你们,以前那些糟糕的dot-com公司玩的是概念和炒作,而没有真正的商业价值。而Facebook不一样,也就是说,我们Facebook是建立在强大的以“疯狂的小鸟”和“一群想像中的羊”的基础上的。

其次,Facebook是世界上最成功的社交网络,我们的用户最近才发现,这个社交网络让人们分享了数以万计别人根本不感兴趣的信息。

第三,当某人点击Faceback广告的时候,我们就会挣到钱。而且我们知道,点我们广告的人都不是故意点击,成百万的人点我们的广告是因为那时他们喝醉了。我们完全从iTunes偷到这个有创意的想法。

最后,如果你买我们的股票,你将永远不会孤独。据调查,在过去几年里使用facebook的全球9亿用户,他们都有轻微或中等程度的大脑损伤,这影响了他们的作正常判断的能力。所以,这些人都成为你的朋友——Facebook的股民。

有了你的帮助,如果明天一切都照计划进行,Facebook IPO将会募到1000亿美金。这是个什么概念,这相当于4到5个摩根大通银行损失的钱。

最后一件事:我,Mark Zuckerberg,是否会因此IPO获得180亿美金? 也许,我正在考虑把希腊买了,但就算是这样,我还是有180亿美金。 LOL.

Friend me (粉我),

Mark

好烂啊有点差凑合看看还不错很精彩 (22 人打了分,平均分: 3.64 )
Loading...
rsync 的核心算法

rsync 的核心算法

rsync是unix/linux下同步文件的一个高效算法,它能同步更新两处计算机的文件与目录,并适当利用查找文件中的不同块以减少数据传输。rsync中一项与其他大部分类似程序或协定中所未见的重要特性是镜像是只对有变更的部分进行传送。rsync可拷贝/显示目录属性,以及拷贝文件,并可选择性的压缩以及递归拷贝。rsync利用由Andrew Tridgell发明的算法。这里不介绍其使用方法,只介绍其核心算法。我们可以看到,Unix下的东西,一个命令,一个工具都有很多很精妙的东西,怎么学也学不完,这就是Unix的文化啊。

本来不想写这篇文章的,因为原先发现有很多中文blog都说了这个算法,但是看了一下,发现这些中文blog要么翻译国外文章翻译地非常烂,要么就是介绍这个算法介绍得很乱让人看不懂,还有错误,误人不浅,所以让我觉得有必要写篇rsync算法介绍的文章。(当然,我成文比较仓促,可能会有一些错误,请指正)

问题

首先, 我们先来想一下rsync要解决的问题,如果我们要同步的文件只想传不同的部分,我们就需要对两边的文件做diff,但是这两个问题在两台不同的机器上,无法做diff。如果我们做diff,就要把一个文件传到另一台机器上做diff,但这样一来,我们就传了整个文件,这与我们只想传输不同部的初衷相背。

于是我们就要想一个办法,让这两边的文件见不到面,但还能知道它们间有什么不同。这就出现了rsync的算法。

算法

rsync的算法如下:(假设我们同步源文件名为fileSrc,同步目的文件叫fileDst

阅读全文 Read More

好烂啊有点差凑合看看还不错很精彩 (39 人打了分,平均分: 4.51 )
Loading...
NoSQL 数据建模技术

NoSQL 数据建模技术

全文译自墙外文章“NoSQL Data Modeling Techniques”,译得不好,还请见谅。这篇文章看完之后,你可能会对NoSQL的数据结构会有些感觉。我的感觉是,关系型数据库想把一致性,完整性,索引,CRUD都干好,NoSQL只干某一种事,但是牺牲了很多别的东西。总体来说,我觉得NoSQL更适合做Cache。下面是正文——

NoSQL 数据库经常被用作很多非功能性的地方,如,扩展性,性能和一致性的地方。这些NoSQL的特性在理论和实践中都正在被大众广泛地研究着,研究的热点正是那些和性能分布式相关的非功能性的东西,我们都知道 CAP 理论被很好地应用于了 NoSQL 系统中(陈皓注:CAP即,一致性(Consistency), 可用性(Availability), 分区容忍性(Partition tolerance),在分布式系统中,这三个要素最多只能同时实现两个,而NoSQL一般放弃的是一致性)。但在另一方面,NoSQL的数据建模技术却因为缺乏像关系型数据库那样的基础理论没有被世人很好地研究。这篇文章从数据建模方面对NoSQL家族进行了比较,并讨论几个常见的数据建模技术。

要开始讨论数据建模技术,我们不得不或多或少地先系统地看一下NoSQL数据模型的成长的趋势,以此我们可以了解一些他们内在的联系。下图是NoSQL家族的进化图,我们可以看到这样的进化:Key-Value时代,BigTable时代,Document时代,全文搜索时代,和Graph数据库时代:(陈皓注:注意图中SQL说的那句话,NoSQL再这样发展下去就是SQL了,哈哈。)


NoSQL Data Models

首先,我们需要注意的是SQL和关系型数据模型已存在了很长的时间,这种面向用户的自然性意味着:

阅读全文 Read More

好烂啊有点差凑合看看还不错很精彩 (17 人打了分,平均分: 3.76 )
Loading...
用Unix的设计思想来应对多变的需求

用Unix的设计思想来应对多变的需求

之前,@风枫峰 在“这是谁的错?”中说过开发团队对需求来者不拒,而@weidagang 也在“需求变更和IoC”中说过用IoC来最大程度地解决需求变更。今天我也想从Unix设计思想的角度来说说什么是好的软件设计,什么样的设计可以把需求变更对开发的影响降低。(注意:这并不能解决用户或是PM的无理需求,面对无理需求,需要仔细分析需求,而用技术的手段无法搞定这个事,但是可以减轻需求变更带来的痛苦) 我曾经在《Unix传奇》的下篇中写过一些Unix的设计哲学和思想(这里重点推荐大家看一下《The Art of Unix Programming》,我推荐过多次了),以前也发过一篇《一些软件设计的原则》,不过,这些东西都太多了,记不住。其实,这么多年来,我的经验告诉我,无论是Unix设计,还是面向对象设计,还是别的什么如SOA,ECB,消息,事件,MVC,网络七层模型,数据库设计,等等,他们都在干三件事——解耦,解耦,还是解耦所谓解耦,就是让软件的模块和模块间尽量少地依赖起来。

现实当中的例子

让我先举几个现实生活中的例子:

1、现实社会中,制造灯具的工厂完全不关心制造灯泡的工厂,制造灯泡的工厂完全不关心制造灯具的工厂,但是,灯泡和灯饰可以很完美地组合成用户所喜欢的样子(这和@weidagang 在“需求变更和IoC”说到的那个PC的例子相仿)。他们是怎么做到的?

2、互联网上,做网站的人完全不用关心用户在用什么样的操作系统,什么样的客户端浏览器(当然事实上,浏览器的不标准让网站那边很头痛,这里只是举个例),反过来,上网的人也不关心做网站的人在用什么的技术开发网站。但是大家在完全不关心对方的情况下,可以很正常地协同工作在一起。为什么?

阅读全文 Read More

好烂啊有点差凑合看看还不错很精彩 (37 人打了分,平均分: 4.38 )
Loading...
做个环保主义的程序员

做个环保主义的程序员

十多年前刚走入社会工作的时候,那时的中国软件开发根本没有什么版本管理,也没有什么编程规范,软件开发相比起今天来说非常地混乱,那时仅凭自己的一些学习总结了一些C语言编程中的好的小笔记,后来,这些笔记写成了一篇叫《编程修养》的文章。今天,又有些感触,想把这个话题扩大一下,从“个人修养”扩大到“环境保护”,所谓,穷则独善其身,富则达济天下,今天的技术人员比十多年前在技术和环境上都富有了许多,所以,也应该或多或少地担负起“达济天下”的责任了。

环境保护说白了就是保护一个良好的环境,为好的环境添砖加瓦,与破坏环境的人和事做斗争。其实,从技术人员来说,我们可以做一些力所能及的事。因为我们身边的技术环境还有很大的改善的空间,而一些来之不易的东西还需要我们去小心维护。另外,对于我们自己来说,少吃一些垃圾食品,健康生活,对自己也有益。

环保主义软件开发

先说说软件开发中的环保。比如:

  • 环保需求。当我们分析需求的时候,如果我们能做到不要像“这是到底是谁的错”一文中那样的来者不拒,如果我们在面对需求能多问这样几个问题:为什么 要有这样的需求?这个功能主要能解决什么 样的问题?为什么不是另外那一种?可不可以简化一下?其实,我们并不需要创新,只需要真正地问好这几个问题,我们就可以少看着一些弯路,少一些苦逼的加班,少一些内耗,少一些埋怨,也就可以为这个社会节省下一些资源,从而环保。
  • 环保开发。当我们做设计写代码的时候,如果我们多花一些时间去思考一下,我们就可以少一些代码(参看“多一些时间少一些代码”)。如果我们在一开始多思考一下,不要急着马上去用迭代的方式认识世界,多思考一下怎么把复杂的东西解藕,把复杂的东西简化,怎么做出一个优雅的设计,怎么让我们的程序少一些tricky的东西,怎么让我们的程序变得更简洁,更清楚,更直,在一开始思考一下未来需求可能的变化,未来软件需要怎么测试,未来的系统需要怎么的运维,那么,我们可以少一些返工,少一些重构,少欠一些债,少一些低级错误,少承担一些系统上线后的压力,那么,我们同样可以为这个社会节约一些资源。说得再直白一点,你用更少的代码产生出更高的效益,少耗一些CPU,就能省一些电,间接地保护了环境。(参看 Why C++?
好烂啊有点差凑合看看还不错很精彩 (150 人打了分,平均分: 4.47 )
Loading...
游戏:VIM大冒险

游戏:VIM大冒险

不知道大家是否还记得“Vim简明攻略”呢?你是不是对Vim的那一大堆热键很头痛呢?现在好好,下面这个游戏是一个使用VIM热键玩的游戏。你可以在玩游戏的过程中熟悉Vim的热键。

你可以点击图片,或是图片下的网址打开这个游戏

http://vim-adventures.com/

VIM大冒险

我试玩了一下这个游戏,真的很不错,下面是一些我给的游戏攻略。

阅读全文 Read More

好烂啊有点差凑合看看还不错很精彩 (37 人打了分,平均分: 4.43 )
Loading...
这到底是谁之错?

这到底是谁之错?

【感谢 @风枫峰 投递本文】

故事一:
背景介绍:RT是一个外包公司,ZWZX是项目承接公司,YD是甲方。

RT公司每天下班的时候都会接到ZWZX负责人的电话,询问一天的工作情况,然后布置任务要求晚上加班做完,RT公司的员工很无奈也很气愤因为每天都要加班,员工们就问项目经理:“为什么天天加班赶需求,今天才提一个需求,明天就要上线,还让不让人活了?” 项目经理无奈的说:“我有什么办法啊?这是人家ZWZX负责人说的啊,对方逼得紧。”

多次以后项目经理也忍不住了,就问ZWZX的负责人怎么天天这样啊,ZWZX的负责人就说了:”明天就要向YD的负责人展示这个页面,我也没有办法啊?YD那边老总就是这么要求的,我怎么办,我也不想这样啊?”

然后RT的项目经理实在受不了了就辞职了,新上任的项目经理又会走他的老路,因为从开始我们就被培养“满足客户的需求是最重要的”。RT的员工也就这样一直抱怨着,一直忍受着。天天在心里咒骂YD的老总真是没有人性,不拿人当人看啊!

人换了一批又一批,加班也就慢慢的变成了应该的,你不加班说明你不敬业,不合格。

故事二:
IE6一直存活着,所有的前端开发人员都痛恨它,都不想兼容它,可是产品经理看到IE6的市场占有率还是这么高,就会要求前端开发人员必须兼容IE6。

阅读全文 Read More

好烂啊有点差凑合看看还不错很精彩 (34 人打了分,平均分: 4.21 )
Loading...