apple说:
| 哦,原来你也是用windows的,那你学的那些语言都用在什么地方?我总觉得学一个东西总要是用出来的吧,如:某个程序、某个网站、某个系统?不可能总停留在某一个函数和算法的研究上啊?
| 而要发布或部署一个系统,又要用到windows平台,那你写代码总要ide帮助才行啊,如果用记事本写程序的话,完成一个系统那得花多长时间啊?所以好的ide帮助你处理了那些和部署相关的啰嗦的东西,然后你才能安心的处理程序逻辑~
| 而且你的动态语言,我真的不理解,现在流行的python,及perl,这些语言自身是不可存在的吧,他们需要借助某种环境,如必须放在网页中,perl 好像还需在*nix下吧。so,我在windows下就很迷惑,我想写段python或perl代码,却找不到该在哪写?然后就算写好了,确不知道该如何运行~
| 而在大学时也曾想转到nix下,装了freebsd,然后却发现用的很不适应,它里面的编写程序的环境也不是很友好,对着黑黑的窗口和界面普通的kde,感觉无所适从,觉得他不像传说中的那样充满吸引力~
| 于是,在周围同学的CS枪声中我又装回了windows。
| 现在,偶然,碰到你,我又对nix找回写兴趣,我觉得我骨子里还是希望能对nix有比较深入的了解的~
我其实不算是用win的,因为很早开始我就在用*nix的方式工作。这个星期装上了freebsd,甚爽,发现以前学的知识都有了充分的发挥,bash/term好用的不行,再也不用忍受连行编辑都不支持的cmd.exe了。
所谓“学东西拿出来用”,我是这样理解的:写程序,做网站,核心的部分、难的部分不超过20%(除非你写的就是算法库);但这部分却要花去你 80%的时间。剩下来那80%的代码呢?普通的逻辑和简单的调用而已。就知识而言,前者是活的,后者是死的。所以我懒得去搞应用,因为我知道,凭我的能力,到时候对照着文档写都来得及。平时重在练“内功”,以期用兵一时啊。
关于ide,这样跟你说吧。我肯定不会去用ide,但也不可能去用notepad。我们prefer高级编辑器。只要你不用java、c+ +、.net这些特别费话的语言,没怎么配置过的vim,emacs这些东西绝对比ide高效(当然,也可以把emacs弄得比eclipse还拉风,但我不用,就没兴趣了)。它们的指导思想是:让你在写程序的时候用100%的精力思考程序逻辑,用0%的时间输入代码。所以,1. 不帮助你思考。需要有程序帮你思考的语言就不是好语言;2. 不阻碍你思考。敢和人类作对的程序应该去死;3. 使你更快地输入代码。这是高级编辑器提供效率的关键,也是不阻碍你思考的一部分。你觉得ide的代码完成高效吗?vim也有,但不会没事干地帮你匹配文件里没有的单词。而其它的地方ide就没什么戏了。如果你要修改前面第4个单词,你刚把手从键盘上撤下来还没放到鼠标上,vim的用户按3个键esc,3, b就定位到了。举个对你应该特别熟悉的例子:你可能经常需要把程序中的两行并成一行,你常常把光标移过去,然后删除所有自动缩进;vim用户用数字建、k 定位到行,按下shift+j就搞定了。速度,永远不是从帮你输入废话上得来的。
编译、发布、部署、打包程序,这种事情你可能经常让ide代劳。不过你也可能从未想过ide怎么会这么清楚的。它们的能力来源很简单,就是跟*nix学的。make程序,提供了组织程序的一条龙服务的终极武器,每个ide的必备抄袭作品。vs再怎么发展,也不会少了它的nmake.exe,否则它就成了史上最大记事本了。但李鬼终究还是敌不过李逵,nmake这样的东西怎么能敌得过新时代的gnu-make?别说是m$麾下的东西了,就是 ant在它面前也得退避三舍啊,复杂的xml怎么能比一个领域特定编程语言强大?连写makefile都嫌烦,没事还有automake、patch,好了只要把目录组织一下就行了,而且连打补丁都不用你操心了。
这些事关ide的存在价值的东西都在*nix小工具面前黯然失色,其它的东西就更没得比了:gnu下有最强大的编译器、汇编器、调试器,各种dsl程序遍地爬,grep不行上awk,再不行上perl,连接它们的管道四通八达,你可以随心所欲地在编辑器里查看从最底层的gcc那儿传上来的经过数层处理后的信息。
不过懒得出奇的*nixr也有嫌这个也烦的时候,如果有什么语言不用编译不要调试不用部署就更好了。动态语言就是这样的东西。在任意一个平台下装上解释器,一条命令就能执行;高阶函数的出错信息可以跟踪出调用轨迹,不需要调试器;文件间互相说声引用谁就行了,不用部署。写好了代码不知道怎么运行?把相应解释器装上运行一句 <语言名> <文件名> 就行啦!
黑黑的窗口,闪动的光标下是行编辑库,让你在输入命令时获得相当于使用emacs的编辑效率;kde当然没什么意思,仿win仿着玩儿的大玩具一个;试试看怎么把wmaker调成Mac第二,把fvwm做成外星OS,我觉得这个比较有意思。我现在的freebsd就是用的wmaker窗口管理器,装上几个顺手的gtk程序,剩下来的让vte终端全包。性能好到不行,启动图形界面4秒钟。Unix的重点不在于刚装好时的配置如何,而在于极限的能力是否能满足你的意图。就拿winer们常指责*nix的驱动程序一项来说,其实os里这些驱动都有了,你所要做的只不过是修改某个配置文件中的一两行。这帮winer自己数典忘祖,忘了win装完后必须下载驱动才有全屏显示和声卡支持,而且如果你没有网卡驱动就只能哭去了!
再如装软件。win装软件要搜索多长时间才能下到,还得提防有没有恶意软件,点多少个next才能装完,装完想删掉还卸不干净,装着装着注册表就破50M了。pkg、yum、apt这些东西多方便,你只要知道软件名,输一行命令就能全搞定。有些不明事理的人还指责*nix软件怎么会对其它软件包有依赖。其实这才是*nix的魅力所在:开发出来的东西大家用,做的好的就是库。事实上,只有本地安装命令才会指出依赖性问题,使用自动安装连这些被依赖的软件也一并装了,反正想删就删,*nix分区只要有5%的空间就能保证没有磁盘碎片,多装没坏处。
最后想说的是玩游戏。我用win的时候打了一年魔兽,现在在班上几乎无敌;但又能怎么样呢?我下围棋估计能全灭学校的人,然而没什么人知道。由此我意识到,游戏终究是一种逃避,想把在其它地方失去的虚荣心找回来。领悟了这一点,我也就不再玩游戏了;有时间就下围棋,没时间下就国际象棋, *nix下的gnugo和gnuchess都是普通棋类程序中的强者(不过围棋程序现在的算法还做不了太强,前者还不是我的对手),杀败了它们还可以上 igs和ics,生活很幸福~`
Showing posts with label 推荐. Show all posts
Showing posts with label 推荐. Show all posts
September 6, 2007
我看 D 语言
初,语言只能用有限的特性发挥有限的力量,那时有个语言自命简单(Basic),其实是弱;真正强大的语言,能用有限的特性发挥出无限的力量,但它们的老大说话总是听不清(Lisp),所以总是有人想取代它的地位;当然了,要使用无限的特性才能发挥出无限的力量的语言也是有的,只是太重了,比珍珠岩(Perlite)还重。然而还有这样一种语言,它们被设计拥有无限的特性,却只能发挥出十分有限的力量,这样的语言在被每个时代抛弃之后仍然不思悔改,现在它们那个以罩杯号码(D)命名的新任老大就是一个典型的例子。
May 18, 2007
推荐一本是人都知道的书
这本书就是:The C programming language
首先纠正一个误区——它决不是什么“入门书”,用它确实能入门,但更重要的是掌握其中每一句话、每一段程序的思想。CPL之于C,就好比SICP(计算机程序的构造和解释)之于Scheme,每一行都是很多计算机科学家思想、经验的结晶。
CPL的语言就是C的规范性文档,CPL的程序就是C库和UNIX系统的标准程序,你通过学习可以了解C的惯例、算法、数据结构、系统编程、内存分配、编译原理、模式识别等各项计算机科学的基础知识,引领真正的学习者选择前往计算机殿堂的路。
我希望每个学习计算机编程的人都去阅读SICP,每个学习C语言的人再去学习The C programming language。
首先纠正一个误区——它决不是什么“入门书”,用它确实能入门,但更重要的是掌握其中每一句话、每一段程序的思想。CPL之于C,就好比SICP(计算机程序的构造和解释)之于Scheme,每一行都是很多计算机科学家思想、经验的结晶。
CPL的语言就是C的规范性文档,CPL的程序就是C库和UNIX系统的标准程序,你通过学习可以了解C的惯例、算法、数据结构、系统编程、内存分配、编译原理、模式识别等各项计算机科学的基础知识,引领真正的学习者选择前往计算机殿堂的路。
我希望每个学习计算机编程的人都去阅读SICP,每个学习C语言的人再去学习The C programming language。
October 21, 2006
献给新访客的一则笑话——古老,但很神奇
- 诶,我的Blog已经很久没更新了——得菌痢住院5天啦,今天终于出来啦!
- Lava-Lava平台上“科技自主创新网”部落的同仁们可能已经看到了我的Blog荣幸进入你们的“酋长推荐”标签页,但似乎没有人给我的文章留下评论。我估计这是大家都没有接触过Scheme语言的缘故。所以我决定写一篇这样的文章,让新来的访客们看一看Scheme时间的精彩——当然,我没有要贬低其它语言(除了Java)的意思,事实上我最喜欢的语言之一就是C。好了,不罗嗦了,让我们一起来推开Scheme那道门吧。
人物:XX大学计算机系的社友Go4——8呆,F1,老农和小四。
时间:“晚汇报”时间…
(老农在计算机系混的时间不短了,可惜技术一直没长进——连打电脑游戏都“不上档次”(小四语)。这不,昨天打CS又被F1欺负了,现在正郁闷着呢。)
老农(上网无聊中):这年头,电脑好的人就是吃香啊~~(旁白)俺编程也差,游戏也差,废啦~~有了,上CSDN.net,找点文章进修一下。
F1:老农,怎么样,CS技术不行啊!好好练啊!
小四(推推眼镜):老农伯伯!算了吧,我看你还是把编程学学好吧,哈哈,你那本《数据结构》好像还是新的吧?
(老农翻着最新的Blog文章,忽然眼睛一亮。)
小四:嘿,发现什么了?
老农(连忙把Firefox最小化):没什么,又不是黄网激动什么?!
老农(旁白):不错,就用这篇文章K.O.他们。
老农(满脸堆笑):嘿,你们仨过来,我在网上发现一道数据结构方面的面试题目,想不想试试?
(正在上铺捧着SICP发呆的8呆忽然从发呆状态切换到亢奋状态,人啊~~)
8呆:废话,快说!
老农(奸笑中):设计一个函数visit_tail,要求通过一次遍历找到链表中倒数第n个节点,然后从它开始用函数func例遍后面的所有链表元素,链表可能相当大,可使用辅助空间,但是辅助空间的数目必须固定,不能和n有关。还有,不需要给出链表的其它操作函数。
8呆(再次切换回发呆状态):无聊…这也能叫题目…
老农(怒):那你做啊!
(8呆在他的SICP上写了点什么,然后很潇洒地离开了寝室)
老农(专向另两个人):既然他不参加,那我们三个比吧。
小四、F1(信心实足):那现在开始计时吧。
……
(老农把刚才背下来的代码改了改,花了3分钟抄在终端里)
老农(觉得时机移到):我好了,你们呢?
小四(大喊):解决解决!
F1:恩,我也好了,只是还没做单元测试。
(老农、小四:寒~~)
(3个人凑在老农的电脑上开始比拼)
老农:你们看,我是用C写的,已经测试过的,思想是,用两根指针,第一根先出发,相距n步后第二根出发。然后同时步进,直到第一根指针达到末尾,然后用func()函数对第二个指针开始的子链表进行例遍。
(小四和F1仔细一看,大笑不止。老农的代码如下(注释是笔者所加,其实是F1和小四看到各句时的反应):)
typedef struct{ //哟,终于不用struct Node了,
int data;
Node * next;
} Node;
Node * visit_tail(iNode * head,int n,void (* func)(int cur)){ //K&R时代的函数指针,见到老佛爷啦!!
Node *pfirst; //吓,终于用到匈牙利命名法了(老农:寒~)
Node *psecond;
pfirst=head;
}
psecond=head;
while(pfirst!=NULL) {
pfirst=pfirst->next;
psecond=psecond->next;
} //什么破编程风格,真实版初学者啊
for(int i=0;i
psecond=psecond->next;
}
} //靠,一个函数解决所有问题,高耦合啊!
老农(再怒):小四少罗嗦!你的呢!
小四:在这儿,好好学学吧!
(大家一看,小四也用了C,但…好漂亮啊。代码如下(注释是小四的解释):)
typedef int int
//没有C++一样“泛型”!
typedef struct {
T data;
Node * next;
} Node;
typedef struct {
Node * pre;
Node * curr; //当前结点与List绑定,不但可以分步例遍,还能保证正确初始化
} List;
void init_curr (List * l) {
l->curr = l->pre; //什么叫“编程风格”,知道不?!
}
void visit (List *l, void (* func)(T data)) {
while (l-curr) { //少用!=NULL
(* func)(l-curr->data);
l-curr = l->curr->next;
}
} //使用内联结点的公用访问函数,降低耦合
void index (List * l, int n) {
if (n) return NULL; //结点下标从1开始
init_curr(l);
if (n > 0) {
for (int i = 0; i <>curr = l->curr->next;
} //小四(自我陶醉):漂亮啊
if (n < n =" -n;" tmp =" l-">curr;
for (int i = 0; i < tmp =" tmp-">next;
}
while (tmp) {
l->curr = l->curr->next;
tmp = tmp->next;
}
}
return l->curr; //方便用户,增强鲁棒性能
}
void visit_tail (List * l, int n, void (* func)(T data)) {
index(l, -n);
visit(l, func);
} //多清爽
老农(倒):我的挽回面子计划就这么,完了…
小四(偷笑):你还是面对现实吧…
F1:小四你先别得意,我的你们还没拜读过呢!
(大家跑到F1电脑前一看,先是被长度吓了一跳,然后,无语。)
package datastruct.fifi.com.baidu.hi; //加入我的数据结构Java包
//当然只有包内成员才能创建Node对象
protected class Node {
private Object data; //多态性,让你们的typedef去死吧!
private Node next;
//构造函数
Node (data) {
this.data = data;
}
//获取下一个元素
public Node next () {
return this.next;
}
protected void setNext (o) {
this.next = o;
}
//取数据
public Object getData () {
return this.data;
}
//换数据
public void setData (data) {
this.data = data;
}
//根据Effective Java的最高指导,要重写toString()方法
public String toString () {
return this.data.toString();
}
//自定义异常类,数据结构下标越界
public class IndexOutOfRangeException extend IndexOutOfBoundsException {
public IndexOutOfRangeException (int lower, int upper, int index) {
super("Lower: " + lower +", Upper: " + upper + ", index: " + index);
}
}
//用于被继承的访问类
public class Visitor {
public operation (Object o) { //访问操作
System.out.println(o);
}
public class List {
private Node preFix;
private Node current;
private int size;
List () {
current = preFix = new Node();
size = 0;
}
//自定义异常类,数据结构下标越界
public class IndexOutOfRangeException extend IndexOutOfBoundsException {
public IndexOutOfRangeException (int lower, int upper, int index) {
super("Lower: " + lower +", Upper: " + upper + ", index: " + index);
}
}
//用于被继承的访问类
public class Visitor {
public operation (Object o) { //访问操作
System.out.println(o);
}
}
public class List {
private Node preFix;
private Node current;
private int size;
List () {
current = preFix = new Node();
size = 0;
}
//定位函数
private void index (int i) throws IndexOutOfRangeException {
if (i > size || i < -size-1) { thows new IndexOutOfRangeException(0, size+1, i); } this.init(); if (i >= 0) {
for (int j=0; j < current =" current.next();" i =" -" j="0;" current =" current.next();" current =" current.next();">_< 。。。 F1:we得意。 (3人正在争执着,忽然门“吱”的一声(什么破门)开了,8呆走了进来。) 8呆:吵什么呢,比完了没?我是第一吧? F1、小四、老农:什么啊,你不是自顾自走了啦?! 8呆(诧异):我走之前已经写好啦。 (8呆拿来他的SICP,只见上面写了一行Scheme代码:) (define (list-visit-tail l n func) (for-each (list-tail l n) func)) (编辑公曰:上面这段Scheme代码滴意思斯酱紫滴:先定义一个名为list-visit-tail的过程,然后用内置宏list-tail取list的后n位组成list返回,再用操作for-each进行例遍。) (完) 结语: 这个题目其实对于任何函数式编程语言来说都是一两句话。Scheme、Haskell它们都来自于世界上第二古老的语言Lisp,但它们的思想博大精深——基于lambda演算理论的函数式编程,古老,但很神奇。 参考资料:
- 老农说的“这篇文章”:一次遍历找链表倒数第n个节点
- 8呆的书SICP:Structure and Interpretation of Computer Programs
- 命令式语言的劣势:为何 Java(以及很多其他编程语言)令人不爽
- 函数式语言的优势:为什么函数式编程至关重要?
- Scheme入门推荐书:Teach Yourself Scheme in Fixnum Days
- 如果你还没学过编程的话:How to Design Programs
- 其它有关Scheme的东东详见:我的Scheme学习笔记(1 2 3 4 5)
Subscribe to:
Posts (Atom)