博客

  • Lua的好和不同 part1

    翻译自 http://notebook.kulchenko.com/programming/lua-good-different-bad-and-ugly-parts

    我已经用Lua编程了9个月,应该是时候停下来想想这段经历了。过去几年用过不少编程语言, perl, C, Javascript, MATLAB还有其他的,从TurboPascal到F#。Lua和这些语言做个比较是件很有意思的事情。我已经用Lua完成了一些不同类型的项目:一个远程调试器MobDebug https://github.com/pkulchenko/MobDebug ,扩展一个Lua IDE https://github.com/pkulchenko/ZeroBraneStudio ,一个mobile应用https://github.com/pkulchenko/LuaRemote ,还有几个教育性质的脚本https://github.com/pkulchenko/ZeroBraneEduPack ,以及一个在浏览器canvas上使用Lua画图的demo http://notebook.kulchenko.com/programming/drawing-on-browser-canvas-with-lua 。

    我已经看到有比较Lua好坏的文章,比如(http://lua-users.org/lists/lua-l/2007-11/msg00248.html http://blog.datamules.com/blog/2012/01/30/why-lua/ http://lua-users.org/lists/lua-l/2012-01/msg00731.html http://stackoverflow.com/questions/564665/advantages-of-lua http://gergely.imreh.net/blog/2011/07/language-of-the-month-lua-part-2/ http://stackoverflow.com/questions/1022560/subtle-differences-between-javascript-and-lua http://www.luafaq.org/gotchas.html ),但是我发现一些影响或者比较关注的特性没有在列表上。所以我写一个自己的列表。这篇文章不够广泛,Lua语言的某些方面也没有覆盖到(比如math和string库),但是它已经包含了我用Lua语言的要点。

    Good

    小:20000行源代码https://github.com/LuaDist/lua 在Linux下编译后就是182K左右的可执行解释器。

    可适性:任何有ANSI C编译器的平台都可以编译。可以看到在http://www.eluaproject.net/ 以及Lego Minstorms NXT上 http://hempeldesigngroup.com/lego/pblua/ ,mobile平台https://github.com/divineprog/mobilelua 游戏主机 http://blog.brokenfunction.com/2011/11/how-to-make-a-massively-cross-platform-game/ 到浏览器中(翻译到Javascript)http://notebook.kulchenko.com/programming/drawing-on-browser-canvas-with-lua

    容易嵌入和扩展:http://www.lua.org/pil/24.html 提供了简洁易用的接口与C/C++进行互通。

    快:http://shootout.alioth.debian.org/ 相比其他编程语言性能非常不错,还有一个JIT编译器 http://luajit.org/performance.html 对某些任务下的性能有显著提升;如果这还不能满足某些人,可以使用C语言实现性能瓶颈部分,与C的集成很容易,还可以继续从其它有用的部分收益。

    文档不错:语言手册 http://www.lua.org/manual/ ,书籍http://lua.org/pil/ 还有wiki http://lua-users.org/wiki/ 另外有http://www.capgo.com/Resources/SoftwareDev/LuaShortRef51.pdf

    友好热心的社区 http://lua-users.org/ ,通过文档,wiki还有邮件列表http://www.lua.org/lua-l.html 和SO http://stackoverflow.com/questions/tagged/lua ,任何问题都可以解决。

    干净和简单的参数适合初学者,对于非程序员也容易理解。Lua从Pascal的后继Modula http://en.wikipedia.org/wiki/Modula 借鉴了大部分控制语法,我仍然记得Philippe Kahn快速优雅的Turbo Pascal IDE http://en.wikipedia.org/wiki/Turbo_Pascal

    集成解释器:只要命令行运行lua就行了

    协程http://www.lua.org/pil/9.html 的内在支持,到实现iterators http://www.lua.org/pil/9.3.html 和非抢占性多线程 http://www.lua.org/pil/9.4.html

    增量垃圾收集器http://www.lua.org/manual/5.1/manual.html#2.10 有很低的延迟,没有额外的内存开销,很少的实现复杂度,支持弱表http://www.lua.org/pil/17.html

    强力的混杂式tables http://www.lua.org/pil/2.5.html 可以存储任意类型(除了nil),可以通过任何值索引(除了nil),比如 [1, 2, 5, foo = “bar”, [func] = “something”, [“some spaces”] = value()]

    词法定界(Lexical scoping)

    函数式编程http://www.lua.org/pil/6.html 通过一级(first class function)函数http://www.lua.org/pil/5.html 和闭包实现http://www.lua.org/pil/6.1.html

    尾调用http://www.lua.org/pil/6.3.html : return functioncall()

    递归函数不需要事先声明 local function foo() … foo() … end ,注意这样是不行的local foo = function() … foo() … end

    函数可以返回多值。调用者可以要求任意数量的返回值,如果比实际返回数量少,剩余的被抛弃,如果要求的多于实际返回的,用nil填充。

    函数允许可变函数参数个数 function foo(…) local args = {…}; bar(param, …) end

    Tables可以解开成一个参数列表,通过unpack(或者Lua5.2的table.unpack)实现 print(unpack({1, 2, 3})) prints 1 2 3

    可以操作环境变量(Lua5.1中的getfenv和setfenv,Lua5.2中的_ENV),这允许Lua建立沙箱机制 http://lua-users.org/wiki/SandBoxes

    变量列表赋值local a, b, c = 1, 2, x, y = y, x, or a, b = foo()

    使用[[…]] 做多行字符串,可以用[[…[=[…]=]…]]嵌套,注释如–[[…]]

    分号作为语句分隔符是可选的

    通过metatables重载 http://www.lua.org/manual/5.1/manual.html#2.8

    元编程http://metalua.luaforge.net/ 可以做到获取、修改一个抽象语法树来建立新的DSL

    for语句有两种方式,泛型式和数字式,数字型不光支持整数

    函数调用(function call)语法糖 f’string’, f”string” f[[string]]和 f{table},以及方法调用(method call) obj:m()

    简单但是很有用的调试库 http://www.lua.org/pil/23.html

     

    不同之处

    表和字符串索引从1开始,而不是0

    在table中给一个元素赋值nil,就把这个元素删除了。

    没有整型这个数据类型;number表现为浮点数

    没有类,面向对象机制通过表和函数实现;继承通过元表机制实现 http://www.lua.org/manual/5.1/manual.html#2.8

    方法调用通过object:method(args)实现,这和object.method(object, args)一样,but with object evaluated only once

    nil和false是唯二的假值,0,0.0,”0″和其他的都是真。

    ~=不等符号

    not, or, and关键字用做逻辑运算符

    赋值是语句http://www.lua.org/pil/4.1.html,这意味着不能a=b=1或者 if (a=1) then … end

    没有 a+=1 a++或者近似的方式

    没有continue语句,尽管有一个解释 http://www.luafaq.org/#T1.26 和一些变体,像是repeat break until true在循环内部打断,或者Lua5.2中的goto语句

    没有switch语句

    括号在某些情况下有必要,for example, a = {}; a.field works, but {}.field doesn’t; the latter needs to be specified as ({}).field.

    循环中控制变量默认本地化,loop外边就用不了了

    数值型for中的限制和步进值是被缓存的http://www.lua.org/pil/4.3.4.html  in for i = init(), limit(), step() do ... end all three functions initlimit, andstep are called once before the loop is executed.

    条件语句和其他控制结构不需要括号

    字符串和数字自动转换,但是在等于和不等于比较中不能自动转换。 0 == "0" is false{} ~= 1 is true . foo[“0”]和foo[0]在表中指向不同的值; other relational operators generate errors on comparing values of different types.

    逗号和分号可以用在table语法中;都可以放在最后的大括号前面作为可选操作符a = {a = 1, b = 2, }。

    一些组件额外提供;一些人认为这是“没有电池”。这是紧凑和可适内核的结果,也可以通过Luarocks和Penlight解决 http://luarocks.org/ http://stevedonovan.github.com/Penlight/

  • 萌萌的作文

    祖国真美丽

             祖国真美丽啊!看,高高的大山,清清的小河,无边无际的大草原,金黄的田野,一棵棵参天大树,广阔的海洋,茂密的大森林,瞧,花丛中,小蝴蝶在飞舞,小蜜蜂在嗡嗡嗡的唱着美丽的歌。秋天,果子成熟了,农民伯伯看着果实饱满的苹果树,露出了满意的笑容。冬天,下大雪了,大地就盖上了一层厚厚的棉被。好好的睡一觉。。。。。。一觉醒来,大地掀开厚厚的棉被,开始新的生活。农民伯伯开始辛勤劳作等着秋天的好收成。夏天,梨花开了,苹果花也开了,小朋友们快乐的看着美丽的花朵,心里别提有多高兴了。奔腾万里的黄河,源远流长的万里长城。啊,我们的祖国多么美丽!

    —————-

    这是萌萌打算参加神马作文比赛的文章,虽然有些词语堆砌,而且我们觉得不如她自己平时写的日记有感觉,她还是坚持要写这个题目。

  • 如何称量代码复杂度(C++/C#)

    微博上的蛙蛙王子提出三个设想,发送给微博上一些知名程序员,惊悚的是,这三个问题我以前也考虑过还动手做过。这是巧合呢?还是巧合涅?

    蛙蛙王子的问题是:是否有个工具可以检测出函数的长度?检测出函数中嵌套的层次?是否可以检测出重复代码?

    基于我在罗克韦尔时写的一个Lua脚本经验来看,第一第二个问题非常容易。第三个问题稍有麻烦,有工具或者开源项目能做到,但是效果一般。

    回到标题上的问题,称量代码复杂度,可以通过实现某个工具检测长度或者嵌套层次来完成,还有另外更简单的办法。

    通常情况下,复杂代码所在文件大小也会比其他文件大出不少,所以不用编写什么工具,只要逐个察看项目中个头比较大的文件,就可以找到代码味道不好的地方了。

    另外一个办法是通过版本控制工具,什么样的文件需要重构?基本上修改check in 次数多的文件,你要考虑重构了,即使代码味道不错,也肯定是责任过重,这个办法也很简单,把history导出统计一下就可以了。

    如果通过判断函数长度和嵌套层次,建议大家可以这样实现,我考虑过C++的实现,算是比较完整,不需要什么编译原理知识。

    函数长度和嵌套层次可以这样判断。前提1,我们可以确定C++中的{}成对出现;前提2,class可以通过关键字定位,而struct可以假定其中没有函数体,不需要判断;前提3,函数中的{}也一定是成对出现。至于其他的复杂问题,我觉得没必要考虑太多,除非你想做一个商用级别的软件,否则一个Python脚本就能搞定。

    基于这些前提我们可以这样实现,先清理注释部分,C++注释分成// /*,另外对于/*要考虑单行和多行,基本上就是按行处理就行了。之所以这样,是为了防止注释部分包含{}或者特定关键字。

    如果能找到class,判断类名,然后查找{。对于{}匹配,可以定义一个树形结构,函数或者类作为根,发现一个{,加入一层嵌套,发现一个},减去一层嵌套。如果嵌套层次为零(不在class定义体中),或者为一(在class定义体中,假定class的{}级别为0),那就是函数,稍微处理一下(),就能拿到参数,然后前面就是函数名字了。

    这样按照文件处理逐个处理完,就能判断出那些函数,函数体多长,嵌套层次如何了。

    针对C#,也可以这样处理,但是我猜测如果用Roslyn有更好的办法,可是没找到例子。

    ————-

    另外一个问题是重复代码。有一些链接,比如 http://en.wikipedia.org/wiki/Duplicate_code http://pmd.sourceforge.net/cpd.html http://checkstyle.sourceforge.net/config_duplicates.html http://patterninsight.com/products/clone-detection/ http://stackoverflow.com/questions/546487/tools-to-identify-code-duplications

    但是我感觉最好用的办法,是通过peer code review来检查,因为这一块对于算法而言,应该是实现难度挺大的,而且结果也不理想,review的方式基本上可以杜绝类似问题。我们之所以不用review方式解决代码长度和嵌套层次,是因为的确有办法实现。

     

  • MFC在VisualC++中依然活的好好的

    http://blogs.msdn.com/b/vcblog/archive/2012/03/05/10278210.aspx

    Pat在这篇文章中介绍了VS11里面的Visual C++部分对MFC的修改,包括bug fix, 静态链接文件大小。

    最值得一提的是MFC对Metro Style的支持。

    总有人不做研究便大放厥词:MFC老旧了,已经过时了,已经死了,不要学了。结果,拿出来比的QT不醒醒了,设计优秀的Borland葛屁了,只有MFC依然好好的活着,照现在的势头,这笔财富还能用上五年十年的依然没有问题。

    所以说,设计好不好,优雅不优雅,这都不是问题,只要能活的比较持久,那就是成功。我一直建议Windows平台的C++程序员学MFC,对于争议,哥是一笑而过啊,不争论用事实说话。

  • 如何成为靠谱的DotNet/C#程序员

    1 确定目标

    微软系开发涉及面太广,所以你得先确定自己在哪方面有所专长。除了基础知识扎实以外,在asp.net / siliverlight / WPF 必须有一定的侧重。这个侧重点选择可以是自身兴趣,但大多数是项目需要。

    2 选择教材

    我还是倾向推荐纸质书,这里简单列几本。

    C#本质论 http://www.amazon.cn/gp/product/B003ZXBKQC 这本书可以在一开始阅读,保证对C#基础有个全面掌握

    CLR via C# http://www.amazon.cn/CLR-via-C-%E7%91%9E%E5%A5%87%E7%89%B9/dp/B00426BTTY/ 这本书建议买,但是高级阅读

    深入理解C# 这本书如果看目录觉得感兴趣,可以买,但是不推荐初学者阅读。

    另外专门技术方面,可以根据销量和评价买一本,不推荐在开始学习阶段购买。建议可以先通过文档/视频/代码实例学习一阵以后,对技术有一定了解了,然后再选择购买。

    3 视频入门

    这里推荐微软中国的webcast http://msdnwebcast.net 全中文视频,精品不少,比如老赵就有很多贡献。建议看视频学代码。

    如果你英文很好,可以到channal9上看英文视频,也有成系列的。

    4 文档中心

    对于前面提到的几种技术,微软都有不同的网站专门介绍。

    http://www.asp.net/ asp.net和asp.net mvc的老家,下载,文档,视频学习。

    http://www.silverlight.net/ 银光的老家,下载,文档,视频学习。

    http://windowsclient.net/  wpf的老家,下载,文档,视频学习。

    另一个网站必须经常看的是 http://msdn.microsoft.com/en-us/default.aspx 比如这个 http://msdn.microsoft.com/en-us/vstudio/hh388566.aspx 就是Visual C#开发中心

    http://msdn.microsoft.com/en-us/library/ff361664%28VS.110%29.aspx 这里是DotNet开发链接页面,可以作为homepage

    www.codeplex.com 这是微软开源中心,推荐下载http://1code.codeplex.com/ all-in-one samples学习。

    http://www.codeproject.com/ 这里面的文档和代码实例大多数目的单纯,简单扼要,学习起来很方便。

    5 提高

    http://msdn.microsoft.com/en-US/practices Enterprise Library, prism4.1, MVVM, 这些模式被广泛使用

    MSDN要经常翻,里面好东西太多了。

    http://msdn.microsoft.com/en-us/magazine/default.aspx MSDN magazine也要经常看。

    就这些。