Jun'uary
Jan'uary » 日志 » Ruby 1.9 (1): 新语法
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就允许的)
字面量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就允许的)
曾经的这一天...
- » 2005年: 陈绮贞cheer精选集 躺在你的衣柜
收藏:
QQ书签
del.icio.us
订阅:
Google
抓虾
