Ruby1.9的变化(一) - 新的语法和语意

资料来自:http://eigenclass.org/hiki.rb?Changes+in+Ruby+1.9

文中有实验性标记的说明很可能会在短时间内被拿掉,原文中解释为”crazy ideas“。
最近将持续连载翻译Ruby1.9的变化。

新的语法和语意

新的字面量hash语法[Ruby2]

  1. {a: "foo"} # => {:a=>"foo"}

代码块局部变量 [实验性]

如下使用:
  1. # {normal args一般参数; 局部变量local variables}
  2. d = 2
  3. a = lambda{|;d| d = 1}
  4. a.call()
  5. d # => 2

当一个变量被隐藏时,Ruby1.9会给出一个警告:

  1. -:2: warning: shadowing outer local variable - d

代码块参数的作用域总是在代码块内

  1. a = 1
  2. 10.times{|a| } # !> 代码块外的局部变量a被隐藏
  3. a              # => 1

新的lambdas语法 [非常实验性]

  1. {|a,b=1| ... }

这种语法在目前的基于bison的Ruby解析器LALR是不能实现的.

这种新语法可以不用括号包裹参数:

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

还可以更加诡异地使用:

  1. c = 2; -> ;c { c = 1 }.call; c # => 2

甚至是

  1. c = 2; -> *d ; c { d }.call(1,2,3) # => [1, 2, 3]
  2. c = 2; -> ; c { c = 1 }.call; c # => 2

用.()替代使用call方法或者[]方法来调用Procs[实验性]

现在可以这样做:

  1. a = lambda{|*b| b}
  2. a.(1,2)                # => [1, 2]

注意你需要句点:

  1. a = lambda{|*b| b}
  2. a(1,2)                # =>
  3.                       #        (eval):2: syntax error...
  4.                       #        (a)(1,2)...
  5. ~> -:2: undefined method `a' for main:Object (NoMethodError)

可以在括号内使用任何表达式:

  1. (lambda{|a,b| a + b}).(1,2)                # => 3

.()用法会无视接受者而调用其call方法:

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

Block arguments代码块参数

代码块可以使用&block参数:

  1. define_method(:foo){|&b| b.call(bar)}

ruby-dev:23533

新的代码块参数语意

|v|现在会像|v,|的形式工作:

  1. [RUBY_VERSION, RUBY_RELEASE_DATE]                 # => ["1.8.5", "2006-08-25"]
  2. def m; yield 1, 2; end
  3. m{|v| v}                                          # => [1, 2] # !> multiple values for a block parameter (2 for 1)

相对应的:

  1. [RUBY_VERSION, RUBY_RELEASE_DATE]                 # => ["1.9.0", "2007-08-03"]
  2. def m; yield 1, 2; end
  3. m{|v| v}                                          # => 1

to_splat 方法使用*参数

用to_splat方法代替to_a方法
nil.to_splat 返回 [].

允许多个*操作符

经Audrey Tang建议,Ruby1.9允许在方法调用是使用多个*操作符

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

表达式也是:

  1. [RUBY_VERSION, RUBY_RELEASE_DATE]                # => ["1.9.0", "2007-08-03"]
  2. a = [1,2,3]
  3. b = [4,5,6]
  4. [*a, *b]                                         # => [1, 2, 3, 4, 5, 6]

允许在可选参数后加上必要参数

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

?c的语意

?a现在返回一个单字符字符串代替原来的整数值:

  1. ?a   # => "a"

[] 方法的参数

可以在[]方法中使用星号,"assocs"(不用方括号的hash)和代码块参数:

  1. RUBY_VERSION                                       # => "1.9.0"
  2. RUBY_RELEASE_DATE                                  # => "2006-06-11"
  3. class Foo; def [](*a, &block); block.call(a) end end
  4.  
  5. a = (0..3).to_a
  6. Foo.new[*a, :op => :+]{|x| x }                     # => [0, 1, 2, 3, {:op=>:+}]

printf风格的格式化字符串(%)

%c 可以输出单字符字符串
%u 为负数提供类似%d的格式 (ruby-core:11575)

允许三元运算符( ? : )扩展到新行

  1. p 1 == 2 ?
  2. 0
  3. :
  4. 1
  5. # >> 1

ruby-dev:29189

defined?方法和局部变量

  1. RUBY_VERSION # => "1.8.5"
  2. RUBY_RELEASE_DATE # => "2006-08-25"
  3. a = 0
  4. defined? a # => "local-variable"
  5. 1.times do |i|
  6. defined? i # => "local-variable(in-block)"
  7. end

相对应的:

  1. RUBY_VERSION # => "1.9.0"
  2. RUBY_RELEASE_DATE # => "2007-08-03"
  3. a = 0
  4. defined? a # => "local-variable"
  5. 1.times do |i|
  6. defined? i # => "local-variable"
  7. end

Posted by maninred 2008年1月25日 17:07