Jun'uary

Ruby 1.9 (1): 新语法

Jan 发表于 2007-12-28 13:21:09

(标记为Ruby2的是已经确定将在2.0中保留的feature, 标记为Experimental的尚在取舍之中)

字面量Hash (literal hash syntax) (Ruby2)

Hash有了一种新的表示方法: {a: "foo"}, 和{:a => "foo"}效果相同,活生生减去两个键的输入,hash用的太多了,这个改动影响巨大.

Block局部变量(Experimental)

在block中使用局部变量:

a = lambda{|;d| d = 1}
a.call()

注意调用proc的时候没有传参数,因为;d是局部变量的生命(d前面是分号). 如果lambda外部也有一个变量叫做d, 外部变量会被遮盖住,此时ruby会给个warning: "warning: shadowing outer local variable - d "

Block参数的作用域被限制在了局部

a=1
10.times{|a|}
a

1.9中最后a依然是1, block中的a是个本地变量把block外部的a遮盖了. 而在1.8中a最终被修改成了9. 这是一个不向后兼容的修改,估计会导致许多框架出问题吧.

lambda的新语法(Very Experimental)

a = ->(b,c){b+c}
a.call(1,2) # => 3

Matz保证说旧的声明lambda的语法永远不会被去除. 又是一个简化写法的改进,lambda六个字母简化成了->两个字符. 同时新语法支持默认参数, 你可以这样做:

a = ->(b,c=2){b+c}
a.call(1) # => 3

但是你不能这么做:

a = lambda{|b,c=2|b+c} #error

因为据说此写法是无法用Ruby现在使用的基于bison打造LALR(1) parser来实现的. 下面介绍更诡异点的写法,你可以把参数外的括号省略:

->{}.call # => nil
->a,b{a+b}.call(1,2) # => 3
c=1; ->a,b;c{c=a+b}.call(1,2); c # =>1 (注意c前面是分号, 分号后面都是局部变量,不是参数. 新特性,记得吗)
c=2; ->;c{c=1}.call;c # => 2
c=2; ->*d;c{d}.call(1,2,3) # => [1,2,3] (只用了一个*d,还没用上1.9中某些新特性呢...)

好了,不折磨你了,继续看新东西.

用.()来调用Proc (Experimental)

a = lambda{|b|b}
a.(1,2)

现在你不需要call这四个字母了.注意.()中的句点不要漏了,不然ruby以为你在调用一个名字叫做a的函数. 值得一提的是无论对象是什么如果你对它调用.()方法ruby实际上都会试图去调用它的call方法,通过为proc之外的类实现其call方法你可以做出有趣的事情:

"foo".(1,2) # ~> undefined method `call' for "foo":String (NoMethodError)

将block作为参数传递给一个block

class A
  define_method(:foo){|&b| b.()}
end
A.new.foo{puts "bar"}

正确处理多余的block参数

def m
  yield 1,2
end
m{|v| v} # => 1

1.8中v的值会是[1,2], 同时ruby给出warning说传入的参数比block接收的参数多. 1.9能够正确处理,把多余的参数忽略,注意在1.8中你可以通过m{|v,|v}达到相同效果.

允许多个数组展开

def foo(*a)
  a
end
foo(1, *[2,3], 4, *[5,6]) # => [1,2,3,4,5,6]

a,b = [1,2,3],[4,5,6]
[*a, *b] #=> [1,2,3,4,5,6]

必需参数可以放在可选参数后面!

def m(a,b=nil,*c,d)
  [a,b,c,d]
end
m(1) # error
m(1,2) #[1,nil,[],2]
m(1,2,3) #[1,2,[],3]
m(1,2,3,4) #[1,2,[3],4]
m(1,2,3,4,5) #[1,2,[3,4],5]

甚为诡异的分配方法,初学者估计要一头栽倒... 记住必需参数获得赋值的优先级最高,可选参数次之,变长参数最低,然后位置一卡,分配下去... 不知道我这样说是不是更混乱了...

?c语义

?a # => "a" (in 1.9, string)
?a # => 97 (in 1.8, integer)

传递Hash给[]方法

class Foo
  def[](*a)
    a
  end
end
f = Foo.new
f[1,2,:ab=>3,:bc=>4] # => [1,2,{:ab=>3,:bc=>4}]

printf风格的格式化字符串

%c: "%c" % ?a # => "a"
%u: 太诡异了,忘了它吧...

经我试验不成功的feature

* 用to_splat代替to_a
* 传递block给[]方法
* 三元运算符?中允许换行(指a:b分成三行, ?后换行是1.8就允许的)
关键词(Tag): ruby 1.9 changes

曾经的这一天...


收藏: QQ书签 del.icio.us 订阅: Google 抓虾

最新评论

发表评论

* 昵称

已经注册过? 请登录

新用户请先注册 以便能显示头像及追踪评论回复

Email
网址
* 评论
表情
 
 

分类小组论坛
杂谈, 娱乐、八卦, 文学、艺术, 体育, 旅游、同城, 象牙塔, 情感, 时尚、生活, 星座, 科技

请注意遵守中华人民共和国法律法规, 如威胁到本站生存, 将依法向有关部门报告, 同时本站的相关记录可能成为对您不利的证据.

相关法律法规
全国人大常委会关于维护互联网安全的决定
中华人民共和国计算机信息系统安全保护条例
中华人民共和国计算机信息网络国际联网管理暂行规定
计算机信息网络国际联网安全保护管理办法
计算机信息系统国际联网保密管理规定

Jan'uary

人类一思考,老夫就发笑

搜索

日历