2007-01-07
D语言和python的差异
这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的位置好点。。
评论
qiezi
2007-01-16
前面在D里面使用栈上构造的函数有些问题,离开当前栈以后再调用可能会失效,这是比较头痛的,不知道是BUG还是Feature?
如果是Feature,我的callLater看来要重新设计了。。。
如果是Feature,我的callLater看来要重新设计了。。。
qiezi
2007-01-10
前段时间把twisted源文件转成D代码,发现代码量反而少了许多,当时想可能只是部分代码这样。只到转了很多以后发现,D代码真的会少很多,这样转下去违背了我当初转换源代码的本意了,所以想从头写一个。
经过了2天加起来3小时左右,实现了一个简单的版本,但却改了几次。起先是Reactor/Protocol,简单的架构,但扩展却不容易。然后改成Reactor/Acceptor/Protocol,融合ACE和twisted,不过少了点transport封装,timer已经可以工作了。后来还是觉得Acceptor不如twisted的Factory灵活,又改成Reactor/Factory/Protocol/Transport,还没有改完,基本上已经确定往twisted方向走了。
ACE虽然高效,但对于Protocol没有抽象出来,底层框架也比较简陋,要开发一个简单的程序也要写不少代码。另外ACE使用“通知”来处理一些事件,使用起来也并不是很方便,我曾经为了写一个“断线自动重连”的连接器,花了一整天时间,甚至要去阅读源码。而twisted使用起来则简单很多,我当初并不知道它已经实现了一个自动重连的Factory(也可能当时的确还没实现出来),但仅1个小时就写出一个来。当时的情况,ACE的代码我已经阅读过几次,而twisted的源码我很少去看。这本身虽然和语言有比较大的关系,但我觉得twisted的架构实现得更好一些。
另外这2天也看了一下epoll,我没有惊叹于它的设计精巧或是高效,而是奇怪为什么select没有这样的眼光?它的“创新”之处在于给描述符绑定了一个用户数据,仅仅一个指针,甚至不能说是创新,但却这么有用。另一点创新是由epoll来管理这些描述符,而不是用户,可以避免一些拷贝开销,虽然它内部也有可能做了类似的工作。
经过了2天加起来3小时左右,实现了一个简单的版本,但却改了几次。起先是Reactor/Protocol,简单的架构,但扩展却不容易。然后改成Reactor/Acceptor/Protocol,融合ACE和twisted,不过少了点transport封装,timer已经可以工作了。后来还是觉得Acceptor不如twisted的Factory灵活,又改成Reactor/Factory/Protocol/Transport,还没有改完,基本上已经确定往twisted方向走了。
ACE虽然高效,但对于Protocol没有抽象出来,底层框架也比较简陋,要开发一个简单的程序也要写不少代码。另外ACE使用“通知”来处理一些事件,使用起来也并不是很方便,我曾经为了写一个“断线自动重连”的连接器,花了一整天时间,甚至要去阅读源码。而twisted使用起来则简单很多,我当初并不知道它已经实现了一个自动重连的Factory(也可能当时的确还没实现出来),但仅1个小时就写出一个来。当时的情况,ACE的代码我已经阅读过几次,而twisted的源码我很少去看。这本身虽然和语言有比较大的关系,但我觉得twisted的架构实现得更好一些。
另外这2天也看了一下epoll,我没有惊叹于它的设计精巧或是高效,而是奇怪为什么select没有这样的眼光?它的“创新”之处在于给描述符绑定了一个用户数据,仅仅一个指针,甚至不能说是创新,但却这么有用。另一点创新是由epoll来管理这些描述符,而不是用户,可以避免一些拷贝开销,虽然它内部也有可能做了类似的工作。
qiezi
2007-01-10
引用
C#在处理这种问题时,把参数打包成object[],以Invoke为例,为了防止其它线程直接调用界面方法,一些操作需要用Invoke来把实际的调用切换到主线程,这和这里的callLater很相似,它把参数打包成object[]然后交给主线程。简单是疯了,我总觉得在静态语言里这种属于旁门左道,为什么不创建一个委托呢?
仔细想了一下,或许它这种做法也是有道理的。因为委托可以调用当时执行栈上的所有可见对像,使用时不注意可能引起跨线程调用,把参数打包在一定程度上对这些资源作了限制。如果不把参数打包,就要使用泛型接口,这可能是不友好的,但不是不可以使用的,有时间再看看。
qiezi
2007-01-10
ACE 网站:
http://www.cs.wustl.edu/~schmidt/ACE.html
除了网络接口外,它对于操作系统相关的API也作了些封装,方便做跨平台的软件。Photoshop里面好像是使用了ACE,当然是大材小用了。金山有一款软件也用了。但都是在客户端,它的长项是服务端。
http://www.cs.wustl.edu/~schmidt/ACE.html
除了网络接口外,它对于操作系统相关的API也作了些封装,方便做跨平台的软件。Photoshop里面好像是使用了ACE,当然是大材小用了。金山有一款软件也用了。但都是在客户端,它的长项是服务端。
qiezi
2007-01-10
ACE是一个C++的网络库,支持多种架构,比如reactor, proactor,支持多种接口,比如select, poll, epoll, IOCP等。代码有些老,主要是时间太长了,而且要支持多种平台和编译器。
cookoo
2007-01-10
ACE指啥啊?
qiezi
2007-01-07
D 1.0里面这个竟然失效了:
上面我标记的这一行,编译错误:
Error: cannot implicitly convert expression ((callable)()) of type void to void delegate()
它当成是执行了。
class Timer{
private void delegate() callable_;
public this(long time, lazy void callable){
callable_ = callable; // BREAK LINE
}
}
new Timer(getUTCtime() + 100, writefln("on timer"));
上面我标记的这一行,编译错误:
Error: cannot implicitly convert expression ((callable)()) of type void to void delegate()
它当成是执行了。
发表评论
- 浏览: 184473 次
- 性别:

- 来自: 上海

- 详细资料
搜索本博客
链接
最新评论
-
使用C#的Generator编写并 ...
不懂C#,老兄能不能给个c++的代码?谢谢先!
-- by vdgame -
Erlang/IoLanguage/Ruby
那热升级的问题怎么处理?
-- by zgd -
标准库的效率--适时选择自 ...
请教:C++中generator用什么实现?另外,libevent大概不支持文件 ...
-- by dayn9 -
云计算的架构
这个是一回事。google那个只支持python,就不看了。amazon的ec2 ...
-- by cookoo -
标准库的效率--适时选择自 ...
哦。我的意思是说使用池也只是少量提升性能而已,对于有些应用来说绝对不要使用这些库 ...
-- by qiezi






评论排行榜