Ruby 2.0 有哪些新特性?

本月24日(也就是明天)Ruby 2.0终于就要发布了。

Ruby核心团队的卜部昌平桑昨天在一个内部学习会上的presentation,介绍了Ruby 2.0所包含的一些新特性。

(本文内容选译自该幻灯片:https://speakerdeck.com/shyouhei/whats-new-in-ruby-2-dot-0 )

 


为什么有Ruby 2.0?

  • 因为我们在改变事物。
  • 我们渴望让自己变得越来越快乐、健康、以及高产。
  • 不必畏惧。“拥抱变化。”

Ruby 2.0有什么新鲜的?

什么不是Ruby 2中的新鲜货

  • 几乎所有的东西。
  • “100%后向兼容”,matz如是说。
    • 在现实中……
  • (举个例子来说)Rails仍然能完好运行如初。

也就是说,

  • 新的东西被加进来了。
  • 许多内部的东西得到了改进。

Ruby 2.0的新句法

关键字参数(Keyword arguments)

下面的代码在1.x中能够正常工作:

1
2
3
obj.method "with" , :lots => "of" ,
                    :args => "in" ,
                    :hash => "form"

但是,问题出在哪呢?

问题是在定义该方法的时候: (Mort注:在Ruby 1.x中,只能将多个带符号名称的参数作为一个Hash来传递给方法。要为参数指定默认值,实现起来就很累赘,参见如下代码)

1
2
3
4
5
6
def obj.method(arg, hash)
   lots = Hash [ :lots ] || "default"
   args = Hash [ :args ] || "another"
   hand = Hash [ :by hand] || "annoying"
   ...
end

注意到代码中错误的Hash[:by hand]——手写代码是错误产生的根源!

从2.0开始,Ruby将引入关键字参数

1
def obj.method(a, b = 1 , c: 1 , d: 2 )

其中a为固定参数,b为可选参数,cd则为关键字参数。这样,局部变量abcd都将被恰当地赋值。

在调用函数时,原有的调用方式无需更改。

Mort注:虽然幻灯片里没有写,传统的基于Hash参数的调用方法是这个样子的

1
obj.method( "foo" , :c => 2 , :d => 3 )

现在Ruby 2.0同时也支持直接采用关键字参数的调用方法:(Python程序员一定会觉得这种语法更亲切)

1
obj.method( "foo" , c: 2 , d: 3 )

更详细的示例,可以参考这里:

http://brainspec.com/blog/2012/10/08/keyword-arguments-ruby-2-0/

其他细微的句法改进

  • 引入了符号数组字面值%i%I
<code>%i(foo bar baz) # =&gt; [:foo, :bar, :baz] </code>
  • Ruby现在默认把所有的输入都视作UTF-8编码。当然你也可以显式地指定需要的编码。

Ruby 2.0的核心性能改进

require的改进

  • 背景:今天,由于我们有了许多gems,启动Ruby有时甚至需要一次require 128+个库——这带来了糟糕的性能问题。
  • 解决:require变得更快了(从计算复杂度的意义上来说)。
    • 若干技术被应用于减少多余的计算上。

Backtrace惰性生成

  • 起初,backtraces只是字符串数组而已。
  • 每当抛出异常时,这些字符串就被自上而下地生成出来,即使在它们没有实际用途的情况下。
    • 这导致了超乎寻常的低效,尤其是当你有1024+个stack frames时(这在Rails应用中很常见)。
  • 从Ruby 2.x开始,Thread::Backtrace被用来取代字符串。
    • 它们非常地轻量级。
  • 当你需要查看backtrace时,只需将它们转换成字符串即可(调用#to_s)。

Flonum类

  • 在64位平台(如今早就烂大街了)上,指针,整型和浮点型数均是64位宽度的。
  • 在Ruby中,指针和整型均为C级别的register寄存器变量。而double却是存储在内存中的,如果我们能够如操作指针一样操作它们,将如何呢?
  • 问题:如何让一个指针和一个double共存于一个union中?
  • 解决:一些技巧性的位移。

Mort注:图片懒得搬运了……请参见原幻灯片。

GC(Garbage Collection)

  • Bitmap标志:以前,GC标志位存储于每个对象中,但现在已经被转移到了专用的内存页中,以减少缓存的误查询(同时也更加CoW (Copy-on-Write)友好)。
  • 非递归标志:标志函数如今避免了机器栈溢出的风险。
  • 惰性清理(从1.9.3起):清理器只有在必须的地方才进行收集(减少了stop时间)。

Ruby 2.0的新核心特性:#1 调试工具

DTrace支持

TracePoint支持

GC stats

Ruby 2.0的新核心特性:#2 核心库

细粒度的异步中断处理

Ruby的执行有时会因为各种原因而中断,例如,超时。

Ruby 2.0提供了细粒度的异步中断处理方案:

1
2
3
4
5
6
7
8
9
10
11
12
13
Thread .async_interrupt_timing Timeout::Error => :defer do
   timeout(rand()) do
     begin
       Thread .async_interrupt_timing Timeout::Error => :immediate do
         setup
         handle
         ...
       end
     ensure
       teardown
     end
   end
end

模块前插

有时候你想要给一个方法添加需要的安装或拆解代码,而相应的部分却定义在别处。

1
2
3
4
5
module ActiveRecordHelper
   def save
     ???
   end
end

该如何去做呢?在Ruby 2.0中,你可以:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Foo < AR ::Base
   prepend AR ::Helper
 
   def save
     bar
   end
end
 
module AR ::Helper
   def save
     foo
     super
     baz
   end
end
 
Foo. new .save

这避开了Rails中的所谓“别名方法链(alias method chain)”的困扰。AMC什么的已经不再必要了。

惰性枚举器

Ruby的foo.bar.baz. ...风格(所谓的“流水作业”)有时会传递许多并不必要的临时对象,而这些理论上都可以通过惰性求值来避免。

1
2
3
4
5
6
7
8
9
10
11
12
File .open(path) {|fp|
     fp.each_line. \
     select {|line| # 生成了临时数组
     /regexp/ =~ line
     }. \
     each_with_index.map {|line, no| # 生成了临时数组
     sprintf( "%d: %s\n" , no, line)
     }. \
     first( 10 ). each {|str| # 生成了临时数组
         puts(str)
     }
}
1
2
3
4
5
6
7
8
9
10
11
12
File .open(path) {|fp|
     fp.each_line.lazy \
     select {|line| # 没有临时数组产生
     /regexp/ =~ line
     }. \
     each_with_index.map {|line, no| # 没有临时数组产生
     sprintf( "%d: %s\n" , no, line)
     }. \
     first( 10 ). each {|str| # 没有临时数组产生
         puts(str)
     }
} # 甚至在到达EOF之前都不读取数据

一个有趣的应用实例:无穷枚举器。

1
2
3
4
# Leibniz formula for π
( 0 ..Float:: INFINITY ).lazy.map {|i|
     ((- 1 ) ** i) / ( 2 *i + 1 ).to_f
}.take( 65536 ).reduce(:+) * 4

其他的新方法

  • Kernel.__dir__:获取__FILE__所在的目录名。
  • Kernel#to_h:通用的Hash转换方法。
  • Random类(1.9+):可重复的PRNG。
  • IO#wait_writable:等待直到可写。
  • Refinements: 实验性的。

Mort注:更多关于Ruby 2.0核心特性的介绍,参考

Ruby 2.0标准库的改进

  • CGI
    • CGI已经为HTML5做好了一切准备。
  • net/http
    • 支持SNI(Server Name Indication)。
  • Zlib绑定
    • Zlib如今运行在解释器的进程锁之外。这意味着zlib在多线程的情形下运行速度将更快。
  • 更新的stdlibs(标准库)
    • Rubygems 2.0.0
    • JSON 1.7.7
    • Rake 0.9.5
    • Rdoc 4.0
    • 以及其它(REXML,yaml,openssl……)

总结

什么不是Ruby 2中的新鲜货

  • 几乎所有的东西!
  • “100%后向兼容”,matz如是说。
  • (举个例子来说)Rails仍然能完好运行如初。
  • 不必畏惧!开始使用2.0.0版吧!

也就是说,

  • 新的东西被加进来了。
  • 许多内部的东西得到了改进。
  • 即使你对你当前的环境充分自信,2.0.0仍然值得你拥有。

Don’t be afraid. Use Ruby today!

转载地址:http://blog.jobbole.com/33904/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值