« 为什么说不要编写庞大的程序 | 返回首页 | 树型打印一个 table »

在 lua 中实现函数的重载

警告:记录以下内容纯粹自娱,请勿轻易用于项目。我个人也不赞同随意使用语法糖去改造语言。

我们知道 C++ 里有函数重载的特性,程序员可以为一个看起来同名的函数做多份实现,让编译器通过调用时的参数类型去指定链接器链接最为匹配的一份实现。对于死忠的 C++ 程序员,这绝对是最必不可少的利器。如果没有它,那些 template 绝对玩不出现在这么多花来,当然也就没那么多机会拿着“充满智慧” 花哨的 template 代码来 YY 自己的智商了。

哦,写 lua 的所谓脚本程序员不要沮丧,其实 lua 中可玩的花样也很多。一样可以写出让同行瞠目结舌的代码来。比如这个函数重载的问题,虽然 lua 不可能做所谓编译期运算(动态生成代码或许勉强算一个),也没有什么静态链接过程。

但 lua 是个有趣的语言,下面看我怎么模拟出一个类似的东西来。

我们的目标大约是这样的:

    define.test {
        "number",
        function(n)
            print("number",n)
        end
    }

    define.test {
        "string",
        "number",
        function(s,n)
            print("string number",s,n)
        end
    }

    define.test {
        "number",
        "...",
        function(n,...)
            print("number ...",n,...)
        end
    }

    define.test {
        "...",
        function(...)
            print("default",...)
        end
    }

然后调用 test 的时候,可以通过调用参数,分发到不同的函数实现上去。当然,需要找到最接近的匹配。


test(1)
test("hello",2)
test("hello","world")
test(1,"hello")

将输出

number  1
string number   hello   2
default hello   world
number ...      1       hello

这件事情其实很容易做,只需要额外为每个需要用多态函数的环境记录一张表。里面放上同名函数的分发器。而分发器按事先注册的参数表去检查匹配参数,找到最合适的对应函数定义。

如果得不到任何匹配就抛出异常,这样也可以在需要强类型检查时增强一些安全性。

不过这些事情当然会有性能上的开销,也就是代价吧。既然是玩具代码,我也没太优化,纯粹是过节自娱。

大家节日快乐。

附上代码: LuaFunctionOverload

ps. 如果在定义函数的地方,定义参数默认值也很容易,这里就不给出代码了。

Comments

这个 mm 不错!

我给云风提个意见啊,不要总说"于是我花了多少多少时间写了一个什么什么",因为你花这么少时间写的,容易让水平低下的人,比如我,很自卑

重载和template说不上“花哨”的吧。
说实话,我以前也对C++不感冒,觉得它仅仅是由编译器“聪明”的完成了一部分人的工作而已。从机器友好性的角度看,C++远远不如C。所以我作为“死忠”的C程序员,在C++的开发环境中坚持开发“C”的代码(当然还算不上符合ANSI C的标准)。
近一年,我的观点有所改变。其实C也好,C++也好,都只是一个载体而已,关键因素还在于人。设计良好的前提下,C++的代码实现就会比C丑陋?未必吧,相反,C++会具有更好的可读性和更少的代码量。
总之,语言无优劣,只看个人掌握情况和习惯。这就像筷子与刀叉,拿着刀叉吃花生米说刀叉不实用,捎双筷子吃牛排说筷子还不如两双半好用,就显得太较真儿了。

BTW:就事论事,没有别的意思,从云风这里学了不少东西,在此一并表示感谢

To lv:
如此死忠的人,我觉得应该都是学生之流的(虽然我也是)。
学校的讲授,都是讲怎样写好“小程序”,做好“小工程”,《软件工程导论》形同虚设,学不到东西。而工作时,如果稍好些的公司,做的都是大项目。怎么把做小项目的体验带到大项目里而不出问题呢?如果能在小项目里玩弄聪明才智的人在大项目里还是不注意复杂度的管理,优化期的延后,版本控制之类的,那么他无疑是团队和项目的破坏者。
听着《计算机组成原理》老师和intel给的手册给我讲着从底层的优化技术,很精彩,但是自己做的本来不大的项目,也不敢在东西能运行+模块和功能完整之前用。
所以,lv君可以拓宽一下视野。

如果没有协调好,最基本的信息隐藏对团队也是个灾难。所以,归根结底还是能力的问题,别什么都赖在语言上

模板因为它编译时的输出信息比较独特,我也觉得应该隐藏在接口内比较好

写代码还是清晰易懂比较好

To lv:
用高级特性自己YY还可以,但对团队来说应该是一种灾难

To sjinny:
重载我觉得只是“看起来”是接口一致的

首先说明下,我是比较敬重云风的,下面完全是技术上的探讨。

看了你不少的文章,发现不时地要把C++讽刺一下。很不幸我就是一个死忠的C++程序员,有些话不吐不快。

C++ 有如屠龙刀,强大而难以掌握。功力深厚者,自然可以挥撒自如,削铁如泥;功力不够的反而要误伤自己。看过你的Windsoul++, 从代码层面看,觉得并不怎么样。密密麻麻的i,j,x,y,x2,y2,抽象得并不太好。面向对象都做得不够好,更别说模板元编程了。当然这个是很多年前的了,那时我都还不知道什么叫编程。现在怎么样了就不是太了解了,但是评价之前还是有一定的基础比较恰当些。

编程是需要乐趣的。而乐趣又是源于挑战和进取。搞些花哨的 template, 一来可以让自己的代码,至少是使用这些库的代码,更简洁优雅,拥有更好的抽象,也更具可读性;二来还可以 YY 一下,何乐而不为呢。对我来说,写些重复的、不需要经过大脑的、可以"年产二十万行"的代码实在是一种煎熬。

节日快乐~~

其实重载特别是操作符重载还是挺重要的,因为它可以给各种数据类型提供一致的接口,而对重载的不恰当使用又是另一回事了。

mm真的是mm啊?好像经常看到她在这里表达对云轰的爱慕之情。

大哥,一年前我看《编程感悟》,懂一点点,一年后的我居然没有任何阅读与思维上的困难,甚至觉得写得过于蜻蜓点水,就像YY,不能开战一样,请问我的水平算入门了没有??

"花哨的 template 代码来 YY 自己的智商了"——搞出个“YY”看出大哥绝对不是枯燥的,木讷的死板的程序员。而是一个及时关注生活充满生活情趣的大男孩!!开句玩笑:其实大哥被无数mm YY!!

节日快乐!一直以来关注你的博客,我是一个大二学生,专业软件工程,大一的时候曾在图书馆借阅过你的《编程感悟》,当时就被非常亲切的叙述风格所吸引,完全一反普通技术书的死板,一个礼拜读完,只是当时知识水平有限,书上大多一知半解,现在快升大三了,又重新翻阅,感触颇多啊!总之,继续关注,继续支持!!!
^_^

节日快乐!我很荣幸能第一个在这篇博留言。如果我是学计算机该有多好,一定时刻关注,可惜我不是。期待你的博有机会加入其它元素,相信那将会是很精彩的一页。但愿这天早点到来。。。

Post a comment

非这个主题相关的留言请到:留言本