ruby入门看的是经典的《ruby编程语言》,可是那描述的是v1.9的老版本啊!下面聊一下ruby2.x.x的新特性,x是0-n都有可能啊。

1.关键字参数(Keyword arguments)

在1.9的时候为了模拟这个功能,我们需要传递散列:

2.1.3 :044 > def foo(n,others)

2.1.3 :045?>   puts n

2.1.3 :046?>   puts others[:name]

2.1.3 :047?>   puts others[:age]

2.1.3 :048?>   end

=> :foo

2.1.3 :049 > foo(11,name:"ks",age:11)

11

ks

11


但是如果要有默认值怎么办?新的关键字参数特性正好满足这些功能:

2.1.3 :050 > def foo(n,name:"noname",age:11)

2.1.3 :051?>   puts [n,name,age]

2.1.3 :052?>   end

=> :foo

2.1.3 :053 > foo 100

100

noname

11


对于不带默认值的参数如果在调用时省略会抛出异常的:

2.1.3 :054 > def foo(n,name:"noname",age:)

2.1.3 :055?>   puts [n,name,age]

2.1.3 :056?>   end

=> :foo

2.1.3 :057 > foo 11

ArgumentError: missing keyword: age

from (irb):57

from /Users/apple/.rvm/rubies/ruby-2.1.3/bin/irb:11:in `<main>'

2.字符串的#freeze优化

ruby中的字符串总是易变的,就算是内容相同的字符串,这在大量调用时会产生内存的浪费。不过在使用freeze后,会在冻结字符串表中查找字符串,导致内容相同的字符串会重复利用:

2.1.3 :058 > def rept

2.1.3 :059?>   "hello"

2.1.3 :060?>   end

=> :rept

2.1.3 :061 > 3.times {puts rept.object_id}

70098312821560

70098312821460

70098312821400

=> 3

2.1.3 :062 > def rept;"hello".freeze end

=> :rept

2.1.3 :063 > 3.times {puts rept.object_id}

70098312835340

70098312835340

70098312835340

=> 3


3.def返回方法的名字作为标示符

以前的def定义最后返回的是nil,现在是返回方法名字:

2.1.3 :064 > x=def foo; end

=> :foo

2.1.3 :065 > x

=> :foo

顺面把原来的示例代码贴出来解释下:

module Around
  def around(method)
    prepend(Module.new do
      define_method(method) do |*args, &block|
        send(:"before_#{method}"if respond_to?(:"before_#{method}"true)
        result = super(*args, &block)
        send(:"after_#{method}"if respond_to?(:"after_#{method}"true)
        result
      end
    end)
    method
  end
end
 
class Example
  extend Around
 
  around def call
    puts "call"
  end
 
  def before_call
    puts "before"
  end
 
  def after_call
    puts "after"
  end
end
 
Example.new.call

这里用到了Module的prepend方法,和include和extend类似,prepend也是将模块插入到类或其他模块中,它扩展的是实例方法(这点和include更像),不过插入的位置不同:它会插入到被插入类的“前面”而不是“后面”,即是说,如果A中有方法foo,它被prepend到有同名方法的类B中,则A#foo会先调用。如果是include到类B中,则B#foo会先调用。

4 有理数和复数字面量

我们已经有了整数(1) 和浮点数(1.0) 字面量, 现在我们也有有理数(1r)和复数(1i)字面量了。

他们配合Ruby的类型转换机制可以轻松搞定数学操作,好比,一个数学上的有理数1/3可以在Ruby中写作1/3r。3i会生成复数0+3i。这意味着复数可以写成标准的标准的数学符号, 2+3i 生成复数2+3i!

5 数组枚举的#to_h方法

现在数组和任何包含枚举的类都有#to_h方法了,so可以这样写代码:

2.1.3 :067 > [[1,2],[3,4]].to_h

=> {1=>2, 3=>4}

2.1.3 :068 > require "set"

=> true

2.1.3 :069 > Set[[1,2],[3,4]].to_h

=> {1=>2, 3=>4}

6 细粒度方法缓存

Ruby2.1之前使用一个全局方法缓存,当代码中任何一个地方定义一个方法,模块引入,模块对象拓展时,这一全局方法缓存都会失效。这使得一些类--如OpenStruct -- 以及一些技术 -- 如exception
tagging
 -- 出于性能原因而不可用。

现在不会有这个问题了, Ruby 2.1 使用基于类层次的方法缓存, 只有讨论中的类和任意子类才会失效缓存。

一个已经加入到 RubyVM 类的方法会返回一些方法缓存状态的调试信息。这个直接看示例代码吧:

class Foo
end

RubyVM.stat   #=> {:global_method_state=>133, :global_constant_state=>820,
                    :class_serial=>5689}

# setting constant increments :global_constant_state

Foo::Bar = "bar"

RubyVM.stat(:global_constant_state)   #=> 821

# defining instance method increments :class_serial

class Foo
  def foo
  end
end

RubyVM.stat(:class_serial)            #=> 5690

# defining global method increments :global_method_state

def foo
end

RubyVM.stat(:global_method_state)     #=> 134

7 Refinements

refine和using配合使用,它们可以在一个局部的作用域中扩展一个模块或类而不污染全局空间,比如:

2.1.3 :091 > module A

2.1.3 :092?>   refine String do

2.1.3 :093 >       def sh2

2.1.3 :094?>       self*2

2.1.3 :095?>       end

2.1.3 :096?>     end

2.1.3 :097?>   end

=> #<refinement:String@A>

2.1.3 :098 > module B

2.1.3 :099?>   using A

2.1.3 :100?>   "a".sh2

2.1.3 :101?>   end

=> "aa"

2.1.3 :102 > "a".sh2

NoMethodError: undefined method `sh2' for "a":String

from (irb):102

from /Users/apple/.rvm/rubies/ruby-2.1.3/bin/irb:11:in `<main>'

2.1.3 :103 > using A

=> main

2.1.3 :104 > "a".sh2

NoMethodError: undefined method `sh2' for "a":String

from (irb):104

from /Users/apple/.rvm/rubies/ruby-2.1.3/bin/irb:11:in `<main>'

8 String#scrub

字符串增加scrub方法用来剔除无效的字符,这个可以参考下ri的结果:

= .scrub

(from ruby site)

=== Implementation from String

------------------------------------------------------------------------------

str.scrub -> new_str

str.scrub(repl) -> new_str

str.scrub{|bytes|} -> new_str

------------------------------------------------------------------------------

If the string is invalid byte sequence then replace invalid bytes with given

replacement character, else returns self. If block is given, replace invalid

bytes with returned value of the block.

"abc\u3042\x81".scrub #=> "abc\u3042\uFFFD"

"abc\u3042\x81".scrub("*") #=> "abc\u3042*"

"abc\u3042\xE3\x80".scrub{|bytes| '<'+bytes.unpack('H*')[0]+'>' } #=> "abc\u3042<e380>"


9 $SAFE级别4被移除

设置$SAFE = 4目的是将Ruby放入一个“沙箱”模型并且允许执行不受信任的代码。 然而这并不是十分有效, 因为这需要代码分散到整个Ruby中,并且这几乎从来没有被用到,所以就被移除了。

2.1.3 :114 > $SAFE=4

ArgumentError: $SAFE=4 is obsolete

from (irb):114

from /Users/apple/.rvm/rubies/ruby-2.1.3/bin/irb:11:in `<main>'

10 Process.clock_gettime

可以通过以上方法来访问系统的clock_gettime函数,从而获取不同种类的时间值,比如一般系统都支持以下3个:

Process::CLOCK_REALTIME将返回一个unix时间戳。这和Time.now.to_f返回值相同,但是因为它跳过创建时间实例,所以会更快一点。

Process::CLOCK_MONOTONIC用途是访问一个单调时钟,这个时钟总是向前移动,无论系统时钟如何调整。这对关键时序或者基准测试是完美的。

Process::CLOCK_PROCESS_CPUTIME_ID对基准测试是有用的,它的工作方式和单调时钟相似,总是向前移动,只有和另一个cpu time做参考时才有意义,但是它只有在CPU工作的情况下,时间才向前移动。

可以检查Process常量查询是否支持其他时钟,比如我的Mac OS 上有:

2.1.3 :118 > Process.constants

=> [:WNOHANG, :WUNTRACED, :Status, :PRIO_PROCESS, :PRIO_PGRP, :PRIO_USER, :RLIM_SAVED_MAX, :RLIM_INFINITY, :RLIM_SAVED_CUR, :RLIMIT_AS, :RLIMIT_CORE, :RLIMIT_CPU, :RLIMIT_DATA, :RLIMIT_FSIZE, :RLIMIT_MEMLOCK, :RLIMIT_NOFILE, :RLIMIT_NPROC, :RLIMIT_RSS, :RLIMIT_STACK,
:CLOCK_REALTIME, :CLOCK_MONOTONIC, :CLOCK_PROCESS_CPUTIME_ID, :Tms, :UID, :GID, :Sys]

使用很简单:

2.1.3 :121 > Process.clock_gettime(Process::CLOCK_REALTIME)

=> 1417521526.4812741

2.1.3 :122 > start = Process.clock_gettime(Process::CLOCK_MONOTONIC)

=> 30244.170570458

2.1.3 :123 > sleep 1

=> 1

2.1.3 :124 > Process.clock_gettime(Process::CLOCK_MONOTONIC) - start

=> 14.592389030996856

2.1.3 :125 > start = Process.clock_gettime(Process::CLOCK_PROCESS_CPUTIME_ID)

=> 0.600038

2.1.3 :126 > sleep 1

=> 1

2.1.3 :127 > Process.clock_gettime(Process::CLOCK_PROCESS_CPUTIME_ID) - start

=> 0.01080200000000009

11 升级RubyGems

Ruby自带的RubyGems版本升级到2.2。基础的Gemfile支持已添加对Gemfile.lock的支持,并向着合入所有Bundler功能到RubyGems而努力。

gem install的--file(或者-g)选项不再要求依赖文件的文件名,它将自动检测Gemfile。如果文件不存在,gem install将产生Gemfile.lock,如果文件存在将遵循特定的版本。

?
1
2
3
4
5
6
7
8
ls
Gemfile
$ gem install -g
Fetching: going_postal-0.1.4.gem (100%)
Installing going_postal (0.1.4)
ls
Gemfile
Gemfile.lock

12 进程标题

添加新的方法Process.setproctitle用于设置进程的标题,不用再设置$0。还增加了相关的方法Process.argv0用于查看$0的初始值,如果$0被设置的话。

2.1.3 :129 > $0

=> "irb"

2.1.3 :130 > $0= "irb_love"

=> "irb_love"

2.1.3 :131 > $0

=> "irb_love"

2.1.3 :132 > Process.argv0

=> "/Users/apple/.rvm/rubies/ruby-2.1.3/bin/irb"

apple@kissAir: ruby_src$ps

PID TTY           TIME CMD

1497 ttys000    0:00.11 -bash

501 ttys001    0:00.38 -bash

595 ttys002    0:00.18 -bash

1251 ttys002    0:00.62 irb

633 ttys003    0:00.17 -bash

775 ttys004    0:00.17 -bash

794 ttys005    0:00.16 -bash

856 ttys006    0:00.17 -bash

apple@kissAir: ruby_src$ps

PID TTY           TIME CMD

1497 ttys000    0:00.11 -bash

501 ttys001    0:00.38 -bash

595 ttys002    0:00.18 -bash

1251 ttys002    0:00.63 irb_love

633 ttys003    0:00.17 -bash

775 ttys004    0:00.17 -bash

794 ttys005    0:00.16 -bash

856 ttys006    0:00.17 -bash

13 修复了eval作用域解析错误

当eval, instance_eval 或者 module_eval 解析的字符串中含有不带参数的private,protected,public或module_function时,方法的可见作用域变成了它调用处的作用域,如下面这个例子 foo 将会是private的。

?
1
2
3
4
5
6
7
class Foo
  eval "private"
   
  def foo
    "foo"
  end
end

这种情况已经在2.1中得到了修正。所以,在这个例子中,foo应该是public的.

14 #untrusted?现在是#tainted?的别名

之前,Ruby有两套方法来标识/检查对象是否是untrusted,第一套是#tainted?,#taint和#untaint,另一套是#untrusted?,#untrust, 和#trust。这些方法行为都一样,但是分别设置了标识,所以一个对象可能是 untrusted,但不是tainted。

这些方法已经被统一成了对单个的标识设值或取值。#tainted?等是推荐的用法,而#untrusted?等会产生警告。

?
1
2
3
string = "foo"
string.untrust
string.tainted?   #=> true

产生的警告:

?
1
example.rb:2: warning: untrust is deprecated and its behavior is same as taint

不过在2.1.3上测试并没有发现警告

15 Lambda 中的return总是从Lambda返回

Lambdas 不同于内部使用了return的Lambda并从lambda返回的Procs/blocks,它不是封闭方法. 但是有一个例外,如果传给某个方法的lambda带有&并且被yield调用. 这一例外目前已经被移除了。

2.1.3 :155 > def call_lambda

2.1.3 :156?>   yield

2.1.3 :157?>   end

=> :call_lambda

2.1.3 :158 > def foo

2.1.3 :159?>   call_lambda(&lambda {return "from lambda"})

2.1.3 :160?>   "from method"

2.1.3 :161?>   end

=> :foo

2.1.3 :162 > foo

=> "from method"

?

上面的例子在Ruby 2.0.0 之前的版本会返回"from lambda"。

16 获取网络接口地址

目前可以通过Socket.getifaddrs获取系统的网络接口详细信息。将返回Socket::Ifaddr对象数组。

2.1.3 :177 > info = Socket.getifaddrs.find do |ifaddr|

2.1.3 :178 >       (ifaddr.flags & Socket::IFF_BROADCAST).nonzero? &&

2.1.3 :179 >         ifaddr.addr.afamily == Socket::AF_INET

2.1.3 :180?>   end

=> #<Socket::Ifaddr en0 UP,BROADCAST,RUNNING,NOTRAILERS,MULTICAST,0x800 192.168.0.3 netmask=255.255.255.? (7 bytes for 16 bytes sockaddr_in) broadcast=192.168.0.255>

2.1.3 :181 > info.addr.ip_address

=> "192.168.0.3"


17 Queue,SizedQueue和ConditionVariable性能提升

Queue,SizedQueue和ConditionVariable已经在C语言中加速实现。

18 Set

Set 中加入了#intersect? 和 #disjoint? 方法。当接收者和参数两者之间至少有一个共同值的时候#intersect? 会返回true,反之,返回false。#disjoint? 则恰恰相反,如果集合之间没有相同的值,返回true,反之,返回false。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
require "set"
 
a = Set[1,2,3]
b = Set[3,4,5]
c = Set[4,5,6]
 
a.intersect?(b)   #=> true
b.intersect?(c)   #=> true
a.intersect?(c)   #=> false
 
a.disjoint?(b)   #=> false
b.disjoint?(c)   #=> false
a.disjoint?(c)   #=> true

Set的另一个主要的变化是,调用一个 set 的 #to_set 会返回它自身,而不是它的拷贝。

?
1
2
3
4
5
require "set"
 
set = Set["foo""bar""baz"]
set.object_id          #=> 70286489985620
set.to_set.object_id   #=> 70286489985620


19 #include 和 #prepend 现在是public的了

Module 和 Class 中的 #include 和 #prepend 方法现在是public的了

2.1.3 :202 > module M

2.1.3 :203?>   def sh

2.1.3 :204?>     self*2

2.1.3 :205?>     end

2.1.3 :206?>   end

=> :sh

2.1.3 :207 > String.include M

=> String

2.1.3 :208 > "a".sh

=> "aa"

2.1.3 :209 > Numeric.include M

=> Numeric

2.1.3 :210 > 1.sh

=> 2


20 Module/Class #singleton_class?

Module 和 Class 中引入了一个#singleton_class? 方法,用来返回接收器是否是一个单类。这个不用解释吧

?
1
2
3
4
5
6
class Example
  singleton_class?     #=> false
  class << self
    singleton_class?   #=> true
  end
end

21 Method#original_name

Method 和UnboundMethod 中添加了一个#original_name方法,来返回非别名。

?
1
2
3
4
5
6
7
8
9
10
11
class Example
  def foo
    "foo"
  end
  alias bar foo
end
 
example = Example.new
example.method(:foo).original_name            #=> :foo
example.method(:bar).original_name            #=> :foo
Example.instance_method(:bar).original_name   #=> :foo

22 整数/大数 #bit_length

调用integer的#bit_length方法会返回一个代表该数二进制数的位数的数字。

2.1.3 :218 > 15.bit_length

=> 4

2.1.3 :219 > 12**12.bit_length

=> 20736

2.1.3 :220 > 12**120.bit_length

=> 35831808

2.1.3 :221 > 12**1200.bit_length

=> 743008370688


23 pack/unpack 本机字节存储次序 long long

Array#pack和String#unpack中添加了使用Q_/Q!和_/q!指令来处理本机字节存储次序的能力.

?
1
2
3
4
5
6
7
8
# output may differ depending on the endianness of your system
unsigned_long_long_max = [2**64 1].pack("Q!")   #=> "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
signed_long_long_min = [-2**63].pack("q!")        #=> "\x00\x00\x00\x00\x00\x00\x00\x80"
signed_long_long_max = [2**63 1].pack("q!")     #=> "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x7F"
 
unsigned_long_long_max.unpack("Q!")   #=> 18446744073709551615
signed_long_long_min.unpack("q!")     #=> -9223372036854775808
signed_long_long_max.unpack("q!")     #=> 9223372036854775807

24  tempfile.create

Tempfile 现在有了一个类似与new的create方法,不同的是,他并不是返回一个当对象被回收后使用finaliser来清理文件的Tempfile实例,而是得到一个块内的普通文件对象,并在块结束时清理该文件。

2.1.3 :225 > require 'tempfile'

=> true

2.1.3 :226 > Tempfile.create("foo") do |f|

2.1.3 :227 >     puts f.path

2.1.3 :228?>   end

/var/folders/z2/n3vz292s0z7f995w0_bphm780000gn/T/foo20141202-1251-1hghnr0

=> nil

2.1.3 :229 > File.exist? "/var/folders/z2/n3vz292s0z7f995w0_bphm780000gn/T/foo20141202-1251-1hghnr0

2.1.3 :230"> "

=> false


25 curses 库被移除了

curses 已经被从标准库中移除了,现在需要单独下载gem了。

参考地址:http://www.oschina.net/translate/ruby-2-1-in-detail

原文地址:http://globaldev.co.uk/2014/05/ruby-2-1-in-detail/

ruby 2.x.x之新特性散谈的更多相关文章

  1. [C#]6.0新特性浅谈

    原文:[C#]6.0新特性浅谈 C#6.0出来也有很长一段时间了,虽然新的特性和语法趋于稳定,但是对于大多数程序猿来说,想在工作中用上C#6.0估计还得等上不短的一段时间.所以现在再来聊一聊新版本带来 ...

  2. JDK各版本新特性浅谈

    JDK 5.0 自动拆装箱 枚举 可变参数 泛型 For -each 内省 静态导入 JDK 6.0 console开发控制台程序 轻量级HTTP ServerAPI 支持脚本语言 使用Compile ...

  3. 前端进阶系列(三):HTML5新特性

    HTML5 是对 HTML 标准的第五次修订.其主要的目标是将互联网语义化,以便更好地被人类和机器阅读,并同时提供更好地支持各种媒体的嵌入.HTML5 的语法是向后兼容的.现在国内普遍说的 H5 是包 ...

  4. PHP5.3、PHP5.4、PHP5.5、PHP5.6的新特性

    1. PHP5.3中的新特性 1.1 支持命名空间(namespace) 毫无疑问,命名空间是PHP5.3所带来的最重要的新特性. 在PHP5.3中,可以用命名空间防止代码的冲突,命名空间的分隔符为 ...

  5. php7 新特性整理

    PHP7 已经出来1年了,PHP7.1也即将和大家见面,这么多好的特性,好的方法,为什么不使用呢,也希望PHP越来越好. 在这里整理 PHP 5.1 ,PHP5.2,PHP5.3,PHP5.4,PHP ...

  6. 一文带你看遍 JDK9~14 的重要新特性!

    Java9 发布于 2017 年 9 月 21 日 .作为 Java8 之后 3 年半才发布的新版本,Java 9 带 来了很多重大的变化其中最重要的改动是 Java 平台模块系统的引入,其他还有诸如 ...

  7. PHP的学习--新特性

    最近做的项目使用了 php7,但感觉有很多新特性没有用起来.就想总结一下,一些可能会用到的新特性.之前使用的环境是 php5.4,所有也会有 php5.5 和 php5.6 的特性总结进来,这里只列出 ...

  8. JDK1.5/1.6/1.7之新特性总结(转载)

    原文地址:http://www.cnblogs.com/yezhenhan/archive/2011/08/16/2141510.html 如果原作者看到不想让我转载请私信我! 开发过程中接触到了从j ...

  9. HTML5和CSS3新特性一览

    HTML5 1.HTML5 新元素 HTML5提供了新的元素来创建更好的页面结构: 标签 描述 <article> 定义页面独立的内容区域. <aside> 定义页面的侧边栏内 ...

随机推荐

  1. FFmpeg源代码简单分析:libswscale的sws_getContext()

    ===================================================== FFmpeg的库函数源代码分析文章列表: [架构图] FFmpeg源代码结构图 - 解码 F ...

  2. Emojicon表情之快速应用于Android项目

    最近在项目中遇到了一个问题,找了半天原因,最后发现是用户在昵称中输入了emojicon表情,导致服务器不识别出现错误,而项目中也未对emojicon表情作支持,因此不得不考虑对emojicon表情做下 ...

  3. 【JavaEE WEB 开发】Tomcat 详解 Servlet 入门

    转载请注明出处 :  http://blog.csdn.net/shulianghan/article/details/47146817 一. Tomcat 下载安装配置 1. Tomcat 下载 T ...

  4. Cocos2D iOS之旅:如何写一个敲地鼠游戏(九):创建动画

    大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请告诉我,如果觉得不错请多多支持点赞.谢谢! hopy ;) 免责申明:本博客提供的所有翻译文章原稿均来自互联网,仅供学习交流 ...

  5. 上海C++游戏服务器群活动PPT下载

    下载页面: http://download.csdn.net/download/jq0123/8227519 跨服与跨区的设计PPT 上海C++游戏服务器群 2014.11.9 沙龙讲义. 自我介绍 ...

  6. How to Use Kdiff3 as a 3-way Merge Tool With Mercurial, Git, and Tower.app

    How to Use Kdiff3 as a 3-way Merge Tool With Mercurial, Git, and Tower.app Jan 12th, 2012            ...

  7. [GitHub]第三讲:简单分支操作

    Git 最核心的操作对象是版本( commit ),最核心的操作技巧就是分支. 什么是分支? 仓库创建后,一旦有了新 commit,默认就会放到一个分支上,名字叫 master.前面咱们一直看到的多个 ...

  8. ROS_Kinetic_05 ROS基础内容(二)

    ROS_Kinetic_05 ROS基础内容(二) 1. ROS节点node 官网教程:http://wiki.ros.org/cn/ROS/Tutorials/UnderstandingNodes ...

  9. ROS_Kinetic_01 在ubuntu 16.04安装ROS Kinetic 2017.01更新

    ROS_Kinetic系列学习(一),在ubuntu 16.04安装ROS Kinetic. Celebrating 9 Years of ROS! ubuntu16.04已经发布半年多了,ROS的K ...

  10. The Singularity is Near---预测人工智能,科技走向的神书---奇点临近

    比尔盖茨评价本文作者: 雷·库兹韦尔是我所知道的预测人工智能未来最权威的人.他的这本耐人寻味的书预测未来信息技术得到空前发展,将促使人类超越自身的生物极限--以我们无法想象的方式超越我们的生命. 中文 ...