Hello World
Spiga

趣味编程:Functional Reactive Programming

2009-09-10 12:26 by 老赵, 15536 visits

最近我们搞了一些把事件当作对象方面的工作。基于事件的编程再常见不过了,尤其是在和UI相关的WinForm,WPF,Silverlight开发方面。把事件作为一等公民看待之后,我们可以实现一些较为“特别”的编程模型,例如Functional Reactive Programming。这是一种较为优雅的基于事件的处理方式,适合一些如交互式动画,自动控制方面的工作。即使平时不太常见,我想作为一个“尝试”或“练习”也是非常合适的。

我是通过F#而了解“事件即对象”以及FRP的相关内容的,而微软的Matthew Podwysocki最近一直在博客上撰写的一系列关于F#事件的文章也给了我很多信息。F#便直接体现了“事件即对象”的概念,它会把.NET类库中的事件转化成IEvent对象,然后便可以对其进行编程。IEvent对象是F#中表示“事件”的标准类型,它的最关键的成员是Add方法,如果使用C#来表示便是:

public interface IEvent<TEventArgs>
{
    void Add(Action<TEventArgs> callback);
}

当然,其实F#的事件并没有那么简单,不过我们目前只需要关注至此即可(更详细的信息您可以关注Matthew的文章Anders Cui同学的中文版)。Add方法是为这个事件添加一个回调函数,它自然会在事件触发时被调用。而传入的参数,您可看作是C#中事件的EventArgs对象(即第二个参数)。有了IEvent对象,在F#中便可以使用各种方式来响应一个事件。例如:

#light

open System
open System.Windows.Forms

let form = new Form(Visible = true, TopMost = true, Text =
form.MouseDown
    |> Event.map (fun args -> (args.X, args.Y))
    |> Event.filter (fun (x, y) -> x > 100 && y > 100)
    |> Event.listen (fun (x, y) -> printfn "(%d, %d)" x y)

Event.map方法会接受一个IEvent对象,以及一个用于转换事件参数的高阶函数,并返回一个新的事件对象。用户可以监听这个新事件。当原有事件触发时,它的事件参数将被高阶函数转化为新的对象,并以此出发新的事件。F#可以使用|>符号来改变参数传递的顺序,这样代码可以编写得更为流畅。例如下面两行F#代码其实是等价的:

Console.WriteLine "Hello World"
"Hello World" |> Console.WriteLine

Event.filter的作用是对事件进行过滤,只有在原事件触发时,其事件参数满足某个条件,才会触发新的事件对象。Event.listen则是简单的调用IEvent对象的Add方法,它只是一个辅助函数。

F#的Event模块还有其他一些方法,例如:

let form = new Form(Visible = true, TopMost = true, Text = "Event Sample")
form.MouseDown
    |> Event.choose (fun args ->
         if args.X > 100 && args.Y > 100 then Some(args.X, args.Y)
         else None)
    |> Event.listen (fun (x, y) -> printfn "(%d, %d)" x y)

Event.choose方法组合了Event.filter和Event.map,即在转化的同时可进行过滤。只有在高接函数的返回值为Some(args)而不是None的时候,才把args作为下一个事件的参数进行触发。还有:

let form = new Form(Visible = true, TopMost = true, Text = "Event Sample")
form.MouseDown
    |> Event.merge form.MouseMove
    |> Event.filter (fun args -> args.Button = MouseButtons.Left)
    |> Event.map (fun args -> (args.X, args.Y))
    |> Event.listen (fun (x, y) -> printfn "(%d, %d)" x y)

Event.merge方法的作用是合并两个(参数相同的)事件。当其中任意一个事件触发时,则会触发新的事件对象。此外:

let form = new Form(Visible = true, TopMost = true, Text = "Event Sample")
let (overEvent, underEvent) =
    form.MouseMove
      |> Event.merge form.MouseDown
      |> Event.filter (fun args -> args.Button = MouseButtons.Left)
      |> Event.map (fun args -> (args.X, args.Y))
      |> Event.partition (fun (x, y) -> x > 100 && y > 100)      
overEvent |> Event.listen (fun (x, y) -> printfn "Over (%d, %d)" x y)
underEvent |> Event.listen (fun (x, y) -> printfn "Under (%d, %d)" x y)

Event.partition方法的作用是把原有事件拆分为两个,并在原有事件被触发时,根据高阶函数的返回值来决定触发哪一个新事件。

以上这些都是Matthew在博客中已经介绍过的内容。不过我认为,Event模块下还有两个方法值得一提,那就是Event.pairwise和Event.scan。请看下面的代码:

let (trigger : (int -> unit), event) = Event.create()
event
    |> Event.pairwise
    |> Event.listen (fun (x, y) -> printfn "%d + %d = %d" x y (x + y))

[1..10] |> Seq.iter trigger // 使用1到10依次调用trigger

Event.create方法将创建一个事件对象,返回这个事件以及它的触发器。Event.pairwise会根据IEvent<T>对象返回一个IEvent<(T, T)>对象——(T, T)是一个元组,当然在C#中没有这个语言特性时,我们可以使用IEvent<T[]>来代替。当我们使用第一次trigger方法来触发event事件时,新的事件对象并不会触发。直到第二次及以后触发event事件时,才会把上一次的事件参数和目前的事件参数“合并”,并以此来触发新的事件。因此,上面的代码会输出以下内容:

1 + 2 = 3
2 + 3 = 5
3 + 4 = 7
4 + 5 = 9
5 + 6 = 11
6 + 7 = 13
7 + 8 = 15
8 + 9 = 17
9 + 10 = 19

而Event.scan方法则可以这样使用:

let (trigger : (int -> unit), event) = Event.create()
event
    |> Event.scan (fun acc i -> acc + i) 0
    |> Event.listen (printfn "%d")

[1..10] |> Seq.iter trigger

Event.scan方法会维护一个累加器(acc),在上面的代码中其初始值为0,每次event事件触发时,则会通过高阶函数,把事件参数计算到当前的累加器中得到新的值,并根据新的值触发新事件。因此上面的代码会输出一下内容(不包括注释):

1 // +1
3 // +2
6 // +3
10 // ...
15
21
28
36
45
55

自然,Event.pairwise和Event.scan方法得到的新对象都是有side effect的,需要考虑线程安全的问题。F#的类库不保证事件触发时的线程安全,于是事件在使用或触发时需要自行进行控制。

好,那么这次的“趣味编程”就产生了,您能否设计并实现一套类库,为C#语言提供这样一个类似的功能呢?您需要实现以下7种功能:

  • map
  • filter
  • choose
  • merge
  • partition
  • pairware
  • scan

有些朋友可能会想,为什么不直接使用C#来调用F#的类库呢?原因是“不合适”。F#的类库设计遵循了F#的语言特性,而且如前面所讲,F#本身会对.NET的事件进行一定转变。此外,为C#实现一个合适的API也是个很好的实践过程。例如,这又是一个适合扩展方法特性的场景。在我看来,最后的API应该是这样使用的:

someEvent
    .Map(args => new { args.X, args.Y })
    .Filter(args => args.X + args.Y > 100)
    .Scan(0, (acc, args) => acc + args.X, args.Y)
    .Add(args => Console.WriteLine(args));

您也来试试看?(答案

Creative Commons License

本文基于署名 2.5 中国大陆许可协议发布,欢迎转载,演绎或用于商业目的,但是必须保留本文的署名赵劼(包含链接),具体操作方式可参考此处。如您有任何疑问或者授权方面的协商,请给我留言

Add your comment

75 条回复

  1. 春晚[未注册用户]
    *.*.*.*
    链接

    春晚[未注册用户] 2009-09-10 12:35:00

    嘿嘿,你的文章写的再好,也没有人家老吉的软文那么收欢迎。

  2. vczh[未注册用户]
    *.*.*.*
    链接

    vczh[未注册用户] 2009-09-10 12:39:00

    用C#来做什么东西实在是容易啊,我一直以来致力于吧各种神奇的功能添加到C++里面,倒是遇到了很多绝大多数是由于释放内存造成的问题。event从F#到C#的改变是很小的,如果是从F#到C++……我觉得这个更有意思……你也可以试试……

  3. vczh[未注册用户]
    *.*.*.*
    链接

    vczh[未注册用户] 2009-09-10 12:41:00

    当然我说的不是托管C++

  4. 老赵
    admin
    链接

    老赵 2009-09-10 12:56:00

    @春晚
    我又不和他比,嘿嘿。

  5. 老赵
    admin
    链接

    老赵 2009-09-10 12:57:00

    @vczh
    “事件”其实是一种模型,用C++实现的目标是什么啊?

  6. Ivony...
    *.*.*.*
    链接

    Ivony... 2009-09-10 13:05:00

    春晚:嘿嘿,你的文章写的再好,也没有人家老吉的软文那么收欢迎。



    装配脑袋的不是更不受欢迎么,正常。。。。

  7. 老赵
    admin
    链接

    老赵 2009-09-10 13:11:00

    Ivony...:
    装配脑袋的不是更不受欢迎么,正常。。。。


    其实脑袋只要能够坚持一周三篇,绝对就可以受欢迎了……

  8. Ivony...
    *.*.*.*
    链接

    Ivony... 2009-09-10 13:11:00

    如果对LINQ和高阶函数比较熟,MS不是很难。。。。

  9. 老赵
    admin
    链接

    老赵 2009-09-10 13:14:00

    @Ivony...
    本来就不是很难嘛,否则我也就不会做了,嘿嘿。
    // 和LINQ无关吧。

  10. Ivony...
    *.*.*.*
    链接

    Ivony... 2009-09-10 13:14:00

    不过这个思想不错,得好好研究,有条件了装个2010研究F#。。。

  11. Ivony...
    *.*.*.*
    链接

    Ivony... 2009-09-10 13:20:00

    Jeffrey Zhao:
    @Ivony...
    本来就不是很难嘛,否则我也就不会做了,嘿嘿。
    // 和LINQ无关吧。



    有关系的,
    当然LINQ是面向集合,但实际上刨去集合,那么map类似于select,filter类似于where,至于pairwise和scan则很像迭代函数不是么?

    当然这些思想也并不是LINQ创造的,或者说应该是从函数式这边渗透到LINQ那边去的,因为LINQ也是依赖于lambda表达式么,但无论怎样,这两者互通性倒是很明显。

  12. 老赵
    admin
    链接

    老赵 2009-09-10 13:23:00

    @Ivony...
    你既然说“刨去集合”那么我也就姑且认为这和LINQ有那么一点点相似的地方吧……
    不过我还是建议不要想着LINQ啥啥,这里就是普通的编程,也就用到个扩展方法。
    LINQ不是和Reactive Programming没有关系,只是这里我实在觉得关系不大。

  13. egmkang
    *.*.*.*
    链接

    egmkang 2009-09-10 13:24:00

    OK..
    语言这方面的都说烦了,能不能来一点OOAD和架构方面的.
    刚看了你架构哪方面的,跟架构关心不是很大啊....

  14. 颜斌
    *.*.*.*
    链接

    颜斌 2009-09-10 13:25:00

    这里略显冷清了 老赵写文章的时候 多加点爆点 ╮(╯▽╰)╭

  15. Kevin Dai
    *.*.*.*
    链接

    Kevin Dai 2009-09-10 13:25:00

    @春晚
    在博客园,技术实力越雄厚,境界越高,就越容易被人吐口水,大家没发现这个规律啊?这就是为什么在博客园很少看到一篇文章的评论是极具价值的,老外的那些文章评论很长,几乎每个都值得看。
    反而那些初级入门的文章是最受欢迎的。

  16. 老赵
    admin
    链接

    老赵 2009-09-10 13:26:00

    @egmkang
    在你看来啥是架构方面的东西亚?

  17. 老赵
    admin
    链接

    老赵 2009-09-10 13:27:00

    @Kevin Dai
    错了,是和技术无关的话题是最受欢迎的。
    其实只要有脑袋和RednaxelaFX两个纯爷们在,评论还是挺好看的。

  18. Ivony...
    *.*.*.*
    链接

    Ivony... 2009-09-10 13:35:00

    @Jeffrey Zhao


    或许,最终实现的效果会更像,如果我没理解错的话,老赵期望的结果是这样的:

    var e1 = Event.Create<MyEventArgs>( obj1, "EventName" );
    var e2 = Event.Create<MyEventArgs>( obj1, "EventName" );

    e1
    .Merge( e2 )
    .Map( e => new { A = e.A, B = e.BAC } )
    .Filter( e => e.A > 100 )
    .Partition( e => e.B < 100 && e.B > 0
    , @event => @event.Listen( e => Console.WriteLine( "Under" )
    , @event => @event.Listen( e => Console.WriteLine( "Over" ) );

    嗯,修改一下Partition的实现,这样应该更好。

  19. 老赵的粉丝[未注册用户]
    *.*.*.*
    链接

    老赵的粉丝[未注册用户] 2009-09-10 13:36:00

    @春晚:

    俺就喜欢赵老师严谨的治学态度。受不受欢迎和受不受用是两码事。

  20. 老赵
    admin
    链接

    老赵 2009-09-10 13:37:00

    @Ivony...
    差不多阿,你这个IfTrue和IfFalae挺有创意的,我只想到返回一个IEvent<T>[],呵呵。

  21. egmkang
    *.*.*.*
    链接

    egmkang 2009-09-10 13:37:00

    @Jeffrey Zhao
    你的"架构设计"方面的文章是不是有一些太低层了??
    能不能跳出语言这个坑?......

  22. 老赵
    admin
    链接

    老赵 2009-09-10 13:39:00

    @egmkang
    谁让我喜欢语言啊,hoho。
    你觉得应该跌到哪个坑里面去会显得更“专业”一些?

  23. egmkang
    *.*.*.*
    链接

    egmkang 2009-09-10 13:40:00

    架构师可能不会关心你的类成员是不是Virtual....
    总之那篇文章放在架构里面我感觉很奇怪...

  24. Ivony...
    *.*.*.*
    链接

    Ivony... 2009-09-10 13:40:00

    Jeffrey Zhao:
    @Ivony...
    差不多阿,你这个IfTrue和IfFalae挺有创意的,我只想到返回一个IEvent<T>[],呵呵。



    这个应该不算是我的创意,是鹤冲天的。我这是抄他的Switch扩展方法的创意。
    或者用Then和Else更好?

  25. 老赵
    admin
    链接

    老赵 2009-09-10 13:41:00

    @egmkang
    你是不是喜欢看一些把模式谈得天花乱坠,然后给出一幅缤纷缭乱的设计图,上面堆满的类或者服务器,然后列举各种项目/名词,然后组合出来的东西呢?
    这我也会啊,不过等我有时间了再说吧,呵呵。

  26. egmkang
    *.*.*.*
    链接

    egmkang 2009-09-10 13:42:00

    语言嘛,我也喜欢,但是我不喜欢MS系列的语言......不知道为啥
    Python,Haskell都喜欢一些,只是太忙了,基本上没怎么学...

  27. egmkang
    *.*.*.*
    链接

    egmkang 2009-09-10 13:43:00

    @Jeffrey Zhao
    我不喜欢模式.

  28. 老赵
    admin
    链接

    老赵 2009-09-10 13:43:00

    @egmkang
    软件架构会分系统架构和程序架构,如果这种类型的文章放在《Beautiful Architecture》里谈,不知道你会不会认为这本书有问题呢?
    但这本书真的没问题,业界评价也很高。

  29. 老赵
    admin
    链接

    老赵 2009-09-10 13:45:00

    @egmkang
    我知道为啥,门户之见呗。我认为昨天在InfoQ上一个评论写得很好:“如果Anders是在Borland设计出C#的话,那么评价就会高很多了。”
    其实从技术上讲,微软的各个产品,如C#,F#,.NET,Windows都是一流的。

  30. 老赵
    admin
    链接

    老赵 2009-09-10 13:46:00

    @egmkang
    你果然还是喜欢看一堆堆的服务器,一堆堆的数据流向,一堆堆的项目名称……用很专业的方式放在一幅图上,呵呵。

  31. egmkang
    *.*.*.*
    链接

    egmkang 2009-09-10 13:48:00

    @Jeffrey Zhao
    我对一堆一堆的Server不感兴趣...汗...
    不过要是其中有一个可以让我抱回家玩,那就很好

  32. 老赵
    admin
    链接

    老赵 2009-09-10 13:48:00

    @egmkang
    不过不用急啊,最近我对语言上可写的东西比较多,写完之后自然会换个角度了,呵呵。

  33. egmkang
    *.*.*.*
    链接

    egmkang 2009-09-10 13:54:00

    @Jeffrey Zhao
    倒也不是.Borland的东西没用过,基本上没用过,如果说大学里面打开一两次TC 2就算用过的话,那就是用过了.
    Unix-Like下面就那么一点东西,也可以设计很好的软件;反观Windows这边呢,光语言方面的就出个不停,有意思么?
    跟在MS的屁股后面还真他妈的累,还不如学个C++,累一次就行了.
    还有就是.NET的开放性太低,MS心眼太小,出来一个MonoRail,被ASP.NET MVC搞死了,MS有意思么?

  34. egmkang
    *.*.*.*
    链接

    egmkang 2009-09-10 13:57:00

    @Jeffrey Zhao
    Beautiful Architecture,这个东西太高,我觉得要是Useful就OK了.
    买的DDD,Programming Windows都没看完...哎,要死人的.

  35. 老赵
    admin
    链接

    老赵 2009-09-10 13:59:00

    @egmkang
    MS出了很多语言吗?除了C#,VB,F#,你还知道哪些MS的语言呢?
    非MS的语言可多了:Ruby,Python,Haskell,Groovy,Scala,Closure,Scheme,Erlang……
    你要学Unix,先熟悉Bash吧,然后Python编程要会吧。哦,似乎Perl更Unix-like一些,嗯嗯……要扩展Emacs,再掌握一门Lisp吧。
    看上去也不少啊,是非MS的东西多还是MS的东西多?你为什么学非MS的东西就不觉得累?

    MS开放性低吗?我觉得很高,充分听取社区反馈。ASP.NET MVC也是MSPL的。
    想要看对比吗?看看最近Java委员会搞出的Project Coin就知道了,视社区呼声不顾,搞出来一个腌臜玩意儿。
    真的,别说我“门户之见”,你去看看都有哪些“改进”就知道了。

  36. 假正经哥哥
    *.*.*.*
    链接

    假正经哥哥 2009-09-10 14:02:00

    春晚:嘿嘿,你的文章写的再好,也没有人家老吉的软文那么收欢迎。


    呵呵,所谓的老吉就像个SA-SC之间的人,有什么好比的?

  37. egmkang
    *.*.*.*
    链接

    egmkang 2009-09-10 14:08:00

    @Jeffrey Zhao
    光C#就更新的这么快,MS可以保证自己的程序员都是一群打了兴奋剂的,不能保证其他的程序员也是.再说了,不用那些新的东西不活的好好的嘛.
    Unix-Like就基本上一直在用C99,也活得好好的.
    这里面有一些东西是需要思考的.

    还有,跟MS混的,有几个善终的?

  38. 老赵
    admin
    链接

    老赵 2009-09-10 14:12:00

    @egmkang
    C#更新实在是太有条理了,你带着偏见去学习,自然学习不好。
    你既然在Unix下可以坚持个C99,为什么在MS平台下就不行?

    Unix上选择很多,你可以坚持一个,然后偏怪MS更新快,让你选择不过来。
    这不是门户之见是什么?哎,我不想讨论下去了,说不动了。

  39. egmkang
    *.*.*.*
    链接

    egmkang 2009-09-10 14:18:00

    @Jeffrey Zhao
    我承认我是一个很无聊很无聊的男人...
    我是被骗了,才学的C#,一直工作在C# 2.0下面.
    大三的时候才学的ANSI C,感觉C#比C没多少进步...
    现在么,老板又不给用C......

    可能暂时一两年内,我不会用C# 3.x的那些东西.

  40. Ivony...
    *.*.*.*
    链接

    Ivony... 2009-09-10 14:20:00

    egmkang:
    @Jeffrey Zhao
    倒也不是.Borland的东西没用过,基本上没用过,如果说大学里面打开一两次TC 2就算用过的话,那就是用过了.
    Unix-Like下面就那么一点东西,也可以设计很好的软件;反观Windows这边呢,光语言方面的就出个不停,有意思么?
    跟在MS的屁股后面还真他妈的累,还不如学个C++,累一次就行了.
    还有就是.NET的开放性太低,MS心眼太小,出来一个MonoRail,被ASP.NET MVC搞死了,MS有意思么?



    话说,如果C++拆成几个语言独立发展,恐怕处境会比现在好很多。

  41. 老赵
    admin
    链接

    老赵 2009-09-10 14:20:00

    @egmkang
    看到我用LINQ、扩展方法或Lambda表达式用一行代码写出你需要10几行才能完成的工作的时候……你真一点不心动吗?

  42. egmkang
    *.*.*.*
    链接

    egmkang 2009-09-10 14:21:00

    @Ivony...
    C++搞得无比庞杂...
    C#我看有那趋势...

  43. Ivony...
    *.*.*.*
    链接

    Ivony... 2009-09-10 14:23:00

    egmkang:
    @Ivony...
    C++搞得无比庞杂...
    C#我看有那趋势...



    C++是属于三头六臂,C#是拉帮兄弟,C#的兄弟很多的,这样可以使得C#单纯些。

  44. 老赵
    admin
    链接

    老赵 2009-09-10 14:24:00

    Ivony...:
    C++是属于三头六臂,C#是拉帮兄弟,C#的兄弟很多的,这样可以使得C#单纯些。


    我同意这个。

  45. egmkang
    *.*.*.*
    链接

    egmkang 2009-09-10 14:25:00

    @Jeffrey Zhao
    我承认当我看到Linq to sql的时候,有很多的心动,至少以前写几十行代码,现在几行就搞定.
    但是心动归心动.MS搞得东西,拖来拖去就可以做东西,看着当然心动.可是实际用起来不是那么回事,被骗了很多次了,没意思了.
    我还是手写我的代码,等什么时候.NET 3.x遍布,MS把记事本用C#写了,我再去把我的程序用C# 3.x重写吧.

    静态语言跟动态语言比快,貌似比不了的吧?有一些公司,核心用C/C++,外壳用Python,我觉得可取.

  46. 老赵
    admin
    链接

    老赵 2009-09-10 14:35:00

    @egmkang
    不知道该说你是一朝被蛇咬十年怕井绳好,还是说你连孩子和洗澡水一起倒了呢?为什么就不能去其糟粕取其精华,非要搞二分法呢?
    C# 3.0的开发效率,我认为很高,不比Python低。这些东西体会过了可以知道(例如用来处理字符串),我认为你现在更像是FUD啊,呵呵。
    我是坚守静态语言的,我以前尝试过用ruby开发一些小工具,重构的时候吃尽了苦头,因为没有静态检查。
    所以就算搞FP,我也要是Haskell,F#等等,静态检查我认为是在太重要了,否则难以开发大型项目。
    我建议,还是尝试使用C# 3.0开发一段时间,看看“是不是那么一回事”,而不要总是停留在对新特性的抵触阶段。
    你现在还分不清Linq to SQL和LINQ就说C# 3.0不好,我认为实在不是一个专业开发人员应有的治学态度啊。

  47. 老赵
    admin
    链接

    老赵 2009-09-10 14:37:00

    @egmkang
    有篇文章推荐给你:http://haacked.com/archive/2009/08/31/7-stages-of-language-keyword-grief.aspx
    讲了人们对待语言新特性的7个阶段,很有意思,呵呵。

  48. winter-cn
    *.*.*.*
    链接

    winter-cn 2009-09-10 14:50:00

    egmkang:
    架构师可能不会关心你的类成员是不是Virtual....
    总之那篇文章放在架构里面我感觉很奇怪...


    架构师恰好要关心这个Virtual的问题

  49. amingo
    *.*.*.*
    链接

    amingo 2009-09-10 15:47:00

    怎么把文章发布到博客园首页????

  50. egmkang
    *.*.*.*
    链接

    egmkang 2009-09-10 18:15:00

    @Jeffrey Zhao
    我承认我有很大的抵触情绪,而且这种情绪一时半会儿不会被消除.
    我之前买过一本关于Linq的书,没看完.有一点原因,相比内容来说太贵了,还有就是我的环境中暂时不能用,因为我工作在.NET 2.0下.
    如果MS愿意把OS里一些小的玩意儿用C#写了,OK,我去说服我的BOSS,换.NET 3.x,4.0都行.
    否则,没门,或者BOSS给我说,咱们换.NET 3.x啦~~

  51. egmkang
    *.*.*.*
    链接

    egmkang 2009-09-10 18:20:00

    我之前也很追新的,对新的事务很感兴趣.
    我上大二(06年)的时候就学了C# 2.0,看MSDN学的.
    可是我现在发现,那些老的东西,对我来讲,意义更大一些,有时候有很多的指导意义,尤其是理论,这方面我比较匮乏.
    Knuth说过"新的代数语言每5年就走红和过时,而我想要强调的是永恒的概念."

  52. 老赵
    admin
    链接

    老赵 2009-09-10 18:37:00

    @egmkang
    其实我也不是为了新东西而新东西,比如我不懂Silverlight不懂WPF不懂这个不懂那个。
    但是我非常推崇.NET 3.5,C# 3.0,因为这切实带来了生产力的提高,可以省很多精力去解决其他问题。
    而且其实C# 3.0本身的改变也是有价值的,可以学到很多东西,不是乱来的,Anders不是菜鸟。
    比如Erik Meijer最近在搞得Reactive Framework,就是基于扎实的理论。
    微软有无数科学家,Haskell的老大也在微软研究院,他们都不是吃素的。
    微软研究院是世界上最好的研究院之一,怎么可能搞出的都是些乱七八糟的东西?
    他们每年都占各种顶级会议许多席位,你读研究生肯定关注这些,我没有乱说吧。

  53. egmkang
    *.*.*.*
    链接

    egmkang 2009-09-10 18:45:00

    @Jeffrey Zhao
    不好意思,我毕业了,现在给别人打工....
    研究生再说吧,等工作一两年看看什么地方最欠缺,而且最有价值弥补,再去学吧

  54. egmkang
    *.*.*.*
    链接

    egmkang 2009-09-10 18:48:00

    @Jeffrey Zhao
    不过估计是要去读MSE,其他的现在不是很喜欢.
    纯理论性的,因为咱的脑子沟比较少...

  55. 老赵
    admin
    链接

    老赵 2009-09-10 20:14:00

    @egmkang
    MSE的话,就是隆胸,意义不大,个人看法,呵呵。

  56. Colin Han
    *.*.*.*
    链接

    Colin Han 2009-09-10 20:31:00

    egmkang:
    @Jeffrey Zhao
    我承认我是一个很无聊很无聊的男人...
    我是被骗了,才学的C#,一直工作在C# 2.0下面.
    大三的时候才学的ANSI C,感觉C#比C没多少进步...
    现在么,老板又不给用C......

    可能暂时一两年内,我不会用C# 3.x的那些东西.


    呵呵,如果你真的花点时间用C++写写程序,就知道了,C#的改进不是一点点。我就敢说:“园子里没有几个人能够把C++的const关键字用顺畅的”。那些说C++比C#好的人也是绝对是没有把const用好的人。

  57. Colin Han
    *.*.*.*
    链接

    Colin Han 2009-09-10 20:32:00

    呵呵,我偷换概念了,C没有const的问题。

  58. Gnie
    *.*.*.*
    链接

    Gnie 2009-09-10 21:55:00

    正文没怎么看,光看你们的辩论了~

  59. 今天心情不好[未注册用户]
    *.*.*.*
    链接

    今天心情不好[未注册用户] 2009-09-10 22:17:00

    Colin Han:
    园子里没有几个人能够把C++的const关键字用顺畅的”。



    过分!叫嚣个什么呀!博客园是越来越没有看头了,你以后还让不让我看老赵的文章了!

  60. 老赵
    admin
    链接

    老赵 2009-09-10 22:21:00

    @Gnie
    辩论的确好看,呵呵。

  61. iceboundrock
    *.*.*.*
    链接

    iceboundrock 2009-09-11 00:39:00

    @Colin Han
    C的const也很绕,尤其是const指针。按我的理解,C++的const也就比C的多了一种场景,用于修饰member method的时候,说明这个方法不会改变对象的状态。其他的差不多。

  62. egmkang
    *.*.*.*
    链接

    egmkang 2009-09-11 08:46:00

    @iceboundrock
    刚才看了一下文档,貌似C语言里面的const也没什么奇特的,C++的没看.
    C99里面把const,restrict,volatile这三个关键字扔一块,这三个关键字都是修饰读取数据的.
    const主要用来修饰只读,后面两个跟优化有一点关系.
    C++,据我所知,无非就是多了一个const函数,不能改变类变量,给编译器看的.

  63. egmkang
    *.*.*.*
    链接

    egmkang 2009-09-11 08:47:00

    辩论可以让我多看看那枯燥的文档,也好.

  64. iceboundrock
    *.*.*.*
    链接

    iceboundrock 2009-09-11 09:17:00

    @egmkang
    是没啥奇特的,但是int const *a; int *const a;这俩咚咚的语义不同,你不觉得有点tricky么?还有const int * const a,反正我觉得挺绕的,虽然我现在能强迫自己去分辨。

  65. egmkang
    *.*.*.*
    链接

    egmkang 2009-09-11 09:31:00

    @iceboundrock
    K&R C里面讲的很清楚.
    int const *a,是说int只读,
    int * const a是说a只读.
    关键看const修饰谁了.

  66. egmkang
    *.*.*.*
    链接

    egmkang 2009-09-11 09:34:00

    @iceboundrock
    你要是这么写,就好看很多
    const int *a.

  67. egmkang
    *.*.*.*
    链接

    egmkang 2009-09-11 09:50:00

    @iceboundrock

    额,你应该还是没分清....
    刚看了一下你第一次回复的:
    是没啥奇特的,但是const int *a; int const *a;这俩咚咚的语义不同,你不觉得有点tricky么?反正我觉得挺绕的,虽然我现在能强迫自己去分辨。

    const int *a
    int const *a....

  68. iceboundrock
    *.*.*.*
    链接

    iceboundrock 2009-09-11 10:29:00

    @egmkang
    是啊,所以我还是觉得它挺绕的。第一次写完之后怎么看都不顺眼,翻文档看了一下改了。

  69. vczh[未注册用户]
    *.*.*.*
    链接

    vczh[未注册用户] 2009-09-11 10:52:00

    @Jeffrey Zhao
    “事件”其实是一种模型,用C++实现的目标是什么啊?
    ----------------------------
    制造出一个小类库,功能跟你的题目一样,让语法噪音尽可能少,而且不需要操心内存泄漏的问题。需要支持:普通函数、类成员函数、包含相应格式operator()重载的任何类(这是c++0x中lambda expression的结果)、指针、智能指针。当然还得有一个Unlisten,因为对象可能会被删掉,这是一个让删对象的人去除相应回调函数的机会。

  70. 装配脑袋
    *.*.*.*
    链接

    装配脑袋 2009-09-11 11:11:00

    const int*和int const*是一码事
    int* const 才是不同语义的
    另外C++的const比这个复杂多了,const变量能否访问const成员的问题,const成员能否访问const/mutable字段的问题,泛型的时候如何处理const和非const区别的问题,const参数的问题,要不要用const_cast<>的问题等……

  71. Colin Han
    *.*.*.*
    链接

    Colin Han 2009-09-17 12:41:00

    今天心情不好:

    Colin Han:
    园子里没有几个人能够把C++的const关键字用顺畅的”。



    过分!叫嚣个什么呀!博客园是越来越没有看头了,你以后还让不让我看老赵的文章了!


    呵呵,我是再说事实,踩到谁的尾巴了,不好意思。其实,我也被const搞得很郁闷。

    最重要的,我觉的一个自称很熟悉C++的开发人员却无法正确的使用const关键字,我觉的他就是在胡扯。至少是没有写过良好的类库。因为,这个东西使用的当确实可以让你的代码的语义更清晰,可维护性更好。而不正确的使用,往往带不来什么很直接的后果。

    呵呵,脑袋知道其中的复杂度。

  72. 老赵
    admin
    链接

    老赵 2009-09-17 13:07:00

    @Colin Han
    哎,那种扯蛋回复理它做甚……

  73. Colin Han
    *.*.*.*
    链接

    Colin Han 2009-09-18 22:22:00

    @Jeffrey Zhao
    呵呵,看来我是真的太闲了。儿子要回来了,以后想回也没时间了。

  74. 智者千虑
    *.*.*.*
    链接

    智者千虑 2009-09-25 18:13:00

    @egmkang
    我承认我有很大的抵触情绪,而且这种情绪一时半会儿不会被消除.
    我之前买过一本关于Linq的书,没看完.有一点原因,相比内容来说太贵了,还有就是我的环境中暂时不能用,因为我工作在.NET 2.0下.
    如果MS愿意把OS里一些小的玩意儿用C#写了,OK,我去说服我的BOSS,换.NET 3.x,4.0都行.
    否则,没门,或者BOSS给我说,咱们换.NET 3.x啦~~

    如果抛却具体的语言,其实是思维方式发生了变化。Linq绝不仅仅是“语法糖”这么简单。

  75. 老赵
    admin
    链接

    老赵 2009-09-25 18:55:00

    智者千虑:
    如果抛却具体的语言,其实是思维方式发生了变化。Linq绝不仅仅是“语法糖”这么简单。


    说的不错,最近又有一个很好的示例,那就是Erik Meijer在JVMLangSummit上的演讲,我真不知道还有什么理由可以轻视LINQ。
    http://wiki.jvmlangsummit.com/NET_Reactive_Framework
    当然,我是指客观理由,如RMS那种主观理由是永远接受不了LINQ的,我可以理解。

发表回复

登录 / 登录并记住我 ,登陆后便可删除或修改已发表的评论 (请注意保留评论内容)

昵称:(必填)

邮箱:(必填,仅用于Gavatar

主页:(可选)

评论内容(大于5个字符):

  1. Your Name yyyy-MM-dd HH:mm:ss

使用Live Messenger联系我