rcomponent吧 关注:17贴子:229
  • 4回复贴,共1
0


1楼2006-09-21 13:19回复
    python和ruby的相同点: 
    都强调语法简单,都具有更一般的表达方式。python是缩进,ruby是类basic的表达。都大量减少了符号。 
    都是动态数据类型。都是有丰富的数据结构。 
    都具有c语言扩展能力,都具有可移植性,比perl的可移植性更好。也都可以作为嵌入语言。 
    都是面向对象的语言,都可以作为大项目的开发工具。 
    都有丰富的库支持。 
    也有最宽松的版权许可,除了一些工具属于GNU世界。 
    都有lisp特色的eval函数,也都能把函数作为参数。 
    也有图形界面的ruby的专门编辑器。 
    都获得了广泛的c库的支持。如qt、gtk、tk、SDL、FOX等,ruby计划实现SWIG接口。 
    都有完善的文档。 
    和python相比ruby的优点: 

    具有正则表达式和嵌入html的功能。python也有正则表达式,但没有ruby的应用方便和广泛。python的嵌入html项目才刚起步。ruby还有apache的mod模块。ruby本身也实现和很多unix工具,如racc,doctools。比python更亲近linux。 
    比python功能更完整的面向对象的语法。 
    ruby的整个库都是具有类继承的结构。 
    他的基本的数据类型和运算符都是可以重载的。 
    ruby主要的功能都是通过对象的方法调用来实现的,而不是函数。python也在向这方面发展,但没有ruby做的彻底。 
    ruby的类是更规范的单继承,还有接口等概念的实现。 
    python可以实现在列表内的条件语句、循环语句,而ruby用“块”的方式来实现这个功能,比python的更灵活,更具有通用性。 
    ruby具有类似lisp的彻底的函数方式的条件语句、循环语句等。语句的表达能力更强。 
    附带一些unix工具,如racc等。 
    和python相比ruby的不足: 

    最大的不足正是因为ruby的强大所引起的。它没有python的简单性好。比较复杂的面向对象语法、“块”语法的引入、正则表达式的引入、一些简写标记都增加了语言的复杂性。 
    python的缩进表达方式比ruby的basic的表达方式更让人悦目,ruby程序的满眼的end让人不舒服。当然,ruby认为end的方式比python更先进。 
    ruby还没有python的“自省”的能力,没有从程序文件中生成文档的能力。 
    ruby没有国际化的支持。国际化支持在ruby的计划中。这是因为ruby的历史比python要短造成的。 
    ruby没有类似jython的东西。 
    python和ruby的语言的选择: 

    从简单的就是好的来说,选python是没错的。python适合寻找简单语言的人,这很可能造成python更流行,因此也有更多的支持。但如果要追求更强大的语法功能,则ruby是好的选择。因为ruby和python的哲学有很多相似的地方,先从python入手,尽量用python,如果python的能力不足了,可以在找ruby。 

    ruby和python的比较,就像五笔和拼音输入法的比较。拼音作为入门的输入法和长久使用的输入法都没有问题。五笔适合更高要求的情况。如果追求性能的不妨学学ruby。对编程语言感兴趣,想了解各种编程概念的学ruby也会很兴奋。


    2楼2006-09-21 13:19
    回复
      解释以上这些究竟在做什么显得有些罗嗦了。但是我希望传递的是,使用ruby这个语言时候的体会。尽管你不能自己亲自尝试,但是你可以通过屏幕看到这一系列的过程。现在我想展示另外一个例子。我希望你们可以所看到的内容中,得到一些体会。如果你之前还没有尝试过任何一种脚本语言,那么我鼓励你去学习ruby. 我认为ruby是非常值得学习的。因为它是很容易学习和使用的,只需要花几分钟去学习。脚本语言的另一个特点是,你可以写一些代码,然后直接去看它的运行结果。Ruby是一个非常优秀的脚本语言。但是,我想ruby的意义不仅在于它是一个好的脚本语言。接下来的几分钟,我将讨论这个问题。

      首先,我希望通过ruby的特性来讨论这个话题。这一点你可能已经从刚在的例子里面有所体会了。Ruby又很简洁的语法,这样你不需要写很多的代码,就能够获得很强大的功能。从刚才的例子里面就可以看到,在写参数的时候,你不需要写括号,当然,你也可以根本没有参数。这个特点可以使你快速的编写代码,但是更重要的是,你可以快速的阅读代码。我们可以对比java, c系列的语言,当你试图去阅读代码的时候,你的视线总是会被分散,并不容易弄明白代码究竟在做什么。松散的类型检查可以帮助我们更快,更好的理解代码。严格的类型检查可以导致更差的可读性。Ruby 在这之间做了很好的一个平衡。代码的可读性无论是对ruby而言,还是对使用ruby的开发人员来说,都有非常重要的价值。我认为用ruby写的代码是可读性很好的。这并不意味着ruby是一个很小的语言,就像smalltalk那样。Ruby是一门很复杂的语言。它具有很多复杂的语法特性,比如在同一行代码中实现多个任务这些小的语法点。如果你使用过其他的脚本语言的的话,(会发现)perl和python的特性都被带到了ruby中。这些给ruby的学习增加了难度。这又是一种新的平衡。在简单的语言里面表达事情是复杂的比如smalltalk, 然而,在ruby里,是很方便的,特别是在控制collection方面。在ruby里,List的语法是很方便的。我并没有展示hashtable在ruby中的使用,但是它们的用法一样是简单的。

      有一点很受到关注,不像java,c#这些主流的静态类型的语言,你不需要在ruby中定义变量类型。它是具有严格的类型的。记得我们在刚才的实验里面举的例子,字符串类型进行减运算,是会被提示错误的。但是你只有在运行的时候才会被告知有错误存在,而不是在编译的时候。所以ruby有严格的类型。但是它的类型是动态的。所以你只有在运行时才能发现错误。这就造成了下面这一个结果,很多人担心在编写ruby的代码的时候是很难发现类型错误的,这不像我们通常在java和c#里面期待的那样。但是,我发现在大多数使用ruby的开发人中并不存在这样的问题,他们通过测试解决这个问题,尤其是单元测试。我本人是测试的拥护者,我会非常多的使用到测试,不是在当前这个小的演示程序里面,而是在以前的稍微大一些的项目里。如果你使用单元测试,你发现那些类型错误的速度将会像在编译中发现错误一样快捷。我非常喜欢这种特性,尤其是在一开始使用smalltalk建立大型系统的时候。只有在很少的情况下,测试是不能发现类型错误的。但是在这样的语言里面有一个缺点,在阅读代码的时候,你不容易理解程序究竟完成了什么,因为在操控这个变量的时候你不能知道他究竟是哪一种类型的。这意味着,ruby还不能像smalltalk那样有一些强大的调试工具,这样可以在调试环境里面步进的运行程序,看到变量的类型。总体来说,我喜欢动态语言带来的这种灵活性。对象可以被替代,在很多地方都可以作为各种类型被使用。但是在另一方面,它又提高了代码的可读性。当你试图去阅读代码的时候,它是比较容易被理解。这就需要看个人的喜好了,有的人喜欢使用静态的语言,有的人喜欢使用动态的语言。所以,你需要挑选一种更喜欢的语言。很多人认为种类是很重要的,我认为这并不是决定性的。
      


      3楼2006-09-21 13:20
      回复
        Make 是一种特殊的文件格式,用来描述怎样构建代码,它是一种特殊的domain语言,可以用来构建应用程序。它有它自己的格式和语法,描述怎么样构建C语言程序。Make存在一个问题,这就是它学习起来并不容易。你也很难去理解那些自动生成的makefile。但是很多程序都有自动生成make文件的能力,因为如果是你自己去写的话,是不容易掌握的。Java一开始是没有构建工具的。所以James Duncan Davidson写了ant用于java的构建。Ant的作者不想让构建涉及到语法的问题,他们使用xml作为构建的脚本。我并不是在抱怨这个问题,在那个时候xml是不错的选择。使用xml语法会有两个问题。因为语法是十分严格的,你需要花很多精力用于关注语法,所以读懂它执行的操作就变得困难了。另外的一个问题是,当系统越来越大的时候,build文件会包含很多逻辑,就给建立ant文件造成了困难。所以当系统变得很大,建立一个ant的文件来构建系统就会十分困难了。我们需要找到一种方式,从xml中释放出来,用来构建这些类。

        Ruby 就是这样一个强大的语言,在有一定语法限制的情况下,去验证ruby的语法。Ruby并没有引入太多新的语法。这看起来还不错,因为你需要一门新的语言,来实现这个功能。但是你还是有一个局限,就是你不能在ruby以外使用它。但是另一个好处在于,当你需要做非常复杂的事情的时候,你可以使用ruby. 所以,你有更强大的能力来完成这件事情。这个外部的语言让你可以使用它的语法,使你逐渐变得更有能力应对。因为在越来越复杂的时候,它可以帮助你编译。这种能力是很容易获得的。它的语法是很直接的,你可以容易的学习。把这样的语言作为宿主(host)语言是一个很传统的想法了。但是这是很有用处的。

        有的时候,使ruby能够吸引使用者并不是一件容易的事情。我成为ruby的爱好者已经有几年了。我致力于把它推广用于我们的工作中。我告诉别人我喜欢ruby,并且鼓励别人去使用它。但是在一个产品中使用或者不用并不是非常重要的。我并不推荐所有的工程都使用。但是在最近半年的许多项目里面,我们都使用了ruby. 我们发现,在一些工程里面ruby可能并不适合,但是在另一些工程里面使用ruby是非常适合的。这个核心在于,那些成功的案例证明,那样项目,才是ruby真正适合的。尽管Rails提供了一个大的框架,但是如果不用ruby的话,几乎不可能成功。这也是项目成功的原因之一。

        我的同事正在做的一个项目是需要大量操作数据库的。把数据从数据库中取出来,在内存中进行计算,再把数据放回数据库是没有必要的。你希望用spl进行这些操作。而使用sql是有一定限制的。它很强大,但是不容易使用。Sql的一个最主要的问题在于,它完全基于domain. 它可以对表格式的数据进行很好的操作,但是没有把表抽象出来的能力。所以如果你想要对表进行操作,这个是非常好的。但是如果你想进行其他操作,就非常麻烦了。典型的例子是:具有层级结构的数据库是比较复杂的,用sql来操作它也变得复杂和困难。在这个项目里面,使用了ruby语言,允许输入domain specific language的ruby, 可以生成sql代码对数据库进行操作。这样的特殊的语言是非常好用的。领域的专家可以脱离出来,去阅读和理解这些代码,不用去考虑语法和究竟如何产生这些。可以把精力放在其他的地方。ruby这样的domain specific language的特点使它非常具有吸引力。

        Ruby社区令人激动

        现在来看几张照片来总结这个演讲。Ruby是一个有趣的系统。我不能说它适合用于任何地方,但是它的确适合用在很多地方。DSL是它的核心。一些特定类型的网站,特别是那些需要用到数据库的,还有使用RAILS框架的。几乎所有的administrating work 和 scripting work都适合使用ruby. 你可以开始使用ruby,因为他是一个非常强大的工具。Ruby是我见过的最好的脚本语言,你也会有同样的体会。在构建方面,Rake(注:ruby的构建工具)是非常好的构建工具。大约在六个月以前,我把我的网站全部换成使用它进行构建和维护这些构建的文件。我想你一定不会后悔的,因为构建和维护这些构建文件都是非常容易的。

        在我完成这次演讲之前,我还有最后一件事情。当我谈论软件开发的时候,我一直在强调,无论你使用什么样的工具,什么样的实践,比如结对编程,测试驱动,关于软件开发项目成功与否的最重要的因素是工作在项目中的人以及这些人如何一起工作。在敏捷软件宣言中,首要的价值观就是个体与互交比过程和工具更重要,更有价值。Ruby值得关注的原因不在于它的特性也不是它的框架,也不是它带来的在RAILS中的生产率的提高,而是ruby社区成员的工作。Dave Thomas (注:<< pragmatic programmers >>一书的作者)多次提到了这一点,这是正式它吸引我的地方。我在最近的二三年内一直很感兴趣。Ruby社区吸引着越来越多高手的加入,从而使它本身不断进步。另一个优点在于,Ruby的开源作品都可以通过网络直接安装, 如果你想要使用,那么可以非常容易的通过RubyGem安装——这是一个package management system. (注:就好像debain的Unix package management system) 。Ruby的社群正在飞速成长,因为不断有优秀的成员加入到这个团队,在这个环境中工作,这使得这个团队非常值得关注。这也是我一直关注ruby的最主要的原因,因为很多值得关注的人都在这个社区里面工作。

        这就是我关于ruby的第一次演讲。我希望它不是一个语无伦次的演说。


        5楼2006-09-21 13:20
        回复
          这是一个研究笔记,主要是为了向同好请教。除了这个开头以外,没有多余的废话,也就免了其他的客套。请大家不要抱怨可读性不好。

          1. 在一个名字或者字符串前面加上冒号,得到一个symbol对象。还可以通过String#to_sym、Fixnum#to_sym和String#intern得到。

          2. 一般用symbol做hash的key,号称是为了节省内存,提高执行效率。

          3. 为什么可以节省内存?Ruby中的String是可变对象,这一点跟Java、C#、Python都不一样。注意跟某些C++标准库中的COW的basic_string<T>也不一样。Ruby中每一个String都可以就地改变。可能是因为这个原因,Ruby中两个内容相同的字符串文本量实际上是两个不同的对象。

           a = "hello"
           b = "hello"

           虽然俩字符串内容都一样,但是你比一下a和b,就知道a.object_id != b.object_id,它们指向的不是同一个对象。结果反而很像未经string pooling优化的C语言的行为。到底immutable好还是mutable好,或者还是貌似聪明的COW好,见仁见智了。不过Ruby的设计在把字符串用作hash key的时候毛病就大了。比如你写:

           h["ruby"].name = "Ruby"
           h["ruby"].author = "matz"
           h["ruby"].birth_year = 1995

          的时候,"ruby"这个字符串动态生成了三次,占用三倍内存。这就严重地浪费了内存。而用:ruby做为key,因为在整个运行过程中,Ruby runtime保证名为:ruby的symbol对象只有一个,所以就不用生成三个,节省内存。

          4. 为什么可以提高执行效率?显然的原因是免得多次动态生成'ruby'字符串了。还不单如此,Hash的key值应该是常量,所以Ruby的Hash对于作为key的String对象都要施加保护,所谓保护,也就是把String冻结了,免得你之后还改变其值。保护当然是有代价的,symbol无需保护,当然是能提高效率的。附带说明,其他mutable的对象也可以作为hash的key,这是Ruby设计得比较奇怪的地方。在irb里运行以下代码,你会发现Ruby的Hash丢值。

           h = Hash.new
           L = [1, 2]
           h[L] = "A big object!"
           L << 3 # 居然能改! 
           h[L] # ==> nil,找不到了,似乎正常
           # 可是
           h[[1, 2]] # ==> nil,居然还是找不到
           # 看看keys
           h.keys # ==> {[1, 2, 3]} 似乎还在里面
           h[[1, 2, 3]] # ==> nil
           # 可是
           h # ==> {[1, 2, 3]=>'A big object'},明明在这里,就是找不到

           h.rehash # ==> 这样就会一切恢复正常。
           
           这一点上Python的设计要比较容易理解,list根本就是unhashable的,不能用来做hash的key。

           回过头来在说提高效率的事。Symbol效率提高还有第三个原因,那是因为symbol本质上不比一个整数多出多少东西,用Symbol#to_i可以得到一个在整个程序中唯一的整数。Hash完全可以利用这个整数来产生hash值,那岂不是比根据字符串内容去算hash值快得多?这还是小意思,既然这个整数是唯一的,那么产生一个唯一的hash值也就是小菜一碟,要是能保证hash值唯一,那还是什么hash表,根本就变成数组了。Hash表还可能会冲突,数组根本不会冲突,百分之百保证O(1),当然快。我没看Ruby源码,不知道是不是这么处理的。

          5. 为什么Ruby runtime可以保证每一个symbol唯一?因为Ruby把symbol存放在运行时维护的一个符号表里了,而这个符号表实际上是一个atom数据结构,其中存储着当前所有的程序级的name,确保不出现内容相同的多个对象。几乎每一个语言和系统都会有这样一个符号表,只不过象C/C++那样的语言,这个符号表只是在编译时存在,运行时就没了。而Python、Ruby则在运行时也保留这张表备用。有这样一个现成的数据结构干嘛不用?

          6. 但是这个表中存放的并不光是我们自己主动生成的symbols,还有Ruby解释器对当前程序进行词法分析、语法分析后存在其中的、当前程序的所有名字。这可是Ruby引擎用的东西啊,我们只要加上一个冒号,就让自己的对象跟Ruby引擎内部使用的对象成邻居了。所以String#intern这个方法叫做intern(内部化)。

           .NET Framework中String类也有一个Intern方法,意思是一样一样一样的,在李建忠的经典译本里翻译为“驻留”。

          7. 可以用Symbol#all_symbols查看当前定义的全部symbol。可以体验一下自己往符号表中塞一个对象的感觉,想想你写的程序跟Ruby引擎能干一样的事情,应该还是挺爽的。

          8. Python中用不着这个,因为字符串是immutable的。放下有用没用不说,有没有办法在Python中intern呢?我还没找到办法。有没有Python牛知道?

           补充一下:查到了,Python中做这个事情的函数叫做 intern()。


          9. 我觉得Ruby的这个设计是从Perl的glob中简化而来的。Perl中可以用*a得到对应于符号a的glob,那是一个八爪鱼一样的怪物。Ruby也可以很容易的得到symbol table中的对象,不过没有把symbol设计成八爪鱼。

          10. 还有一些小问题没搞清楚,比如:name跟@name是什么关系。attr_reader :name,实际上是给attr_reader方法传了一个symbol作为参数,前者要通过这个symbol找到@name变量,是不是'@' + :name.id2name这么简单?大概可以去看看source了。


          6楼2006-09-21 13:28
          回复