开篇基础

感悟

经常被人问,为什么你不学这个语言?为什么你们要采用这个语言而不用那个语言?哪个语言最好?我应该学哪门语言呢?看看自己这几年编程之路一些心得。

其实26个字母,每一个字母背后至少有一门语言?为什么会这么多种编程语言呢?因为没有一门语言是万能的。编程语言也是不断向前演化的。随着人们对计算机需求的发展而不断向前发展,没有最好,只有更好。 程序语言是最重要的思维工具,它们首先让我们能够明确地传递表达自己的想法,以至于即使是计算机也能理解,如果有人发明一种编程语言即符合他们的思维,又能解决当下的问题。此时,选哪种语言都无关紧要了。

每一门语言都它自己特有的应用环境。但是编程语言也有共性:所有的语言都会由这些基本元素组成:变量,循环,分析,顺序,函数。以及常规数学运算以及逻辑支算。如果说你的需求是这种大众化的。任何一门语言都能满足你。如倮你的需求不是这么的简单是特定领域的。:就找到在这方面应用比较广泛的语言。例如你的应用环境是办公软件(ms的office),学习办公软件支持的脚本语言VBA,以及相关的API.是最好的选择。如果你要文本处理,并且需求简单,常用的shell语言都能实现,复杂的用perl,tcl来处理。对速度有要求用java,C++还处理。如果是做嵌入式那么C语言是更好的选择。同时也要看你的应用环境支持哪些语言。对于是同一系列的语言,后出来的语言会之前的语言要强大一些,并且易用性会好一些。如果没有特殊的需求,只是为了学语言而学,那就学习C/C++或者scheme,python吧,因为这两种语言计算模型是不一样的,学会这种两种计算模型,对于你学习其他语言都会有莫大的帮助。

根据个人编程经验分三个方面的总结希望对大家有帮助:

编程语言的组成,

语言学习发展曲线,分三个阶段吧,

以及自己这几年用过的编程语言一些体会吧。 作为一名经验丰富的程序员,回过头再重新学习上述一门编程语言则是获取新感想的最有效方式:这些语言所涵盖的概念提醒着我们,这都是些我们现在看来理所当然的概念,但是初学者却需要在某个阶段学习它们。当我们这么做的时候,我们与学生以及其他的初学者的沟通合作将会更加有效率,因为我们更容易回想起整个逻辑链条,包括那些我们之前认为理所当然而省略的思维步骤。

变量

从编码的脚度变量本质就是替换,一般变量赋值就是一次替换,指针类型变量的赋 值是二次替换,动态语言经常会用到三次替换。但是大部分情况下,用不到三次以 上替换,这也就是什么一般编程语言对二次以下替换支持很好。三次以上替换需要 靠自己去实现了。(3这个数字是特殊的,俗话事不过三,这个是有原因的,根据 一般人的思维能力的来的,就拿最简单的yes/no的逻辑判断来说,连续三次 ,就是八种情况,但是一般人思维能力同时关注最多九种情况,再多了人的思维就 会混乱容易出错了,这也就是为什么,一般人下栱只看二三步的原因,很公司的编 码规范会要求禁用或者少用三层以上if else/ for嵌套。并且学编程 最头疼的内存管理也是三层管理,这样的例子到处都是不多举了)。

从物理的存储角度看:变量又为简单标量,复杂变量列表,哈希。再复杂一些树, 栈,表等数据结构。一般的编程语言都对简单标量,复杂点的列表,哈希支持的很 好。对于标量来说,常见的应用就是字符串的处理,与数值变量各种数学逻辑运算 的。而对于树,栈,表都复杂的数据结构都自己去实现。并且数据量再大一些数据 结构就需要专门的工具数据库来管理了。

变量的另一个作用,那就是信息的传递,以及的分配与释放。难点是变量的存活时间 。也就有了各种变量作用域。都是为提高内存的复用机制。通过分析app的数据的分布 就可以知道其内存的基本使用情况了。同时引用计数是一种最常用的机制。以及各种 的强引用,软引用,弱引用都是这种出于这种目的。 变量复一次值,就多一次引用计数。 每一个系统中引用计数加减原则也是不一样的。

强引用,就是内存不用,也不回收,直接报错,而软引用就是内存够,就不回收。 经常那些somtimes 的问题都是由于软引用与弱存用引起的。因为他的变量回收时间不定 并且你的测试环境,经常内存是充足的,但是实际环境就未必了。

流控与表达式

程序代码的本质是思维与知识的固化。所以程序的结构是根据人的思维习惯来的。 三种最基本结构:顺序,条件分支,循环。就拿人走路来说吧,人沿着路一直走到 下,这就是顺序结构,走到一个交叉路口,要选择走哪条路,这个选择的过程就是 条件分支。选好了路继续走前走,来到一个大山的脚下,然后顺着盘山公路,一圈 一圈的往上走,这就是循环。每一种编程语言都对三种基本结构最具有很好的支持 。但是每个领域都除了这些基本处理逻辑外,都会自己特殊的处理逻辑。人们对这 些处理逻辑进行抽象建模,然后再根据模型,开发出来的相应的语言。例如per l对文本处理的优化,为了测试集成电路而开发出来tcl语言,针对集成电路中 时序与状态转换处理逻辑,对于定时器与事件驱动的状态转换机制提供了很好的支 持。数据库对大规模数据的集合运算,以及并发操作,原子操作都提供了很好的支 持。Matlab对于大型数值计算支持与优化。以及coroutine机制支 持的erlang与GO语言。当然随着技术发展,每门编程语言应用范围越来越 广,同时随着人们的计算需求的发展,还会更多的语言被开发来应对这些新需求。

表达式

加,减,乘,除的常规运算。 离散位运算,与或非,移位运算 逻辑运算,比较

代码块的复用与扩展

每一种语言都会提供代码复用的机制,邮最初的汇编语言的那些中断函数开始。到 C语言等等函数的功能,以到C++,java等面向对象的机制。都是为了解决 代码的复用性与易读性问题。我们编程与在框架设计的时候原则,对于功能比较小 公用模块,例如一个计算公式就可以函数来实现。但是公用模块的复杂度提高,利 用面向对象类的机制,对其实现比较适合。对于更加复杂的共用模块,但又不适合 用函数与类实现,可以考虑用模板来实现,例如你会发现IDE工具生成各种各样 样版代码,这就要元编程,你可以用lex/yacc来实现,可以利用sche me来实现。为了进一步提高提高代码灵活性,把数据与函数是不区分了,也就产 生了函数式编程。对于代码动态调用:尤其是脚本语言,是灵活复用性,采用动态 生成代码,直接运行。对于整个过程自动化,很有帮助,例如每一个脚本语言都会 一个eval指令。基于不同的计算模型,编码的方式也是不一样的。

当代码的代码功能不足,有问题,但是你又不能直接修改其原始代码怎么办,这时 候,OOP的继承,重载就起到作用了,只写一个新类继承原来的类,并且只需要 把对应的代码改掉就行。 这样原来的运行的代码没有任何影响,需要新功能类, 就可以使用新就可以了。

对于编译型语言的好处,可以快速解决语法错误,其实节省了大量的时间。但是却 但是自身不能执行,并且添加了部署的时间。解释型语言来说,虽然节省了部署时 间,但是缺少事先的语法检查,增加了调试的时间。每一个错误的出现都有等到运 行的时候,才能知道其对错。但是能有一个事先的语法检查,那样就可以大大提高 开发的效率。另外一点,那就是相对于来说编译型语言的api水平太低了,需要太多 的细节来才处理,当然可以用一些成熟的库来实现脚本语言一样的简便功能。

新语言的产生一方面是应用场景的变化,另一方面那就是设计的改进了,C++ 改进了C, 而Java改进了C++,而C#又改进了Java. 可以参考http://coolshell.cn/articles/7992.html

面向对象的数据模型和面向数组的数据处理着眼于静态环境下构建数据模型,或是以带有标签属性 数据集合的形式,或是包含结构化数据组的形式。 而函数式编程强调动态地构建数据模型,通常是以计算流的形式。学习函数式编程的基础对数据转换操作 的结构大有裨益。 事件驱动编程,计算管道是处理数据转换各分析的一种出色方法。

函数

递归函数是悖论一个很好的表达形式。 同时构造悖论就像写递归函数一样容易了。同时利用状态机来环路 来就像一直悖论。同时悖论的打破要从外部来实现,并且也常常是系统的最优解位置。

计算模型的原型

编程语言最终反映了两个方便的东西,那就是资源的管理,以及基于资源实现的功 能。由于我们支持能力与认识不同。采用了分层模块的方法把难的东西变的简单可 实现。我们在硬件操作的加了操作系统,操作系统之上我们又加了各种库等。 从进程,线程,协程就是把资源的管理方式,一步步的提升。让从我们可以编程语 言层面就可以控制资源。从效率来说,那就是最好能够直接编程写2进码。或者让 我们编程尽可能靠近二制码。就是例如提供各种语言到汇编的直接转化。LLVM 现在就是这样的一个项目。例如CUDA对于python的支持都是这种原理。 corepy google支持的把python直接转化为汇编。 各个平台的通用化过程,其实了简单,源码或者中间码再加上一个JIT编译器就可以 了。pyasm 目前都是基于LLVM在玩。

另一个方向就是程序验证如何保证程序百分之百的正确呢。

编程语言的本质逻辑,逻辑的最好表达方式那就是图,这也正可视化编程的方向。 同样是不是可以在代码里直接加入表情字符,例如int用一个图形来表示,fl oat,array,dict各种的图形来表示,但是写代码本身文本就像可视 化html的开发一样。就像现在html写介面是一样的。有这些标准控件可以 搞定了。把注释变成事例这样会很方便。

Perhaps of all the creations of man. Language is the most astonishing.

一个语言的完备性也不是那难,一个语言需要原语并不多。只形成这样闭环。就能形成一个小的系统。 当然一旦形成这样一个闭环,也就很难自动突破。

The right language can make all the difference in how easy it is to write a program.

什么时候需要再创造一门新的语言呢。

当你发现在你要为一个小功能,写很多的代码的时候,或者你现有的语言来表达你的逻辑与流程非常麻烦的时候。 这个时候,就是要创造一门语言的时候,语言的大小,是根据要解决的事务本身的大小来决定。 当然语言发展都是根据计算模型来的。

例如那个printf函数簇那就是一个小符号系统。 正则表达式是也一个小符号系统。grep,awk,sed等等都是基于正则式。 巴斯特范式也是一个小符号系统。 protobuf也是一个小符号系统。 一个简化版本,那就是pack/unpack package的函数。

int pack_type1(unsigned char * buf, unsinged short count,unsigned char val, unsigned long data)
{
     unsigned char * bp;
     bp = buf;
     * bp++ = 0x01;
     * bp++ = count >> 8;
     * bp++ = count;
     * bp++ = val;
     ....
     return bp - buf;
}

#include <stdarg.h>

/* pack: pack binary item into buff return lengh */
int pack(unchar * buf, char * fmt, ...){
    va_list args;
    char ap;
    uchar * bp;
    ushort s;
    ulong l;

    bp = buf;
    va_start(args,fmt);
    for (p = fmt,* p !='\0'; p++) {
        switch(* p) {
           case 'c': //char
              * bp++ = var_arg(args,int);
                break;
           case 's': //short
              s = va_arg(args,int);
              * bp++ = s>>8;
              * bp++ = s;
              break;
           case 'l': //long
              l = va_arg(args,ulong);
              * bp++ = l >>24;
              * bp++ = l >>16;
              * bp++ = l >>8;
              * bp++ = l;
              break;
           default:  //illegal type character
             va_end(args);
             return -1;
        }
    }
    va_end(args);
    return bp - buf;

}
pack(buf,"cscl",0x01,count,val,data);

例如把可以log的输出直接写另外一门语言本身。 这样拿到log就直接执行,就可以分析出大量问题。

当你实现了新的符号系统,一个原来系统中复杂的事情,在新的系统中却是非常简单方便的。 对于正则表达式,用状态机来实现,然后breakdown一下也就简单了。当然如果看到通配符,就要往前看一步了。并且采取的是从取左往右,还返过来都是不一样的。 如果用列表来表达些,最通过的表达那就是x:xs 这种前缀表达式。

而最终的目标

  1. simplicity
  2. clarity
  3. Generality
  4. Evolution

复杂的问题,可以在同级采用设计模式来解决,在不同级采用元编程来解决。 元编程来实现循环。 生成代码->再用进程替换来不断的执行。通过进程替换来实现代码加载与切换,同时又通过环境变量来进行数据的传递。

ProgrammVerification.rst

framework

对于任何一门语言都会有自己特定的编程模型,以及编程接口,以及硬件实现,以 及优化。所谓的framework就是一个pipline而己。例如OGL, make,ant,等等都是一个pipline而己。同时decorator 也是pipeline的一种体现。 函数的调用也体现的是一种pipelin e。代码的执行顺序也是一种 pipeline. 如何快速设计一个pipl ine呢,最简单办法就利用现有的例如make,或者在现有的基础上进行二次 开发,ruffus,以及python http://www.ruffus.org.uk/. 这样的东东很多。 以及mapreduce也是一种pipline. 如何动态创建pipeline,其实最简单那就是列表,这也正是 scheme,haskwell,语言特别适合创建pipeline的原因。 因为它们返回值,要么是值,要么是一个列表或者列表还是可以嵌套的。那个是C 语言本身不具备的,C语言只能简单的返回值,如果用到列表,就要利用指针显示 分配内存不是很方便,

语言一般都会包含五大块, build,compile,debug,profiling,verifi cation.对于程序本身来说,语法,关键字,内建指令。以及基本教程。而 这些都已经有现成的工具。xxxdoc可以直接查询,加上的IDE工具,以及 相关的API查询工具。并且还可以vim集成。 不管是什么样framewo rk,其本质都是为建立一个pipeline, framework = p ipeline在不同的地方叫法不一样,我需要解决问题的时候,如何才能利用 这个呢,那就是根据pipline不断把问题breakdown.达到很容易 解决为止,这也是daniel他们的过人之处。而自己还是大部分时候依赖经验 。没有能够把问题与工作不断的breakdown.

如何同时多个工作的面前还能focus,一个办法,利用不同的时间跨度来解决 ,其实就是最终的办法,例如一段时间固定一两个sample,然后把的测试都 给过一变,就可以把当前的时间focus在一个事情上,同时也不会浪费时间, 最终会把所东东都搞定。

compiling 本身是为了解决代码的复用,以及各种格式之间转换,例如 不同的架构的支持,以及各种ABI的支持。这些都是传统的最基本的。另外一个 就是编译效率的问题。并且编译与profiling以及debug相关,它们 都需要特殊compiling配制。 为了加快编译的速度,并行编译,以及可以分段离线编译,例如直接现成的编译好 的汇编可以直接用,直接将作原文件来编译,这样的好像一个是离线编译加快速度 ,另一方便在做代码优化的时候,就可以使用在关键的地方使用汇编了来优化了。

而现在的新的趋势,就是分层模块化。模块自包含。对于代码也构建也是一样。除 了各种库的依赖。另一方面那就是代码的优化。或者达到像人工写的汇编,或者人 写的汇编更强的代码。这个就像代数公式先画简再求值。而现在LLVM就是研究 解决这个事情。而CUDA本身也是利用LLVM来实现的。

对于优化很大部分那就是根据硬件平台的不同,采用对应的库,这样来加速计算。

当然所有东西都不会那么完美,特别并不是每一个人每时每秒都会尽十分的力。要 接受不完美,对于编译#pragma warning(disable) 来 对一些编译选项的控制,http://baike.baidu.com/view/1451188.htm#2_5 哪些情况下会用到这些,一个定位编译 错误的,例如找的路径不对,当编译在此的时候打印信息,或者error对出就 知道到此来过。另外那就是每一个文件的个性化设置,之前还在想如何对编译实现 不同粒度的灵活控制,其实继承重载是最方便的灵活控制,只需要改动你需要的。 其中一种方式那就像unreal一样直接用C#来做编译系统来实现灵活的控制 ,或者使用gradle来实现灵活的控制。

build,主要是解决依赖,以及集成的问题。

profiling 是对程序的透明性的讽刺,优化就意味着要针对特别的结构 来适配。透明性是解决万能性的问题。profiling之后的事情,那就是重 构,设计模式是重构的出来的,但是如何快速重构,这些都是需要工具支持的。对 于文本处理来说这个比较难,可以利用cscope再加上vim的编辑功能,或 者直接使用structure editor,而各个语言的IDE正是工具。

verification 如何来保证的正确性。测试驱动开发是一种,但不是 全部。更重要的还是逻辑的正确,这个正是programming验证的事情。

interpreters,Compilers,Virtual machines

主要是效率的问题,但是网格计算应该用的虚拟机吧,这样才容易部署。才能有效的计算。

采用Compiler相当于一部分计算前置。

对于树形结构计算可视化

利用目录+文件来实现其可视化, 可以用目录与文件名来表示,变量名用文件名,内容就是值,再用一个特殊的文件当做代码来执行。

还有于图形计算可以化

直接把每一步过程进行screenshot,然后PIL来重新播放,这可以了。而在render时的可视化也这种实现方式。 例如每一步,每十步或者每一分钟生成一个screenshot,就实现了计算的可视化。

元编程

什么需要元编程,元编程一般都至少两级编程,如果能实现三级的编程就可以实现代码的演化。 A->B,B->C,C->A. 这样能不断演化。

具体点来说这些情况用元编程更简单

  1. 原来写代码实现特别复杂,这个时候就要考虑元编程了。把基本操作当做元,然后生成二次操作。 就像画电路板时,一层板太复杂时,就二层板或者多层板来实现,就会发现简单多了。

  2. 其实编译器就相当于是一种元编程

  3. 原来实现不是那么简练,使用元编程,采用二次的编程就会发现简练了很多。

  4. 那一种快速的流水线化,把产生的log格式规整一下直接变成python代码,再添加一些操作,就省去解析的工作。 当然这一步也可以手工做。 例如生成的log,然后再python 来解析log,那为什么不直接写成python的格式。 例如

    log(self,tag,content,time):
       printf "tag = { time: {0}, content:{0}}".format(time,content))
    

    这样出来不直接python 数据嘛。

    • 把一个目录大部分文件都删除,只留下一部分。 如果直接写是不是要一个循环,还得一堆的if else 来判断,挺麻烦呢。还是调试看看出错了没有。 这样呢,ls > del.sh 然后vim del.sh 把不必要删除文件,直接删除掉。 然后 :%s/^/rm -f/ 不就完成了脚本编写。并且不需要调试,基本不会出错。 再后 sh del.sh 一执行不就完了。 是不是简单多了,你所需要的知识也是一条 rm。 并且快速高效简单的完成任务了。

    把代码实现这个过程不就是一个元编程。

生成HTML 也是元编程表现之一。 用代码生成RST 也是元编程表现。 基本是生成结构化的机器友好的代码都代码都是元编程一种,与其中间产物,然后再解析,还不如直接用元编程来的简单高效。

特别是在测编译器的时候,就经常需要生成源码编译,然后再执行其结果然后再比较结果。

另一种情况就是,literate programming. 这是一种新的编码风格。

  1. C用Macro,以及C++用template等等都是一种体现。伴随着元编程的出现的技术那就是JIT. 这个最明显的例子是shader的编程。

同时采用元编程也可以问题分阶段执行,这样可能会减少最终的机器指令,而提高效率。

函数调用本质

就是一个stack状态机的过程,一个进栈与出栈的过程。 所以正常的函数调用,那就是进去多少,就要出来多少。 所以只要CPU本身支持栈操作硬件模型,或者后期软件一个栈模型,就可以实现函数调用的功能。 进栈出栈采用打包的操作,或者采用定界符的方法。然后再加上一些回调实现了执行。例如+ 对应 sub这样的元函数。

运行时候常见错误

#. unhandle exception memory address,access violation reading location: 都是因为使用到一个错误的指针地址,还有一些函数指针,逻辑错误导致指针达到 一个错误的值,例如直接00001之类的一般直接到指内核区域,还有代码区域 ,每一个区域都会不同的读写权限的。如果数据指针指错地,可能会改了别人的数 据,而如果函数指针指错了趣,结果就未知了,会把乱码当指令来执行的。

#. can’t hit there is no debug info in the so file. you could use nm to check debug symbols. C:nvpackandroid-ndk-r10toolchainsarm-linux-androideabi-4.8prebuiltwindowsbinarm-linux-androideabi-nm.exe

XXdoc

Language Usage remark
pydoc topics  
cpandoc/perldoc perlfunc/perl/perlcheat  

Build

解决依赖工具 例如报缺哪一个文件,可以快速查到哪一个package里有这个文件系统里的里 apt-fileapt-cache 都是用来解决这个问题的。 而这些都是包管理解决的问题,来解决这些依赖问题。

另外一个那就是准备编译环境,当然也可以采用预编译的方式来加快编译,也可以 用InrediBuild 来并行编译。无非那就是准备toolchain, 然后各种编译的选项以及环境依赖的准备,在linux下 .configur e来实现配制。对跨平台可以用 xpj.cmake 等等来实现。

对于编译错误,简单的语法错误很容易解决,另一点发现调用不对,或者说找到声 明或者头文件。只要看一下编译选项就知道了,对了gcc,make ,ant 以及msbuild都应该有debug 选项。

对于链接错误,找到对应的库,利用上面的依赖工具来到这些库,还有ingor e undefined symbols,以及循环依赖的使用。另一个那就是 toolchian的工具与库之间版本兼容性,例如linker就是有ld. golden ld 几个版本。可以试着换一下。

并且这些可以参考gentoo,kernel module以及Pentak ,Nexus,QuadD的编译。

COM
shell扩展

命令式程序设计、面向对象程序设计、函数式编程、面向侧面程序设计、泛型编程 多种编程范式。泛型、LINQ ` PLINQ <http://msdn.microsoft.com/en-us/magazine/cc163329.aspx>`_ 和 Futures 对于面象对象的语言,类的静态变量与静态代码是在类进行构造的时候,就已经要 执行了。是先于任何运行时代码。通过自己的debug来快速的深入底层。

什么是Dynamic Programming 与Linear Progr amming?这两个不是编程语言,一个是线性规划与是动态规划。

目前的cardhu 的板子已经做好了lua支持,并且已经有了这个解释器也 已经做进来了。

mparation with lua and C

See also

needing study

OOP

现在才OOP的复用有了更深的认识。 现在对于继承的好处,那就是按需修改。需要什么修改什么。继承与重载。中间插入一个最长匹配查找功能。 得到了非常灵活的应用,只要修改需要的部分代码就复用大部分代码。 跨平台的时候,再通过宏定义把抽象层与实现层的mapping对应上也就搞定的差不多了。 大部分的代码就可以直接复用了。 OOP一部分是事物本身的逻辑,另一块那就是事务的功能。在整个继承关系中,这个函数放在哪一层实现最平衡呢。 太接近基类,每个类的包袱有点大。 太接近低层,复用性得不到更更好的应用。 所以应用的分级分类也是类层次设计的参考基准之一。基类肯定是一些更基本 的东东。这样就可以利用不少的代码。 并且在调用函数的就要有一个不断查询虚表的过程。

函数式编程

函数的本质就是替换,再进一步步何时替换,这样就与变量的生命周期相关的。 而一般的函数变量只能是局部一次性的,所以也就无法惰性求值。惰性求值就是替换的变量的 生命周期。 它的基础 λ演算 Lambda_calculus ,但是它的原理还没有看 明白。这是一个例子 解释1 这个有点浅显了。

APIO讲稿——函数式编程 这个讲的比较浅显易懂,核心只有

三条采用BNF:

1. &lt;expression&gt; ::= &lt; l abel &gt; 1. &lt;expression &gt; ::= λ &lt; label + &gt; . &tl;expression &gt; 1. &lt;expression &gt; ::= (&lt;e xpression &gt;&lt; expression &gt;)

1,2 用于产生函数,第三条产生调用,同时还有两条替换,代入法则。另外还 有那就是部分求值(学名叫柯希求值,也就是自由变量的定义),就像复合函数一 样,每一次只看一个变量。这样就形成λ演算系统。对于递归,还有一个不动点。 不动点就相当于评介返回值。 再加一些基本规则,例如与或非,就构成了完整的 推理系统。而lisp,scheme正是基于此的。

并且函数式编程采用的惰性求值,所以你可以定义奇数,偶数这种抽象的定义,而 在之前的编程中是不存在抽象的定义,只能是一个具体的数。而这些正是符号计算 与证明的基础。

函数式编程方便并行计算。 λ演算 就只有替换与单参数的函数,就是进行替换然后进行基本运算。并且是左 结合的,这也是python里为什么可以连着写的原因。并且函数式编程实现变 量只定义一次,大大简化了后期编译优化工作。 同时从这里也提到停机问题,停机问题,那就是不是能够检测死循环。

63a6e.html>`_ * 形式语义学-Lambda演算 还没有完全看明摆。

通过对 pandocfilter 的python 接口的实现对于函数试编程有了进一步的理解,函数可以嵌套定义,动态构造函数,可以输入来定制函数, 而函数编程更是把函数的自由替换达到M4的水平,同时解决了M4 替换没有边界的问题。

来实现一个最简单的C语言版本的field吧。

static int func()
{
   static int i = 100;
   if (i >0)
   {
      i --;
   }
   return i;
}

思考

Coroutine and Contination IT is just like interrupt of the OS.

Actor、Coroutine和Continuation的概念澄清 Continuation 概念与协程(CoRoutine)

其本质也就是函数本身能够记录自己的状态。这方法多的事,对于python来 说,那就是函数直接当做对象。这像可以很多事情了。例如python中的yield的指令。

另外一个方法那就是函数内部直接使用static在C语言里,来直接记录函数 的状态来实现yield的功能。

– Main.GangweiLi - 16 Aug 2012

如何学习编程语言 每一门语言都有其优缺点,通过学习每一门语言来解决特定的问题,并且掌握每一 门语言的优点。没有一门通用的语言,所以要知道每一门语言的精华,同时对于算 法来说,是无所谓的什么语言的,只考虑功能的话,但是考虑功能与复用的话,这 时候每一门语言才有其不同。

– Main.GangweiLi - 28 Oct 2012

debug 在出了问题,最快的方法不是逐行debug,而是根据业务流 程,然后进行二分法,在函数调用问题上,看一下函数的调用链。其实就是定位问 题界限,是在函数范围内还是范围外。在调用路径上进行二分,这是最快的方法。

– Main.GangweiLi - 30 Oct 2012

加强对于编程语言理论的学习,来提高自己能够快速应用各种语言的能力。而不是 去学,而是去猜与查。

– Main.GangweiLi - 01 May 2013

重载 以前只是知道定义,现在才有了更深的认识,例如你有一个标准流程,后来有了有 改变,但是只有一个地方改变了,其他的都不变,怎么办呢,用一个新类来继承原 来的,只需要需要改变的那个地方重载一下,并且还可在其内部调其父类的内容。 这样机制大大简化了对于变化的应对。

– Main.GangweiLi - 29 Jul 2013

一般情况下,递归算法效率相对还是比较低的,例如我就只是求了,一个二次函数 的递归。发现超过了,20需要的时间就会大大增长了。递归算法的时间复杂度 分析 ,递归是会耗费栈的 ,递归的层数是不是有限制。递归算法,程序开始计算后无响应- CSDN论 坛- CSDN.NET

– Main.GangweiLi - 16 Aug 2013

类型转换 例如int -> short就会截断,截高位,低位保留。符号扩展。

编译 一般情况下,会采用每一条语句单独一段汇编代码。如果没有经过优化的话。但是 如果优化了。就不一定了。因为一般情况下,CPU是只支持四个字节的操作。l oad+ALU+store 模式。所在浮点数计算是汇编代码组合实现的,而 非直接对应出来的。

– Main.GangweiLi - 17 Aug 2013

闭包 也就是子函数可以直接访问父函数的局部分变量,类似于线性空间的闭 包运算。看来是时候把泛函这些东东好看看的时候。简单的东西都已经被实现软件 简化的差不多,下一个时代估计就那些理论了。例外闭包运算可以方便去解决三级 内存问题,你如GPU的多级内存速度不同,函数式可以更加接近算法本身的逻辑 结构,对于编译来说更加容易分析依赖关系。特别适合于自动计算__share __的memory的大小。

– Main.GangweiLi - 18 Sep 2013

反向工程 要充分利用语言的反射机制,与动态gdb的手段。例如动态加入断点。这样可以 大大加快自己的反向速度。

– Main.GangweiLi - 30 Oct 2013

进程的输入输出 以及working space,脚本本身的路径都是很 重要的属性,而二者往往是不一样的。今天所解决的%CD%的问题,就是由经引 起的了,如果没有设置的话,那就是继承父进程的working path当做 working space.

– Main.GangweiLi - 26 Nov 2013

dll 使用动态库方法,一种是头文件,知道这些symbol,在编译的 时候,加入链接库使其通过。所以要使链接能通过也很简单,只要知道让所有符号 能找到位置,但是另一个问题,那就是符号地址的分配问题。哪些符号分配到里。 并且函数根本定义是在哪里。 例外一种那就是要动态加载,这两者其实是一样,自己load这个库,然后取其 直接执行。现在python就可以直接调用.net是不是就样的机制。

直接在脚本语言中调用lib.so 这个在python中是可以直接调用 的,通过ctypes,这个如何实现呢,要么通过SWIG这样为tcl实现, tcl也可直接load dll , 实现方法估计就是把dlimport,dlsymol ,dlclose封装一样,例外就是如让CPU来执行它的问题。 是不是也需 要动态链接器。其本质就是控制CPU的指令执行,把它想像汇编代码就一样了。

当然也一种办法也就是现在JIT,这种动态编译,然后直接执行它。例如s

hell可以直接调用gcc来编译,然后直接执行。

– Main.GangweiLi - 28 Nov 2013

如何用函数编程实现并行 只需要在函数内部实现一个计数器,然后调用一个函数,直接用线程或者申请另外 计算单元直接执行它,并且把计数加1,当然这个计算单元完成之后,再把计数减 1,主函数然后等待或者定时查看计数器当计数为零的时候,就要说明函数调用完 全。当然也可以用C语言再加多线程与硬件驱动来实现并行计算,而cuda就是 这样一个例子。把pentak中多线程改成这种模型。

– Main.GangweiLi - 14 Jan 2014

弱引用 可以用来 实现缓存机制,原理那就是什么时候删除那些不用数据。这个是垃圾回收策略,同时也对用过的数据处理模式。 之前所谈都是预存取,对将要用到数据如何处理。垃圾回收是对用过的数据如何处理。两者很重要。

– Main.GangweiLi - 26 Apr 2014

loop vs recursive 到底是哪种效率高,这个是要看环境与具体实现的,在C 语言是循环,而在函数 式语言里是recursive,另外还要看最终实现是采用栈的方式还是直接j ump的方式来实现,这个是编译有关的,另外在并行环境是如何实现的。与实现 有关。loop 与递归哪一个运算效率高,这是由硬件来决定的,那就是硬件的 每条指令的周期是不样的,循环依赖跳转,而循环依赖call指令,但是cal l也可以由跳转实现的。就看硬件是如何实现了。另外递归的深度与内存大小有关 。

– Main.GangweiLi - 08 Jun 2014

LINQ,Parallel LINQ Language-Integr ated Query 这个就像numpy的那些功能一样,而在C#中它这些 都集成到编程语言了,其实就是相当于把一些通用底层功能直接变成元编程并且编 译器层面去实现。用一定模式然后用LLVM直接直接做掉的。这也就是谓的分层 编译技术。也就是在C#具有一部分SQL的功能。 http://baike.baidu.com/view/965131.htm http://blog.csharplearners.com/tag/directory-enumeratefiles/ http://msdn.microsoft.com/en-us/magazine/cc163329.aspx Running Queries On Multi-Core Processors

Element of programming

程序的设计就是一种迭代过程,研究有用的问题,发现处理它们的高效的算法,精炼出算法背后的概念,再讲这些概念和算法组织为完满协调的数学理论

语言的抽像模型从 汇编->过程->OOP->逻辑->数学模型 asm->C->C++/Python-> prologic/FP -> Haskell等等。 转化的基础,对比python 与C++ OO的实现原理。 如何把OOP还编译成ELF呢。

语言学习发展曲线的三个阶段

阶段一,厚积薄发

写代码,就像写小说,要想写好小说,不读个百八十本小说,肯定也是写不出来的。写软件也是一样,不去研读几个一些经典软件代码,想学好软件开发是不可能的。通过读别人的优秀的代码来学习编程是直接高效的。现在优秀开源代码多的是,你可以根据自己的能力与兴趣来研究那些源码小说,首先是运行一下,看看它长什么样,了解其运行原理,然后再理解其软件架构,好的开源代码,都会相关的文档来讲述其架构呢。有问题去找度娘与谷姐。同时手边放本编程语言的书籍,开始你的代码阅读之旅。根据个人经历,如果对你操作系统比较感兴趣,可以去linux内核与minix内核源码(个人感觉minux是会更具启发性)。如果你对网站比较兴趣,去读一个wiki的源码去看看吧。如果没有特别感觉兴趣的,那就去读coreutils吧,这里面包含操作系统最基本的cd,ls,sort,cat,find,grep之类的源码。了解这些最常用命令的实现原理,对你使用这些命令会更加得心应手,并且在开发大的系统的时候,都会需要这些需要这些常用的功能。你可以容易把这些功能移值进来。

这样的学习好处,在学会了一门编程语言的同时也学习一种构架设计与一个好代码风格。通过研究这些经典代码,对你自己编程技巧也会有很大的提高。你会熟悉常用的一些算法,以及经典设计模式。以后遇到复杂的算法,也知道如何把它拆分几个子算法用这些常用算法来实现。此外也能通过此对一个软件熟练精通,知其然,且其所以然。可以说是一举多得。

阶段二:提高效率

到时候,就会感觉只要给时间与精力,老子什么都能实现,但是现实往往是没有那么多时间与经历,慢慢你会感觉到效率的重要性。并且开始修炼自己的效率。

文本处理处理的能力你与计算机交互大部分都是通过文本与编辑器来实现的。所以文本处理效率高低,直接决定了你工作效率。如何实现批量处理呢。对于文本处理,核心的技术就是正则式,并正则式是在编程武器排行老大:长生剑。对于正则式,光知道是不行的,必须熟练才行,熟才能生巧,才能出效率。所以熟练使用一种支持正则式的编辑器。两大编辑器中的神器,vim与emacs.两者都对正则式具有完美的支持。至于选择两个根据自己偏好(本人在纠结了一年后,最终选择了vim).对工具本身也达到能做二次开发,例如写个语法文件呢,随时写些小的插件,来尽可能使一些重复文本编辑工作自动化。

数据处理能力两组数据的集合集合运算.最常用的交并补。别小看这些东西,经常见一些在分析log,定位问题的时候,人为了找到两组数据差异,就纯粹用两眼一行行对比的。心里在想如果两种数据在数据库里,可以用数据库多方便了。其实那些常用的交并补运算,完全可以用sort,uniq,diff,再加上正则式做一些格式化来实现。三两行就完成了,要比你用眼一行一行对比,快千倍了。同时也要熟练一些小型数据库技术,例如sqlite(因为如果用mysql,postgres用于临时分析用的话overhead太高),因为在定位问题时候,数据量比较大的情况下,你可以用正则式把原数据进行格式化处理,导到sqlite中,利用sql来进行分析。

Debug能力代码不是写出来的,而是调出来的,调试快慢基本上决定写代码的速度。你如果达不到下面Debug合格水平,就要好好修炼了。标准如下:

  1. 批量给添加断点:例如在所有与ABC开头的函数前面添加一个断点。
  2. 自动检测常个变量或命令的状态变动,并保存相应的log,(对于一些复杂的,sometimes ,不容易重现的问题,log是对于定位问题是关重要的)。而不是靠人眼去盯着。
  3. 半自动化调试,在定位关键问题的前期一些步骤是不是能够自动化,执行到关键自动停下来。

Template与元编程:走到遇到大的一些软件功能,有些功能具有通用性,但是有点复杂又很难抽象成函数或类。这时候就要用template与样板代码。例如对于共性比较大,IDE开发环境,会自动为你生成代码模板。但是对通用性还没有达到你让IDE开发工具提供商帮助实现这些模板代码。但是这些功能对于你说,很通用,经常遇到。特别生成配置文件的时候。这个时候,template与元编程就很有用了。如果功能只需要一个静态的template,那么一般template技术就好可以搞定了(建议去研究一下,perl toolkit template库)。如果需要动态的template就用到元编程了(这个建议去研究一下,scheme语言,它做这个比较擅长)。

在这个阶段你要经常到开源社会区去转一转,加入一些邮件组,看看有什么时最新的发展,例如我个加入vim,fowiki,graphviz的邮件组。定期去sourceforge上去看看当前有什么新的软件与技术出现。

阶段三:创造自己的语言

等你走过了第二个阶段,你的手指在键盘键指如飞,能做到指随心动。走到这个时候会感觉效率进一步提升遇到瓶颈了,并且慢慢发现原来编程语言以及工具的一些不足了。会有一种改进这门语言,甚至是重新造一门语言的冲动了。

到了这个时候,你已经对一个领域有了深入透彻的认识。你还需要学习巴斯特范式,编译原理以及lex/yacc做一些词法/语法分析,内存数据库(在构建符号表的时候会用到)。经常用google学术看看最新论文找一些启发与灵感。等这些东西准备好了,就可以对这个领域抽象建模了,基于模型去创建一门小的DSL语言。并为之开发出相应debug工具等。并在实践的应用中不断完善它。

计算机模型发展->计算机硬件体系结构的发展-> 计算语言的发展->逻辑思维的发展。

软件发展这么多年,常规的逻辑都已经有了各种各样的优良的代码库放在里。基本上但反是有规律的,都是可以用计算机来做的,简单的问题,有一些简单的编程模型,复杂的都可以用设计模式的,都用元编程写DSL来实现。 当然各种规律与人的思维是不全面的,是有局限的。这反映在代码上,那不是那么灵活与高效了。 所以常规有规律的事情可以代码来做。而让人来解决灵活与高效。 这一块,也正是人与机器的区别。也是机器短期内取代不了人的地方。当然重复无差错执行有规律的事情是人不如机器的地方。 就像电路板一样,人的作用是重构与架设飞线的那部分。

然后再把重构与架设飞线的那部分,规律化->理论化->转化代码让机器来执行。这样不断的循环往复,来探索更高层级的知识与智慧。以及至于达到代码的自动演化功能。其实就像递归。并且如递归在某些条件下不反回值,直接跳转。这就实现演化。或者递归转化循环。

(三) 自己这几年用过的编程语言一些体会

C语言,最经典的高级编译型语言言之一,性能是脚本语言所无法企及的(只有手工调优的汇编程序的性能才能超过它)。操作系统和设备驱动程序以及嵌入式系统中只能使用编译代码来高效地实现。实际上,当软件和硬件需要进行无缝地连接操作时,程序员本能地就会选择C编译器:灵活的指针应用并且可以直接操作内存,距离“原始金属材料非常近” ——即可以操作硬件的很多特性——并且C的表现力非常强大,可以提供高级编程结构,例如结构、循环、命名变量和作用域。虽然目前随着嵌入式性能的提升也开始对C++,java的支持。但是支持最好的还是C.在这方面你会找到大量的C库来供你使用而避免你重复造轮子的工作。

java语言可以一次编写可以到处运行,如果你的应用环境需要跨平台的,可能你的java是你最好的选择。并且在金融行业,以及ERP软件,以及互联网行业对java的应用库多一些。不过本人只是学生时代学过,没有项目应用经验就不做评论。

C#语言是与面向对象,与java相抗行一门语言,这门语言的产生根源于商业竞争。如果你是windows平台的应用程序,C#,C#.net就是一个巨无霸。可以在windows平台做任何事情。

perl文本处理之王由于本人擅长文本处理。对于perl的了解深入一些。那就谈个人愚见了。

  1. 对正则式的完善支持。对于文本处理,正则表达式是核心。一般语言正则表达式只能硬编码或者对动态生成正则式支持很弱,而perl的正则式是完全可以动态生成。这对于复杂的文本处理极其有用。
  2. .对于perl的诡异符号的解读。每一个诡异符号的背后都是一对常见问题抽象。当你学会一个诡异符号,你就可以简单用一行命令来解决这一类抽象的问题。由于perl自身历史较长,一些常用符号已经常用功能给占用了。所以才看到这诡异符号。当你解决问题时,遇到perl的这些诡异符号,这说明你的遇到问题,已经被历史上的大牛们给完美解决了,简化为几个符号了,而你不必要重复造轮子了。而在别的编程语言中你可能为这个功能再写一坨代码。所以爱上这些诡异符号吧,当然有人会说代码不易读,其实perl有pod文档,让你他随时随地写文档来说明它。
  3. 对于报表格式的支持。如果报表与图表话,你使用perl format指令就知道会有多方便.对于更复杂一些paper工作,例如一些user manual的编写排版。perl的template toolkit模板系统,让你消除排版与多种格式(html,pdf,xml)输出问题。
  4. pod文档系统。大家经常代码没有注释,不易读。另外在编程语言中对没有什么排版支持。那么你来看看perl中,perl语法的灵活性再加上pod文档系统。让你感觉不是在写代码,而是在写文档。把代码嵌在文档中,而不是注释写在代码中。编程界一个倾象文学化编码。可能对它是天生的支持吧。把代码嵌在文章中。并且将来生成多种格式(html,txt,pdf).
  5. web编程。perl是最早用于web编程语言之一。如果你对perl的web编程还是停留在CGI编程,就像你对C语言的认识只是能写hello Word!阶段。perl Catalyst框架,就像MFC之于VC. AWP可以轻松实现web client端编程。
  6. CPAN,windows编程之所以强大是因为有MSDN库。而CPAN就是perl的”MSDN”.

tcl/tk自己的工作语言。工业自动化的标准.以及Expect对于命令行交互的终极武器。

  1. 交互式协作,特别是关于时序与状态的编程是天生的支持。因为tcl/tk发明它的目的就是为了测试电路的。
  2. 所有的事物可以重新定义和重载,所有的数据类型都可以看作字符串。
  3. 可以容易嵌入其他语言中,在大型系统中作为二次开发的脚本语言。
  4. 通用SWIG很容易用C/C+
  5. tcl扩展Expect利用Unix伪终端包装其子进程,允许任意程序通过终端接入进行自动化控制;也可利用Tk工具,将交互程序包装在图形用户界面中。

Scheme语言 作为元编程中主力语言,本身是一种函数式范型语言。Emacs扩展脚本语言,(scheme是Lisp主要方言之一)。DocBook的样式表DSSSL语言。

Lex/yacc 如果想自己实现一门小的语言,那么就来研究lex/yacc吧。也许你会奇怪linux下面的小语言为什么那么多,awk,sed都有自己的语言,就连bc这个小算器都有自己的语言。是不是感觉老外实现一门语言就像家常便饭一样,而对于国人,操作系统还有人敢说自己动手做,但是对动手实现一门语言,还是就充满了神秘与敬畏。其实设计一门语言也没有那么难。如果你想打破这个设计语言这个神秘的面纱,就来看看lex/yacc吧。如果实现多语言的翻译与转换,也可以参考一下antlr.

python, 最近开始使用做代替matlab做一些计算,由于是比较新的语言,集成了之前的语言的各种优点,并且再接近人的自然语言。并且有google这样的大公司的支持。前途不可限量。