原创作者: qiezi
阅读:1210次
评论:0条
更新时间:2011-05-26
这2个语言的比较怪怪的,我最近转换了一些twisted的源文件到D,发现有些东西直接抄过来还是不可行的。
一、参数
比如twisted的callLater:
实际调用大概是这样的:
执行时,它在3秒后调用func(arg1, arg2, arg3=5, arg4=6)。
把这种接口转到D语言,要面临2个问题:
1是参数打包,在D语言中需要用到变参函数,由于前面还传递了一个func参数,所以这个callLater可能被复杂化成一个模板方法。C#在处理这种问题时,把参数打包成object[],以Invoke为例,为了防止其它线程直接调用界面方法,一些操作需要用Invoke来把实际的调用切换到主线程,这和这里的callLater很相似,它把参数打包成object[]然后交给主线程。简单是疯了,我总觉得在静态语言里这种属于旁门左道,为什么不创建一个委托呢?
2是字典参数,这2个东西处理起来都比较烦燥。
所以我干脆把2个都抛弃,改成这样:
调用时只需要:
上面那个委托可以用lazy替代,所以改成这样:
调用:
看起来很简单,不过有误导性,代码不易读,如果D语言强制在调用时也加上lazy关键字可能会好点:
这个在邮件列表中已经有人提过了。
二、多返回值
这个在动态语言中应用比较普遍,D语言中也可以用tuple来解决,但总觉得不是静态语言最优雅的方式,所以还是把返回值写成一个确定的结构或类吧。
三、返回值类型
twisted很多地方返回值类型都不一样,可能返回一个Failure,也可能返回一个0或-1,还可能返回一个字符串,这在动态类型语言中是很普通的做法。不过我还是对这点很有意见,因为我发现它调用起来也很辛苦,调用一个方法,然后要判断一个返回值是否是个Failure,总之自己给自己找了很多麻烦。
D语言强制你只能返回一个类型,所以这是转换过程中比较费时间的,需要折衷考虑,有时需要把多种类型的返回值做成一个类,或者是使用out参数。
四、类的成员
twisted中经常使用getattr来判断一个成员是否定义过,以确定下一步的做法,这种方式没有可能也没有理由在D中继续生存下去。最可恨的是一个成员可能会有不同的类型,又要挨个判断。
所以我想转换源代码或许不是好办法,我又有点相信ACE了。。
-----------------------------------
为啥我写的东西总是虎头蛇尾呢?或许把第1调到第4的位置好点。。
一、参数
比如twisted的callLater:
class IReactorTime(Interface): """Time methods that a Reactor should implement. """ def callLater(self, delay, callable, *args, **kw): """Call a function later. @type delay: C{float} @param delay: the number of seconds to wait. @param callable: the callable object to call later. @param args: the arguments to call it with. @param kw: the keyword arguments to call it with. @returns: An L{IDelayedCall} object that can be used to cancel the scheduled call, by calling its C{cancel()} method. It also may be rescheduled by calling its C{delay()} or C{reset()} methods. """
实际调用大概是这样的:
reactor.callLater(3, func, arg1, arg2, arg3=5, arg4=6)
执行时,它在3秒后调用func(arg1, arg2, arg3=5, arg4=6)。
把这种接口转到D语言,要面临2个问题:
1是参数打包,在D语言中需要用到变参函数,由于前面还传递了一个func参数,所以这个callLater可能被复杂化成一个模板方法。C#在处理这种问题时,把参数打包成object[],以Invoke为例,为了防止其它线程直接调用界面方法,一些操作需要用Invoke来把实际的调用切换到主线程,这和这里的callLater很相似,它把参数打包成object[]然后交给主线程。简单是疯了,我总觉得在静态语言里这种属于旁门左道,为什么不创建一个委托呢?
2是字典参数,这2个东西处理起来都比较烦燥。
所以我干脆把2个都抛弃,改成这样:
interface IReactorTime{ IDelayedCall callLater(float delay, void delegate() callable); }
调用时只需要:
reactor.callLater(3, delegate void(){func(1,2);});
上面那个委托可以用lazy替代,所以改成这样:
interface IReactorTime{ IDelayedCall callLater(float delay, lazy void callable); }
调用:
reactor.callLater(3, func(1,2));
看起来很简单,不过有误导性,代码不易读,如果D语言强制在调用时也加上lazy关键字可能会好点:
reactor.callLater(3, lazy func(1,2));
这个在邮件列表中已经有人提过了。
二、多返回值
这个在动态语言中应用比较普遍,D语言中也可以用tuple来解决,但总觉得不是静态语言最优雅的方式,所以还是把返回值写成一个确定的结构或类吧。
三、返回值类型
twisted很多地方返回值类型都不一样,可能返回一个Failure,也可能返回一个0或-1,还可能返回一个字符串,这在动态类型语言中是很普通的做法。不过我还是对这点很有意见,因为我发现它调用起来也很辛苦,调用一个方法,然后要判断一个返回值是否是个Failure,总之自己给自己找了很多麻烦。
D语言强制你只能返回一个类型,所以这是转换过程中比较费时间的,需要折衷考虑,有时需要把多种类型的返回值做成一个类,或者是使用out参数。
四、类的成员
twisted中经常使用getattr来判断一个成员是否定义过,以确定下一步的做法,这种方式没有可能也没有理由在D中继续生存下去。最可恨的是一个成员可能会有不同的类型,又要挨个判断。
所以我想转换源代码或许不是好办法,我又有点相信ACE了。。
-----------------------------------
为啥我写的东西总是虎头蛇尾呢?或许把第1调到第4的位置好点。。
评论 共 0 条 请登录后发表评论