关于霏昀

☑80后 ☑双鱼 ☑猫 ☑技术男 ☑Web前端 ☑秋裤男 ☑窝囊废 ☑内拉祖里 ☑弃机从文中 ☑右派 ☑开放社会敌人的敌人

学习了一下Python的实现

最近在网上看到这个《Python源码剖析》系列,写得很好,赞一下顺便帮着宣传http://blog.donews.com/lemur/,呵呵

顺着看下来,发现Python的实现的确有够糟糕。又引用计数来维护对象进行垃圾回收,每当一个对象的引用计数减到零时就进行回收――我怎么也觉得这是十年以前的技术了。

另外比如对于int和string类型(都是经常被大量创建和销毁的对象)使用了两种不同的缓存机制来加速。但是对于int来说,只有一定区间内(官方版本里是[-5,100)之中)的整数才能被缓存,而区间之外的整数来说都会被创建多个不同的副本。而对于string则是虽然被缓存再利用但是缓存之前字符串一定要被创建一次――也就是说这个机制只能帮助只是帮助比较操作(估计是没说清楚:-p)。本能上觉得应该有更好的做法,但也未必,因为我实际上也就看过这一种实现。

再有的发现就是一个PyPy项目http://codespeak.net/pypy/dist/pypy/doc/news.html,用Python来实现Python。从用Lisp实现Lisp开始,我就没有搞清楚这里的逻辑关系,抽空要把这个项目看一看。

周五晚上去泡酷热

酷玩也被拆了,晕呀。于是去了酷热。

这家也算是北京有名的bar了,气氛热烈那种――估计很多人还是喜欢苍娆那种幽静的坏境。刚到的时候乐队正在那里调音,咿咿呀呀的,还不是很闹。两个人要了半打Budweiser在那里聊天。后来乐队开唱以后基本上就要喊话了,如果不喜欢喧闹的人大概会觉得很吵。开始时总是唱一些我没听说过的歌,到最后也就只有两首歌听过――神话,我是觉得很不适合在酒吧里唱很诡异的感觉;唱嘻唰唰的时候倒是全场气氛热烈。长岛冰茶,可乐有点多,口感发涩。B-52,各处调法都不太一样(基本上是两种甜酒加一种烈酒,甜酒里理论应该有君度),这里像是用的vodka,甜酒就喝不出来了:-),可能是咖啡酒加奶油酒因为有种可可的味道,很喜欢。

黄记煌,美炉村,蜀味浓

黄记煌,焖锅鱼。传说中的三汁焖锅,因为服务员说冬天的鲶鱼不怎么好,就要了推荐的“回鱼”(菜单上写的鱼字旁加个回,输入法没这个字……);另外禽流感所以没有网上很赞的鸡翅,点了2两虾(一共8只);还有就是一些蔬菜豆腐。点完菜,等呀等,很慢,饿死了……最后上来的还是生料,一个服务员把料一层层铺在锅上然后盖上盖子焖,浇上汁。接着等,真的要饿死了……回鱼本身的质感应该还可以,但是这种做法最后吃的时候也焖得没有口感了――如果是草鱼估计就烂了。味道也不是太喜欢,不论鱼虾都是很咸,而不是鲜味。不怎么符合我的口味。服务员的态度倒是很好。

美炉村,江西菜。跟实验室的人一起去的,所以点菜就不归我管了。土鸡汤味道不错,就是太油了。香芋饼赞一下,不过吃的时候不小心掉了半个在桌上,我很ft。有一种笋也不错,名字忘记了。还有一道炒木耳之类的菜,据说木耳是运过来的,不过也就跟市面上比较好的木耳差不多,口感可以。煨南瓜我一向不喜欢这种菜。炖猪蹄,有个师姐说毛没弄干净,就没尝。菜量不大,不过价钱也不贵。总体很一般。

蜀味浓,火锅。进去居然排号排了1号,真是少见。也可以点菜,不过要的是火锅,因为我印象里网上有人推荐这里的鲜兔火锅,不过回来后发现没人推荐过――而且是推荐吃炒菜的人比较多一些――有点很失败……鲜兔火锅,说有一斤多的兔肉吧,不过上来后也没捞出来多少块肉,还是带骨的,总之是不够两个人吃。所以后来又加了一盘羊肉,倒是便宜6元,而且量也不少。锅底料就是很一般的鸳鸯锅。上菜慢……

程序设计语言中的动静融合

 

程序设计语言概论课的作业,1万多字,其中可能有8000多我自己写的吧。贴在这里,把摘抄不是自己写的部分删掉只留标题,所以有些段落可能不够通顺,姑且看之。Word贴过来,格式也许有问题

——————————————————-

动态语言与静态语言概述

我们常用静态语言和动态语言来划分众多的编程语言,其实这种划分并没有明确的界限。相对明确的概念是语言静态特性和动态特性的划分。动态特性是指在运行时刻的语言特性,主要依赖解释器或虚拟机,而静态特性则依赖于编译器。

(对于语言来说,动态这个词在不同的语言中有着不同的表现。对比多种编程语言我们会发现在,某些语言中,大部分关系是在运行之前确定的,即在编写代码,编译或者连接的时候就已经确定了――也就是说静态特性多一些;另一些语言则尽可能地推迟确定的时间,直到运行时才确立许多关系――动态特性多。较多采用静态特性的语言比较倾向于静态,反之就比较倾向于动态。任何一种编程语言都可以看作具有某种程度的动态特性,比如最简单是一个变量可以运行时改变它的值,可以说它也具有动态特性。而Smalltalk和Lisp这样的语言因为可以运行时改变自身的结构甚至是函数(方法)的定义,我们认为这个语言具有更强的动态特性。)――注:这段应该是抄自《程序员》,删了就不通了,留在这里

早期的程序设计语言(这里主要指高级语言)偏向于极端比如Fortran极端静态,相对的Lisp极端动态。然而下面我们会论述随着程序设计语言的发展,纯粹的静态语言和纯粹的动态语言间有一种相互吸收彼此特性的趋势。特别是随着Java之类的同时包含大量动态特性和静态特性的程序设计语言的出现,使动态语言和静态语言的界限愈发模糊。

(从Fortran -> C/C++ -> Java/C# -> Smalltalk -> Python/Ruby -> Lisp,动态特性从左到右不断加强。比如最原始的Fortran语言中没有堆栈,因此无法在运行时动态分配内存,甚至都无法进行函数递归调用;C/C++进一步,拥有堆栈,指针,能够灵活的在运行时动态生成对象(new语义)。Java和C#语言因为拥有很强的RTTI 功能,使得运行时动态识别、加载和管理类的能力大大提升。使得他们动态特性又前进了一大步。而Python和Ruby干脆可以在运行时动态改变类或是实例的结构或是定义。)――注:这段同上面注

这里我们依照习惯将Java、C#划分为静态语言,而别它们更动态的语言划分为动态语言。由此给出动态语言定义:可以在运行时刻改变变量类型和修改程序结构的程序设计语言,这里运行时刻改变变量类型主要指动态类型特性,而运行时刻修改程序结构主要指可以动态创建、删除类或函数并且可以在类中添加、删除方法或属性以及修改方法的实现;不满足这个的既是静态语言。以下我们首先讨论对这个定义中明显区分静态、动态语言的特性:静态类型和动态类型,并且简述一下静态语言和动态语言的特点;然后论述程序设计语言发展中的动静融合趋势。

静态语言

静态类型简述(删)

静态语言的特点(删)

动态语言

动态类型简述(删)

动态语言的特点

语言动态特性可以为程序提供很多好处,比如:健壮性、可移植性等等,但随着Java吸收了这些特性后,这些好处也不再是动态语言所特有的。在下一节我们会逐一讨论Java所吸收的动态特性和它们所带来的好处。而这里我们主要考虑我们定义的动态语言的特点:动态类型和运行时刻修改程序结构,给程序设计和编写所带来的好处

动态类型最基本设计哲学在于赋予程序设计最大灵活性,不在编译期给程序添加不必要限制,并认为这样可以最大程度的提高开发效率。为了说明这点,我们可以参考一下MFC的实现。MFC(出于效率考虑,但不一定必要)没有使用在现代图形界面中经常使用的多态技术――多态显然是语言动态特性,而是采用一组宏来构造消息链和消息映射等等机制。不可否认MFC从实现来看还比较优雅,但大量的宏使用使得不通过wizard来手工构造一个MFC应用几乎不可能,而且不经过深入研究很难理解MFC的工作方式。对比之下,类似wxWindows之类的图形界面框架使用多态来完成消息映射,其开发和理解难度对比MFC都很低。虽然MFC使用宏来实现主要是出于效率考虑的结果,但这恰好反映出动态语言和静态语言使用是在开发效率(程序设计的灵活性、简单性)和运行效率权衡的结果。

Java等语言吸收了大量动态特性并且被广泛使用后大大提高了人们的开发效率,但由于没有我们定义的动态语言所具备的两个主要特性:动态类型和运行时刻修改程序结构,还是给人们的开发工作带来一定的限制。作为例子我们可以参考Hibernate和Ruby on Rails中的O/R Mapping模块。如今主流的O/R Mapping框架因为需要实现对领域模型进行透明的持久化,所以需要在运行时刻对领域模型进行监视,当其数据发生变化时表示“脏数据”。然而为了不在ORM框架和领域模型之间造成不必要的耦合,也就是希望领域模型可以以POJO来实现,这就需要在运行时刻修改领域模型的结构,在其中添加必要的监视“脏数据”的方法。这里Hibernate使用CGLIB+反射机制来实现这种修改,不论从实现还是理解的难度都比Ruby那种从语言层面直接支持的方式差了许多。而实际上Ruby on Rails正是因为其大量动态特性――主要就是动态类型和运行时刻对程序结构的修改――的运用大幅度提升了开发效率才造成了对J2EE社区的极大地震动。

Java――成功的动静融合

从程序设计语言出现开始,静态语言一直是工业界的主流(Fortran、C、C++)――相对来说动态语言则是学界和Hacker的最爱(Lisp、Perl、Smalltalk)――这主要是出于效率考虑的原因,动态语言大量的运行时刻特性造成其效率不彰,在硬件比较慢的时代这是必然的结果。然而随着硬件在摩尔定律的推动下飞速前进,加之软件复杂性越来越高,那种注重运行效率而忽略开发效率的程序设计语言既失去了依存的环境也不能满足人们的需要。长期以来静态语言一直在逐渐吸收动态语言的特性:递归的引入;动态分配内存;多态等等,但这种步伐一直比较缓慢。(其中兼容性也起了一些负面的影响,就因为在对C的兼容性和效率方面投入了极大的关注,一堆天才们也只能设计出C++这种庞杂的语言,而后来的经验表明与其关注语义方面的兼容性倒不如通过对遗产系统的桥接来得直接,也更能卸掉包袱。)

对比后来的语言我们就会发现最后一个广泛流行的比较纯粹的静态语言C++太复杂了,以至于很少人可以正确使用它。即使只是以一定的运行效率的牺牲就来换取不用专家就可以实现绝对不会内存泄露的程序,我想在95年那个时候也会有很多人来做这个交易,何况动态特性还可以提供很多其它有助于开发效率的特性。所以Java的出现具有一定的必然性。

如果说语法是语言的皮,那么拔掉这层皮之后,实现看不出Java和C++有哪一点相似――Java和Smalltalk倒是更像一些――但Java在推出的时候仍然说自己是C++的更新换代,可以说Sun在这一点上做的很好,有一种假的兼容性吸引了广大C++程序员的目光。

根据我们前面的定义Java仍然是一种静态语言,但实际上Java(包括后来微软的Java实现C#、VB.NET)更像是一种动静混合的语言。它对语言动态特性的吸收可能比历史上所有静态语言吸收的综合还要多,下面我们来逐一阅览当时Java所标榜的特性,考察它们是动态或静态特性,并讨论对Java流行的影响。

我们将根据著名的”Core Java 2(7th) “中The Java “White Paper” Buzzwords部份来论述Java的特性:
简单:在做语言繁简的对比时,Java语言选取的对比标准一般是C++,对比后我们会发现我们不再有指针、头文件、结构、联合体、运算符重载(虽然必要)、虚基类、多重继承等等繁杂的概念了,Java真的很简单。遗憾的是同时我们也会发现几乎所有语言都比C++简单。另外虽然简单性不是从动态、静态角度上的特性,但简单而具有强大的表现力长久以来就是动态语言所追求的(相比动态语言Java那种每次从容器中取数据都要经过向下类型转化也就显得不那么简单了)――动态语言的始祖Lisp只用7个操作符就描述了自身。
纯粹的面向对象:Java的流行原因之一,这点的确和动静特性没关系……
分布式:Sun力推的特性,但事实证明同构平台下的分布式操作在绝大多数情况下并不需要,EJB的失败见证了这一点,而人们记住的就是Martin Fowler分布对象设计第一定律:“不要分布你的对象”。这点不是动态、静态角度上的特性,但也没给Java语言的流行带来帮助――如果不是起了反面作用。
健壮性:Java程序比C++程序更健壮,其中动态类型检查和虚拟机的内存管理量的特性功不可没――不会出现C++中的因为向下强制类型转化引发的奇怪错误,更是在理论上彻底消除了内存泄露(前提是虚拟机实现正确)。这是促使Java流行最重要的特性之一――使开发人员更关注于业务逻辑而不是时时刻刻想着堆栈――但其实动态语言从一开始就拥有这两个特性,在Lisp、Perl等等动态语言中从没见过谁关心过内存。(Lisp根本就不关心谁是冯•诺依曼)
安全:部分程度是上一点的附加特性,类似“栈溢出”等等的攻击手段被彻底杜绝了。
体系结构中立:与C++不同,Java代码被编译成byte-code,运行在虚拟机中。虚拟机有各种体系结构下的实现。但是这种体系结构中立对Java的流行有多大帮助很难说。如果说在Java刚出现C/S架构还在当道,那么Client的“一次编写,到处运行”很重要,但等到Java真正被广泛接受的98、99年,第二次浪潮已经来到B/S成为主流。所以很难说这种体系结构中立对于如今主流的Java应用还有什么帮助,可能的也就是嵌入式开发了。当然不论如何,动态语言一直是体系结构中立的,因为整个Java虚拟机的想法就是从动态语言这里发展来的,虚拟机本身就可以算是语言的动态特性。
可移植性:同上,只不过体系结构中立的同时还是OS中立(值得注意的是现在的J2EE应用已经被绑定在应用服务器中了)同样这种可移植性也是一种依赖虚拟机的动态特性。
解释型:毫无疑问,动态特性。不过对Java流行没有帮助。
高性能:(我没有考证这是从第几版开始被写入Java “White Paper”的,如果是一开始就被写入的,那么这就是个彻头彻尾的谎言。)原文的意思是说可以在运行时时刻根据程序运行的硬件环境对程序进行优化。首先可以肯定的是这也是个依赖虚拟机的动态特性;其次如果我们可以在每次部署的时候根据部署平台重新编译系统,那么可以肯定Java的byte-code肯定是要比经过编译优化的二进制代码慢的。可能有人会觉得做不到部署时重新编译,但要注意Java目前的主流应用是B/S架构的企业级应用,所以部署时重新编译是可能的;第三是这里Java有一个很大的贡献,Java的流行使虚拟机的效率在短期内大幅度提升(借助JIT等技术),并向人们证明了解释型语言的运行效率并不是想象的那么可怕。
多线程:提供并发的关键字,由虚拟机支持。较新的动态语言(Python等)都具有。
动态:主要包括动态类装载、反射,比如Java一个类的结构是由解释器在类动态装入时决定的,而在C++这样的静态语言中类在内存中的结构是编译时刻确定的,所以在类中增加一个实例变量或一种成员函数后,引用该类的所有子类都必须重新编译,否则将导致程序崩溃。这里Sun本身也承认Java是一种比C/C++动态得多的语言。原文如下”In a number of ways, Java is a more dynamic language than C or C++. It was designed to adapt to an evolving environment. Libraries can freely add new methods and instance variables without any effect on their clients. In Java, finding out run time type information is straightforward. “

总结一下我们会发现真正对Java流行起作用的语言特性(排除了分布式),除了纯粹面向对象特性(实际上打了折扣,模块、类本身和函数都不是对象,不能以一致的方式来处理,比Smalltalk、Python弱了一筹)之外,Java标榜的所有特性都可以被归为动态特性,而这些特性大部分依赖虚拟机。

如果我们对比一下主流的动态语言Perl、Python和Ruby就会发现Java除了具有静态类型特性和不能在运行时刻修改程序结构之外――后者主要指不能动态改变类、方法的声明等等,这其实是静态类型的一个副作用,比如静态类型提供编译时刻检查使程序不能调用类中还不存在的方法(实际上通过反射和CGLIB扩展字节码可以实现运行时刻一定程度修改程序结构但这种模拟方式很迂回,也不够灵活)――从哪方面看都很像一个动态语言,但也就是静态类型这一点使Java仍然是一个极为动态的静态语言。

Python、C#――进一步的动静融合

从前面所述我们可以看到,Java以静态语言为依托同时大量吸取了动态语言的优势――加之成功的运作――使其在数年间迅速发展为最为流行的程序设计语言之一。

然而自从Java诞生以来――也许是受了“Java是一种简单的语言”这句话的桎梏――从1.1到1.4 Sun除了对Java语言中的瑕疵修修补补(优化虚拟机、修改类库中一部分不好的实现等等)以外,在语言核心层面一直缺乏大的动作。只是到了C#“兵临城下”之际才在Java 5.0(这里Sun的心虚一如这个版本号)加入了泛型、自动拆装箱、元数据等特性,而这些特性也都是已经在其他语言中广泛使用的了。

Sun公司在Java发展历程中的表现告诉我们,这家公司在企图有所创新时几乎总会失败(早期Java类库的实现,Entity Bean等等),而它在软件商业领域的表现更是让我们质疑它的能力(应用服务器、集成开发环境方面的表现,我们有理由认为作为Java的发明者Sun实际可能上并没有从Java的流行中获得了太大的利益),加之JCP这个看似民主的过程存在着其他民主过程的通病――各个大利益集团相互掣肘导致的缓慢,这些因素本来完全有可能让Java这颗新星迅速陨落。但幸运的是Java发展的早期那种对微软的抵抗态度,或者说它所标榜“自由”的“宗教信仰”拯救了它自己。开源社区蓬勃发展,以及其对Java语言的大力支持,使Java仍然是今天最值得使用语言――试想如果失去众多的优秀开源产品(Eclipse、Hibernate, etc),而这些产品支持的是另一阵营(PHP、Python甚至是.NET),那将是怎样一种局面(虽然我不否认偶然中的必然性)。但需要明了的是Java在语言层面的革新动作是始终微缓,而且不值得人们报以期望。而通过下文我们会发现仅仅通过不断扩展的类库是不足以(至少是不能直观的)适应语言发展变化。

这里我们首先指出我们认为语言的发展趋势会是进一步动静融合,而从前面对Java的分析可以看到Java和主流动态语言最大的不同就是静态类型和动态类型,所以进一步动静融合的重点就在于兼取静态类型和动态类型的优势。下文将通过对Python和C#语言目前演变趋势的描述来说明这种趋势。

Python,静态类型的引入

05年年初Python的作者Guido在其blog上发表了数篇文章(Adding Optional Static Typing to Python, etc)论述了在Python中引入可选静态类型的可能性,而后在Python3.0 Plans的文档中Core language部分出现“Add optional declarations for static typing”的目标。下面我们首先叙述一下这种特性,然后讨论其引入带来的变化和好处。

Guido在其blog的文章Optional Static Typing — Stop the Flames中说明Python可能添加4种语言特性来支持可选静态类型,依次是:
参数、返回值类型定义,Argument and return type declarations
属性类型定义,Attribute declarations (maybe)
接口定义,Interface declarations
基于契约设计,Design by contract (maybe)

实际上我们注意到在目前的版本中Python类型判断运用的实际上是一种被戏称为Duck Typing的方法――Duck Typing的名字来自这句话“If it walks like a duck and talks like a duck, it must be a duck”。例如在Python中我们定义一个函数f
def f(i):
    print i.value
这样当我们调用f时传入的参数可以是任意类型,但如果运行时刻发现i不包含value的属性(it is not a duck),解释器就会抛出一个异常。这种动态类型为Python语言提供了极大的灵活性。

但是这种灵活性不是没有代价的,强大的动态类型也使Python丢失了大部分静态类型语言所拥有的便利,这包括:
文档生成,类型可以帮助我们更确切的描述参数和返回值,而动态类型导致需要大量文字来说明
IDE的帮助,现代IDE提供强大的智能完成和代码生成功能,这经常需要变量有确定的类型
优化,编译器可以利用类型信息来进行优化
反射类型信息,通过反射可以在运行时可得到函数参数和返回值的类型,利于外部库进行函数调用(特别在外部库是静态类型时,比如数据库桥,这尤为重要),尽管动态语言的反射能力一般都非常强大,但如果其本身的语义不支持函数参数返回值类型,那么也是无能为力
静态类型检查,通过早期检查提高程序的健壮性,而如今设计模式的发展已经可以很大程度上弥补静态类型所导致的紧密耦合出现。而对于大型项目,特别是多个模块同时开发的项目,静态类型接口可以作为一种有效的契约来约束各个模块的行为,而静态类型检查有效地保证了这种约束

事实上可以认为前三点只能说是引入类型带来的额外好处,而真正重要的是则是后两点。从前面论述可以看出对于大型项目失去静态类型是一件非常不利的事情,这完全可以抵消使用高灵活性动态语言所带来的生产率的优势。在此我们深化本节开始的说明:作为一门更进一步的动静融合程序设计语言最重要的特性就是兼具动态类型的灵活性和静态类型的可靠性。

这两点看似矛盾,实际上如果我们将这两点放到不同的粒度上去考虑,在一个粗粒度的级别上用静态类型描述接口,而在内部是使用动态类型编写程序,可能在将来的Python3.0中我们可以这样来编写程序:
interface IBussinessLogicFacade:
    def insertOrder(order: Order, date: Date) -> boolean: #静态类型的接口
        “insert a Order return true if succeed”

class BussinessLogic(IBussinessLogicFacade)
def insertOrder(order, date): #动态类型的实现
    …
这样我们就既能有效的利用动态语言来提高生产率又能利用静态类型来巩固程序。

但是如果我们详细阅读Guido年初的文章,我们会发现Guido最后的定稿中的可选静态类型的语言特性只是他开始提出的全部想法中很小的一个子集,大量有趣的特性没有出现在Python3.0 Plans中,这包括泛型、重载等等,而且Guido还提到Python可能不会在language core级别添加静态类型检查等等功能――静态类型可能更多的是为外围的库(比如Pychecker,一个Python程序的检查工具)提供支持,这里的静态类型可能更多地沦为一种元数据的描述手段。这里我们可以体会到Guido的小心翼翼,毕竟对于动态类型为核心的语言在其上包装一层静态类型的壳,如果一不小心就会丢失掉动态类型的好处而还要承担大量反射带来的性能损失。而且一个兼具动静融合的语言可能同时需要强大的编译器和解释器,Python社区作为一个缺少大厂商支持的社区,如果语言设计过于复杂就可能超出其能力实现的范围就可能沦为下一个Perl 6。

C#,超级编译器

微软之于JCP,与其说是专政之于民主,倒不如说是私企之于国企更为恰当。对比微软来说,JCP做对一件事几乎和做错一件事一样难,当然大部分时间他什么也不做。反之微软开发技术每次的更迭所带来的变化总是令人乍舌(Dos到Win32,Windows DNA到.NET),而这也是微软最遭开发人员诟病的地方之一。

类似的,对比属于JCP的Java和属于MS的C#(实际上也包括VB.net,简洁起见以下略去),我们同样发现C#在语言核心变更上的激进程度令人惊讶。实际上如果我们注意Java以及更早的C++就会发现这些语言都是在努力保持着语言核心的稳定和类库的激进。但是不应忘记的是与它们不同C#事实上的一种厂商专有的语言(虽然被标准化),所以从微软的角度来说变更语言核心和变更类库是可以完全从技术上考虑,这使得C#较之商业语言更像一种实验室语言――并不排除这是MS打击Java的一种战略。唯一令人担心的是语言核心如此剧烈的变更会打击开源社区的积极性(比如Mono)。

回到正题,我认为微软很久之前就注意到了动态语言的重要性。实际上远在Win32的时代,VC+VB方案流行的时候,VB就可以称为一种基于对象的动态脚本语言。而微软从COM开始就致力于不同程序设计语言间的无缝集成,到了.NET的时代从设计之初不同语言的集成就是其重要的目标,所以我们也就看到了大量的将其他程序设计语言向.NET平台迁移的项目(Perl.net, IronPython, etc)。但也许现在MS已不再热衷于动态语言与静态语言在虚拟机一级的集成了,因为从不久前微软发布了一个C#3.0的预览版本来看(实际上从C#2.0就已经开始)MS似乎想在语言层面让C#尽可能地吸收动态特性,塑造出一种可能是兼备动态类型的灵活和静态类型的可靠性的语言,而这正是我们认为的未来语言的趋势。以下简单浏览一下C#3.0的特性,并讨论一下C#和Python在动静融合方面思维方式的不同。

C#3.0最大的一个特点就是赋予了编译器强大的类型推导能力,C#3.0的大部分新特性都需要类型推导能力。比如隐式类型局部变量(implicitly typed local variable)允许我们编写这样的代码:
var i = 5;
var s = “Hello”;
var d = 1.0;
var numbers = new int[] {1, 2, 3};
var orders = new Dictionary();
这里编译器会帮助我们根据初始化语句推导出变量合适的类型,而匿名类型特性以隐式类型局部变量为基础可以产生更惊人的效果:
var p1 = new { Name = “Lawnmower”, Price = 495.00 };
var p2 = new { Name = “Shovel”, Price = 26.95 };
p2.Price = p1.Price
p1 = p2;
注意p1和p2是可以相互赋值的。可以看到这段代码很像动态语言的代码。另外C#2.0引入匿名方法,C#3.0更是引入lambda表达式(其中隐性局部变量仍然起了重要的作用)这种函数式编程的特性。这些都反映出C#在吸收动态特性方面的努力。

另外值得我们注意的是C#进行动静融合时的思维方式。为了对比我们首先看Python。实际上一般来讲我们认为静态方面的语言特性由编译器来完成,反之动态方面的语言特性由解释器(虚拟机)来完成。Python本身作为一种动态语言,它在试图吸收静态特性时首先想加强的是它的编译器。直观地想,我们会认为C#既然拥有CLR这样强大的解释器(已经在其上实现了几个动态语言,证明了其能力)那么当它吸收动态特性时理应应用这一点――如果这样做C#3.0和Python3.0可能就没什么不同了。

但事实不是这样,这里不得不承认C#3.0在这方面是另辟蹊径,C#把这些动态特性大部分推给编译器――类比C++的静态多态(泛型),利用编译器的推理能力,使程序开始运行时仍然像个静态类型语言,但在编写时可以忽略大量类型的桎梏而很像动态语言。这里最大的得利就是效率――Python、Ruby总是被人们批评为“世界上最慢的语言”,因为今天硬件的表现还不足以让我们忽略反射的损失(虽然也许10年之后谈反射的性能损失就像现在谈论虚拟机的性能损失一样)。

当然这样的实际上是“伪动态类型”的程序设计语言的灵活性到底如何还有待大范围应用后考验,但微软在这里已经走出了第一步,而C#也符合了我们开始说的实验性语言的地位。

2005-12-8

 

江织田

江织田,日料自助。98块钱一位(贵……)。刺身,章鱼我喜欢,北极贝也不错,三文鱼的口感和平时的不太一样?赠送海胆,第一次吃这个,感觉粘粘的……烤鳗鱼一般稍微有一点点腥味,酱烧大虾没网上说得好,汁烧鱿鱼口感味道都很赞。几种手卷都不错,普通寿司也就是寿司吧,其中鲈鱼寿司让我想起GTO里的画面。送两瓶清酒,一如既往那么淡,不过配鱼生很合适。土瓶蒸,原来不知道这个比较土,怀疑就是日式快餐咖喱饭、拉面之类的套餐里那个汤的来源,因为味道都是和方便面汤是一样的……另外“应部分客人的要求”菜单也可以卖,500块一份,不知道谁买。

06,新年新气象

第一天就没睡觉,去避风塘通宵打牌――“跑得快”留一张一毛钱,输的钱全部捐入fb基金――4个人一晚上攒了185块……真是凑钱fb的好办法

IBM研究院的实习

笔试,全是选择。5个数据结构,20多个Java相关其中4-5个是关于J2ee的,其他都是语法糖。主要在4个方面,容器、内隐类、异常、多线程,还好昨天补了一下Java语法,内隐类和异常的东西都还清楚,容器跟着平时的感觉。至于多线程,一向是我的畏惧,有时间应该看一下Lea的经典

面试,考官2男2女,没什么特殊的。因为没人通知我应该带简历,所以就是随便扯了扯。

ps:其实去的路上我是决定不打算去这个实习的,我现在的计划里学习给eclipse写插件的优先级是很低的。而且难得下学期真正清闲,还是希望能按着自己的步伐走,现在的我离我想要的那种完美的绝对强势还差很远。所以面试的时候还是有点保留,有意无意的吧――也可能是因为面试技巧的不够――反正是给他们的感觉估计也就是较好的本科水平,肯定是比我现在的实力要弱很多的。应该是肯定不会招我的。不过回来的路上又有点后悔,毕竟要是能去IBM实习一下履历上会很好看的。哎,人还真是矛盾呢。

读书进度+规划II

without EJB 第7章到最后 394页
RUP导论 170页
计算机网络 第6章到第8页 302页
POEAA 357页
Concepts of Programming Languages (5th Edition) 660页

UP 330页
数据库系统概念 第6-18,21,22,24-27章 480页
软件工程:实践者的研究方法 第三部分第10-19章 206页
—————————-
可计算性与计算复杂性导引 210页(下学期必须要重新听一下那门课)
SICP 431页
—————————-
AOSD 395页(视情况定,看放假能不能先看一点)
Introduction to Algorithms 1100页(这本下学期每天看一点,循序渐进)
编写有效用例 280页
uml和模式应用 第6章到最后 421页
重构 413页
深入Java虚拟机 355页
effective enterprise java 307页
Bitter EJB 255页