Ruby 1.9中非常酷的功能

shi*_*zui 23 ruby ruby-1.9

随着Ruby 1.9.2版本即将发布,现在是让开发人员对Ruby 1.9感到兴奋的时候了.你可以在Ruby 1.9中做些什么好事,你在Ruby 1.8中做不到?

Jör*_*tag 31

我不敢相信这还没有被提及:Ruby 1.9.2+的最大特点是,17年来Ruby首次有了规范.

您可能听说过Ruby 1.9.2(本应在2010年春季发布)的所有发布计划都已取消,这就是原因:首先,将开发一个完整的Ruby 1.9.2规范. RubySpec项目,然后将发布Ruby 1.9.2(编程语言),只有它通过RubySpec测试套件才会发布YARV 1.9.2 .

这完全取决于以前的工作原理:首先发布了MRI,然后所有其他实现者都读取了(不是很好设计,通常记录很差)的C源代码,以试图弄清楚这个新功能到底是什么本来应该做的,然后他们试图编写可执行的规范,只有这样他们甚至有远程实际兼容的机会.但到那个时候,一般来说,YARV的新版本已经发布,并且周期重新开始......更不用说MRI和YARV的维护者甚至没有运行RubySpecs.

这有很大的影响.例如,尽管目前有十几种不同的Ruby实现正在积极开发中,并且多年来它已经有超过30种不同的Ruby编程语言实现,但这一事实还没有被维护者所承认. Ruby编程语言.对于他们来说,Ruby和MRI(或者更近期的Ruby和YARV)一直都是同一件事:MRI既是语言又是执行引擎,Ruby既是执行引擎又是语言.Ruby编程语言的"规范"是MRI的C源代码.

截至五周前,这已经发生了变化:现在,Ruby编程语言的官方规范(至少版本1.9.2及更高版本)是RubySpec项目的可执行测试套件.而YARV只是另一个Ruby实现,完全等同于MacRuby,IronRuby,JRuby,Cardinal,tinyrb,SmallRuby,BlueRuby,MagLev等.

这意味着所谓的"备用"实现(现在不再称为"备用",因为YARV已失去其特殊状态)现在有机会实际赶上YARV中实现的最新语言功能.事实上,由于大多数其他实现实际上都比YARV更好地设计和实现了更好的语言(这基本上是一个巨大的意大利面C),加上拥有更多的人力,其他实现实际上是完全合理的 YARV 之前符合Ruby 1.9.2 .


Jim*_*lle 16

我个人喜欢新的哈希语法:{:a => 1}成为{a:1}

  • 同意了,但是在我开始在代码中使用它之前还有一段时间我会回馈社区.它不够酷,不能单独打破向后兼容性.(我确实在测试中使用它,或者因为我使用的其他功能而使用的代码在1.8中不起作用.) (2认同)

Aug*_*aas 13

普查员.

["a", "b", "c"].map {|elem, i| "#{elem} - #{i}" }
# => ["a - ", "b - ", "c - "]
["a", "b", "c"].each_with_index.map {|elem, i| "#{elem} - #{i}" }
# => ["a - 1", "b - 2", "c - 3"]
Run Code Online (Sandbox Code Playgroud)

Enumerablemethods返回Enumerator没有传递块的实例.在这种情况下,它用于给出map一个index参数,取自each_with_index.

这也被反向移植到1.8.7.


Fil*_*eca 11

Ruby 1.9具有不同的行为:

  • 块参数始终是其块的本地参数,块的调用永远不会为现有变量赋值:

  • 块语法已扩展为允许您声明保证为本地的块本地变量,即使封闭范围中已存在同名的变量也是如此.

线程也不同:

  • Ruby 1.8只使用一个本机线程,并在该一个本机线程中运行所有Ruby线程.这意味着线程非常轻量级但它们从不并行运行.

  • Ruby 1.9不同,它为每个Ruby线程分配一个本机线程.但是因为使用的某些C库本身不是线程安全的,所以Ruby非常保守,并且永远不会允许多个本机线程同时运行(这种限制可能会在以后的版本中放宽)

其他一些小改动是在加载路径中包含RubyGems,不再需要require "rubygems"了.


SFE*_*ley 10

我喜欢枚举了很多 -不仅为现有类型,但写我自己的藏品为枚举类.自从切换到1.9以来,我有两次不得不为外部Web服务构建API适配器,从而提取大型JSON或XML结果集.有时我会被限制在一次可以检索多少条记录,这意味着我需要做多个请求.(获得前500,然后获得记录501到1000等)

我已经处理过的"旧"方法是获取第一批,用.eachor 一次迭代它.collect,并创建一个大小相等的Ruby对象数组.如果我无法在一个请求中获取所有记录,我也会循环访问API请求,每次都添加到数组中.这意味着所有的时间都是前载的,被认为是一种缓慢的检索,而且我正在嚼大量的内存:源数据,相同数量的Ruby对象,有时用于中间数组操作.当我可能一次仅在一个对象上操作时,这是浪费的.

使用枚举器,我可以获取第一批,将源数据保存为我的"权威"集合,并在我进入它时处理并生成每个Ruby对象.当我传递最后一个元素时,如果我知道要从源中提取更多数据,那么我可以进行下一个API调用.(即,延迟加载.)这意味着在检索方法调用上获得更快的返回,并且更好的内存使用.我完成后,每个Ruby对象都有资格进行垃圾收集,并且已经移动到下一个.

这个想法的抽象实现看起来像这样:

class ThingyCollection < Enumerator
  attr_reader :total

  # Returns a new collection of thingies.
  def initialize(options={})

    # Make the request for the first batch
    response = ThingyAPIClient.get_thingies(options)
    @total = response.total   # Number of ALL thingies, not just first batch
    records = response.data  # Some array of JSON/XML/etc. from the API 

    # Create a closure which serves as our enumerator code
    enum = Proc.new do |yielder|
      counter = 0              # Initialize our iterator
      while counter < @total

        # If we're at the end of this batch, get more records
        if counter == records.length  
          more = ThingyAPIClient.get_next_thingies(counter, options)
          records += more.data
        end

        # Return a Ruby object for the current record 
        yielder.yield Thingy.new(records[counter])   
        counter += 1
      end
    end

    # Pass that closure to the Enumerator class
    super(&enum)
  end
end
Run Code Online (Sandbox Code Playgroud)

一旦你有了,你就可以走过它们,如:

thingies = ThingyCollection.new(foo: bar) # Whatever search options are relevant
puts "Our first thingy is #{thingies.next}"
puts "Our second thingy is #{thingies.next}"
thingies.rewind
thingies.each do |thingy|
  do_stuff(thingy)
end
Run Code Online (Sandbox Code Playgroud)

你输了什么?主要是通过引用轻松跳转到特定元素的能力.(这意味着你也失去了"最后",排序等等)只是获得.next并且有几个.each变体没有数组功能那么丰富,但对于我最常见的用例,这就是我所需要的.

是的,由于backporting,你可以使用Ruby 1.8.7做到这一点.但由于内部使用纤维,1.9的速度要快得多.如果它不是1.9,那么就不会有1.8.7,所以我认为它仍然是我最喜欢的1.9功能.


shi*_*zui 9

Ruby 1.9.2支持获取有关方法参数的信息.您可以获取参数的名称以及有关它们的信息,例如optional,required或block.

查看方法#params的示例.


shi*_*zui 9

哈希以红宝石1.9订购.它在实现某些算法时非常有用.您必须依赖gem或在ruby 1.8中编写自己的有序哈希.


Ken*_*oom 6

对多字节字符编码的完全本机支持,尤其是Unicode.


hor*_*guy 5

instance_exec和class_exec是很棒的新功能,但对我而言,主要是小的更改(已经向后移植到1.8.7).像Method#owner这样的东西很棒 - 曾经想知道在继承链中确切定义了一个特定的方法?my_object.method(:blah).owner会告诉你:)

我喜欢1.9的其他事情是更一致的范围规则,尤其是.在eval上下文中.这是一个愚蠢的遗漏(IMO),常量和类变量没有在instance_eval中查找,1.9修复了这个:)


Chu*_*uck 5

我喜欢Symbol#to_proc,这样可以节省每次使用高阶函数时必须写一个lambda.因此,虽然总结一个数组arr.inject(0) {|memo, val| memo + val},现在你可以写arr.inject(&:+),而不是houses.collect {|house| house.price},你可以写houses.collect(&:price).

有些库(例如ActiveSupport)在1.8下提供了相同的功能,但是将它作为核心语言的一部分仍然很好,并且1.9实现比库方法更好地优化.