设为首页收藏本站|繁體中文

Project1

 找回密码
 注册会员
搜索
楼主: DeathKing
打印 上一主题 下一主题

[讨论] Ruby/RGSS Tips 每日一更 [技术区的版聊帖?]

  [复制链接]

Lv1.梦旅人

梦石
0
星屑
61
在线时间
24 小时
注册时间
2008-8-5
帖子
1924
94
发表于 2011-4-19 01:07:29 | 只看该作者
本帖最后由 紫苏 于 2011-4-19 01:16 编辑

`Module#undef_method' 是一个值得注意的方法。它的作用是将一个方法从方法分派的任务中移除,使得调用该方法者收到一个 `NoMethodError' 异常(即 `obj.respond_to? :method => true')。然而,`undef_method' 并非是把方法彻底从类结构中移除了,它仅仅是将以符号表示的方法名所标识的方法标记为“未定义”,使得解释器在通过方法分派、反射等机制寻找这个方法时会立即抛出异常。这就逻辑蕴含了另一个事实:哪怕基类或是 mixed-in 模块有同名的方法,在派生类的同名方法被 `undefine_method' 处理后,也不会尝试进行向上搜寻的方法分派。

`Module#undef_method' 还有一个家族成员——`Module#remove_method'。它彻底从当前模块(即 `remove_method' 的接收者。一个 `Module' 的实例)结构中移除一个方法的引用。如此一来,方法分派函数在派生类中找不到一个方法,就会尝试在基类中寻找。
  1. class Base
  2.   def bar
  3.     p :'base bar'
  4.   end
  5. end

  6. class Derivation < Base
  7.   def bar
  8.     p :'derivation bar'
  9.   end
  10. end

  11. d = Derivation.new

  12. class Derivation
  13.   remove_method :bar
  14. end

  15. d.bar                   # => :"base bar"

  16. class Derivation
  17.   undef_method :bar
  18. end

  19. d.bar                   # => NoMethodError
复制代码
可见 `remove_method' 后仍然能找到基类的 bar 方法,但 `undef_method' 后却不能。

再演示另外一个和 eigenclass (Ruby 单例类)有关的例子:

  1. obj = Object.new

  2. def obj.foo
  3.   p self
  4. end

  5. p obj.respond_to? :foo  # => true

  6. class << obj
  7.   undef_method :foo
  8. end

  9. p obj.respond_to? :foo  # => false

  10. Marshal.dump(obj)       # => error
复制代码
可以发现,仅仅是 `undef_method' 并不会移除 eigenclass 中的 eigenmethod(单例方法),所以它不能被 `Marshal' 模块 dump。当我们把 `undef_method' 替换为 `remove_method' 后,就可以 dump 了。

在方法被标记为未定义或彻底移除之前通过反射获取的该方法的 `Method' 对象,在之后仍然能正常运作:
  1. class Klass
  2.   def foo
  3.     p :'Klass#foo'
  4.   end
  5. end

  6. obj = Klass.new

  7. def obj.bar
  8.   p :'obj.bar'
  9. end

  10. m_foo_unbound = Klass.instance_method :foo
  11. m_foo = obj.method :foo
  12. m_bar = obj.method :bar

  13. class Klass
  14.   remove_method :foo
  15. end

  16. class << obj
  17.   remove_method :bar
  18. end

  19. p obj.respond_to? :foo        # => false
  20. p obj.respond_to? :bar        # => false

  21. m_foo_unbound.bind(obj).call  # => :"Klass#foo"
  22. m_foo.call                    # => :"Klass#foo"
  23. m_bar.call                    # => :"obj.bar"
复制代码
这同时也演示了方法的绑定和方法分派相互独立的特性。

最后,Ruby 还提供了一个语法糖 `undef' 以更简洁的语法(后面可以跟上一个纯粹的标识符,而无须符号或是其它字面值,类似与 `alias' 这个语法糖)调用了和 Module#undef_method 相同的实现。`undef' 是 Ruby 的关键字。
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
110
在线时间
953 小时
注册时间
2007-4-25
帖子
805
93
发表于 2011-4-15 04:29:55 | 只看该作者
http://ideone.com/

这是一个在线试玩 Ruby 的 Web 接口,省去了编译一份本地 Ruby 拷贝的工作。它使用的 Ruby 解释器版本是 1.9.2。
[email protected]:~> repeat 1 fortune
Matz is nice, so we are nice.
回复 支持 反对

使用道具 举报

Lv2.观梦者 (管理员)

八云紫的式神

梦石
0
星屑
549
在线时间
1243 小时
注册时间
2008-1-1
帖子
4282

烫烫烫

92
发表于 2011-4-8 07:57:58 | 只看该作者
Ruby命名参数

在设计一个大型库的时候,由于一个方法传递的参数可能很多,而参数默认值会有顺序的限制,如果我们要传递比较靠后的一个参数的值,那么就要把前面的一起传递进去,不太方便,这时我们希望能直接指明要传递哪个参数

Ruby没有原生的命名参数,但是可以使用Hash传递时的语法糖来达到类似命名参数的效果

例如我们想创建一个Window类(与RM的不完全相同,只是举例),在初始化时可以提交很多值,其中x,y,w,h是必填,然后还有些z, windowskin等属性
  1. class Window
  2.   def initialize(x, y, width, height, params)
  3.     self.x = x
  4.     self.y = y
  5.     self.width = width
  6.     self.height = height
  7.     self.z = params[:z] if params[:z]
  8.     self.windowskin = params[:windowskin] if params[:windowskin]
  9.   end
  10. end
  11. @window = Window.new(0, 0, 100, 100, :windowskin => "window")
复制代码

点评

->DK,函数里num.is_a?(Fixnum)可以么? 参数*arg,就能用*arg[x]。(不过还是Hash好用些...)  发表于 2011-4-15 14:45
@DK 有一定的意义,相当于有了多重分派(见本主题之前某贴)的好处。但实际上 Ruby 的反射以及灵活的参数列表足矣,无须进一步复杂化使解释器实现  发表于 2011-4-15 04:27
->DK 我记得在看The Ruby Way的时候提到过一个库,实现契约式设计的,在方法开头加入对参数的验证,不只是能验证类型 还能限制范围assert a, Positive之类   发表于 2011-4-9 07:06
->D7 不用*,最后一个是个Hash对象  发表于 2011-4-9 07:04
def initialize(x, y, width, height, *params) ?  发表于 2011-4-8 23:31
rm for linux(wine)制作中,期待夏娜SAMA能实现到webrm上
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
110
在线时间
953 小时
注册时间
2007-4-25
帖子
805
91
发表于 2011-4-3 20:21:29 | 只看该作者
我曾在这一贴中给出过一个深层数组克隆的方法:
http://rpg.blue/forum.php?mod=viewthread&tid=131787

然而,这个方法并不好。Object#clone 的协议有很多部分,而克隆对象成员只是其中之一,其它部分还包含对象的污染状态的复制等。我们重写了 clone 方法,就忽略了原本 clone 的额外的工作。

我们如果只是想进行深层克隆成员,那可以重写 initialize_copy 这个私有的实例方法,它可以被仅仅当作是克隆协议中负责成员克隆的部分。每当 Object#clone 或 Object#dup 被调用时,它们都会回调 initialize_copy 这个方法进行复制构造。所以,initialize_copy 就相当于 C++ 的复制构造函数。
  1. class Array
  2.   def initialize_copy(anArray)
  3.     for i in 0...anArray.size
  4.       self[i] =
  5.       begin
  6.         anArray[i].clone
  7.       rescue TypeError
  8.         anArray[i]
  9.       end
  10.     end
  11.   end
  12. end

  13. foo = [ 1, [ 1, 2 ], 3, [ 4, 5 ] ]
  14. bar = foo.clone

  15. bar[0] = 2
  16. bar[1][0] = 0xffff

  17. p foo, bar
复制代码
这是 Array 的深层克隆。重写 initialize_copy 前,bar[1] 被变异的同时也变异了 foo[1]。

一个泛用于拷贝所有实例变量的例子:
  1.   def initialize_copy(aKlass)
  2.     aKlass.instance_variables.each do |variable_name|
  3.       instance_variable = instance_variable_get(variable_name)
  4.       begin
  5.         instance_variable = instance_variable.clone
  6.       rescue TypeError
  7.       end
  8.       instance_variable_set(variable_name, instance_variable)
  9.     end
  10.   end
复制代码
这里是利用了 Ruby 强大的元编程能力。

点评

后面这一段A走了^ ^ 有时候想复制数据库某对象.就去重写该类的clone.一写就一大篇.还贼累= =...  发表于 2011-4-19 10:32
[email protected]:~> repeat 1 fortune
Matz is nice, so we are nice.
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
61
在线时间
24 小时
注册时间
2008-8-5
帖子
1924
90
发表于 2011-4-2 17:11:36 | 只看该作者
本帖最后由 紫苏 于 2011-4-2 17:13 编辑

Ruby 是一个发散性很强的语言——同一个问题,通常有继承自众多程序语言的不同风格的解法,这使得有着各种程序语言背景的程序员在使用 Ruby 的时候都能有似曾相识之感。

Perl 的默认变量就是一个例子。Ruby 内置了不少全局变量,它们的语意等同于 Perl 中的默认变量的概念,比如默认字符串分隔符。今天我们介绍 `$/' 这个被称为输入记录分隔符的默认变量。

很多 Ruby 内置的和输入有关的辅助子程序都使用了 $/ 作为默认的输入分割符,比如 String#each_line 方法。

  1. #coding: GBK

  2. <<-ENDS_HERE
  3. 上.虞.县.
  4. 祝.家.庄.
  5. 玉.水.河.滨
  6. 有.一.个.祝.英.台
  7. ENDS_HERE
  8. .each_line { |c| p c }
复制代码
输出:
"上.虞.县.\n"
"祝.家.庄.\n"
"玉.水.河.滨\n"
"有.一.个.祝.英.台\n"

这段程序把我们人类语言中“台词的每一行”打印了出来,这是由于 $/ 的默认值是 "\n"。如果我们在开头加一段代码改变 $/ 的值:
  1. $/ = '.'
复制代码
那么输出就会变为:
"上."
"虞."
"县."
"\n祝."
"家."
"庄."
"\n玉."
"水."
"河."
"滨\n有."
"一."
"个."
"祝."
"英."
"台\n"

这是由于 each_line 使用了 $/ 这个默认的输入记录分隔符,发现它的值是一个小圆点,所以就将小圆点当作了“每一行”的分隔符。这里的“每一行”的语意是我们定义的。

实际上 each_line 接受一个参数,参数默认值是 $/。我们可以通过传递一个实际参数来覆盖 $/:
  1. each_line("\n") { |c| p c }
复制代码
这样一来,无论 $/ 的值是什么,each_line 都会将 "\n" 当作分隔符。

类似的辅助方法还有很多,比如 IO#gets、IO#readlines 等输入方法,他们几乎都是将第一个参数作为分隔符,并设置其默认值为 $/。

最后,$/ 还有一个同义变量——$-0。

点评

ENDS_HERE 是 here document 的分隔单词,本主题某楼曾提过。Ruby 1.9 和 1.8 词法分析器有差异,我用的是 1.9。用双引号也可,但为了演示效果仍需要保留 \n。  发表于 2011-4-2 19:31
RM,RGE用这不明物ENDS_HERE出错.我认为用字符串""代替即可. 每行最后加"\"可消除"\n", 能消除"\n"又无同一的其他符号在最后且做到第一个输出效果?   发表于 2011-4-2 17:55
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
110
在线时间
953 小时
注册时间
2007-4-25
帖子
805
89
发表于 2011-3-26 15:25:56 | 只看该作者
  我们曾经多次提到过一个术语——全局解释器锁(Global Interpreter Lock,下简称 GIL)。GIL 是一个通用的术语,而 Ruby 1.9 的开发员似乎又赋予了 Ruby 1.9 的 GIL 另一个特有的名称——Giant VM Lock,硬翻为中文就是“巨型虚拟机锁”。
  在官方和其它一些 C/C++ 的 Ruby 实现(如 Rubinius),以及其它有着相似线程模型的动态类型语言实现(如 CPython)中都存在着 GIL。顾名思义,它是被集成在解释器核心、为解释器量身打造的一个全局的互斥锁,用来保护解释器内部的共享资源。
  虽然 CRuby 解释器的核心部分是线程安全的,但这并不代表本地扩展库提供的代码也是线程安全的(当然,编写扩展的人可以刻意地去写出线程安全的代码)。当我们使用标准库、第三方 Gem 时,我们很多时候都是在使用包含了线程不安全代码的本地扩展,而这些本地扩展多少要访问一些解释器核心的共享资源。一旦线程不安全代码与解释器内核在没有任何线程安全措施的情况下同时访问这些资源,就可能发生各式各样的多任务问题,尤其是竞争条件。这些问题使得我们的程序充斥着奇怪的八阿哥却又极其难以调试,所以我们迫切地需要一个措施来实现线程安全。
  通常保证线程安全性有四种途径:
  • 设计可重入的子程序
  • 使用线程局部存储
  • 仅使用原子操作
  • 多任务同步(引入互斥锁)
  然而,前三种途径并不能解决 Ruby 解释器的资源分配问题。解释器的共享资源对于一个解释器实例(解释器进程)来说具有全局性。既然解释器核心和本地扩展都需要变异全局静态的数据,那么即便解释器核心可重入,本地扩展仍然可以在并发时变异这些数据,使得解释器核心代码线程不安全。这也强调了一点:可重入并不意味着线程安全。由于涉及到共享资源,仅仅使用第二种途径的线程局部存储自然也是不够的。原子操作的定性和底层平台具体的(虚拟或物理)机器指令有关,对于一个需要跨平台的解释器实现来说,依赖原子操作而实现并发并不是一个好习惯。最后我们只剩下通过互斥锁设定一个内存屏障,建立临界区这个方案。
  同步多任务也可分为细加锁(Fine-grained locking)和粗加锁(Coarse-grained locking)两种加锁方案。细加锁是一种高密度加锁,它在所有和共享资源有关的结构上分别加锁(这些锁相互独立);粗加锁则是一种低密度加锁,它使用一个被所有结构共享的全局锁。
  假设某组织一幢办公大楼,有若干工作人员和若干工作室,工作人员需要按工作室的顺序进入各个工作室工作,而从当前工作室出来到进入下一个工作室之间的这段时间他们也有一些别的任务需要完成。细加锁,就好比这些工作人员一旦进入其中一个工作室就将其门锁住,直到自己工作结束,再解锁出门。这时可能有若干工作人员为了进入某个工作室而被迫等在门外,但也可能有若干工作人员正在完成不需要在工作室中进行的任务(即前文所说的从当前工作时出来到进入下一个工作室之间需要完成的任务)。在另一方面,粗加锁就好比工作室并没有锁,但整个办公大楼有一道大锁,一旦有一个工作人员进入办公大楼就锁住大楼入口,其它任何人都不得进入。每一个工作人员进入后可以自由工作 15 分钟,之后解锁走出办公大楼,让下一个工作人员进入并工作 15 分钟,如此反复。
  这里的工作人员就相当于线程,而工作室则是有着共享资源的临界区,办公大楼好比是整个进程。显然,较之粗加锁,细加锁有更高的并发性,有更多的工作人员可以在同一时刻工作。然而,细加锁在工作人员每次出入工作室时都多了一道解锁、加锁的程序。试想该组织只有一个工作人员,他独自一人在办公大楼中自是通行无阻,也无人和他争夺工作室,又何须频繁加锁解锁?这在现实世界中是举手之劳,在某些语言实现(比如曾经依赖于引用计数的 CPython 垃圾回收器)中却会带来巨大的开销。因此,细加锁会降低单线程程序的执行效率,提高多线程程序的执行效率,而粗加锁反之。
  想必看官业已猜到,粗加锁的这把锁,就是我们的话题——GIL。Ruby 语言的创始人 Matz 在他的 MRI 实现中使用的是 GIL 进行粗加锁。他之所以做出这个抉择,无非是为了不用考虑本地 Ruby 扩展的线程安全问题,以及提高单线程程序的执行效率。此举是否得当当然也是可商榷的。有些人宁愿在写扩展的时候自行考虑线程安全问题,也不愿为了代码简易而丢失效率。而从长远来看,程序迟早将全面步入并发计算领域,为了单线程执行效率而牺牲多线程执行效率的意义似乎越来越小了。
  Ruby 1.8 内置的 Thread 类使用的是绿色线程,而并非本地线程。Ruby 1.8 的解释器通过模拟本地 OS 的排程机制实现了 Ruby 层线程之间的周期性切换。因此,自始至终每个 Ruby 解释器进程都只有一个真正的用于求值的本地线程(不包含解释器的辅助线程)。哪怕有再多的 CPU 内核,在 Ruby 1.8 中也绝不可能实现真正的并发。更甚的是,当你调用某个外部的耗时函数时(比如进行阻塞 Socket),由于调用线程是唯一的一个负责绿色线程调度的本地线程,整个解释器进程都会因之而阻塞,Ruby 层的绿色线程自然也会尽数僵死。出于这两点考虑,Ruby 1.9 的 Thread 类使用了本地线程。然而,由于 GIL 的存在,两个 Thread 的实例仍然不能真正的并发运行。既然如此,将绿色线程替换为本地线程的意义何在呢?
  首先,绿色线程的调度是在用户空间中管理的,在很多情况下下效率不及由 OS 在内核空间中管理的本地线程;其次,本地线程可以解决解释器进程整体阻塞的问题。Ruby 1.9 默认将部分耗时运算(如 Bignum 的乘法)分配到了一个本地线程中运行,并在进行该运算时暂时释放 GIL,直到运算结束再重新收回 GIL。在 GIL 被释放的这段时间里,其它 Ruby 层的线程就可以运行,那么在多核 CPU 的环境下,即便很短暂,也实现了真正意义上的并发。在写本地 Ruby 扩展的时候,用户可以调用 rb_thread_blocking_region 这个函数来进行可能导致阻塞的操作,其内部其实就是封装了一个释放并收回 GIL 的过程。
  为了科学严谨性,我们最后还要强调一个事实,那就是采用 GIL 只是一个实现细节而并非语言特性。比如,同样是 Ruby 语言,基于 Sun JVM 的 JRuby 就不需要 GIL,因为它在底层依赖于有着自己的独特线程模型的 Java 虚拟机。Sun JVM 并不依赖于 GIL 的保护,相反它依赖于细加锁,这和现代化的 GC、高效的 JIT 乃至于整个虚拟机的复杂度都是密切相关的,这也是为什么 Sun JVM 的性能能得到公众的认可。
[email protected]:~> repeat 1 fortune
Matz is nice, so we are nice.
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
61
在线时间
24 小时
注册时间
2008-8-5
帖子
1924
88
发表于 2011-3-23 10:56:55 | 只看该作者
本帖最后由 紫苏 于 2011-3-23 11:05 编辑

将对表达式的求值推迟到真正需要其值之时的行为被称为惰性求值。惰性求值在基于表的函数式语言(如 Haskell、Lisp 及其派生语言)中尤其有用,它使得在不产生死循环的情况下定义无限表成为了可能。
  1. def i
  2.   5
  3. end

  4. def j
  5.   3
  6. end

  7. res = if true then i else j end
复制代码
这是一段 Ruby 代码,最后一行是命令式语言中常见的一种惰性求值。此处,只有 i 和 j 的其中一个最终会被求值,而永远不会出现他们同时被求值的情况。然而,如果把最后一行替换为:
  1. def fn(pred, u, v)
  2.   if pred then u else v end
  3. end

  4. res = fn true, i, j # => 5
复制代码
那么,i 和 j 都会预先被求值,然后才传递给 fn。这被称为热情求值及早求值
在 Ruby 中,和大部分命令式语言一致的 if ... then ... else ... 以及函数等结构都拥有惰性求值的特性,而同样是在语言层被支持的块、闭包、纤程和线程亦是如此。

本主题 37 楼曾介绍过 Ruby 1.9 的纤程,其用到的例子程序中的纤程是一个生成 Fibonacci 序列的工人纤程。实际上,这个工人纤程就相当于基于表的函数式语言中的一个无限 Fibonacci 表,程序只在需要序列中某个 Fibonacci 数的时候才进行求值,否则生成一个无限表将会产生死循环,从而导致 OOM。

线程和纤程红花绿叶是一家,在惰性求值这一点上是没有差别的。

闭包则是一个有趣的实例——

  1. fib = lambda do |n|
  2.   case n
  3.   when 1, 2
  4.     1
  5.   else
  6.     fib.call(n - 1) + fib.call(n - 2)
  7.   end
  8. end

  9. fib.call(6) # => 8
复制代码
在 fib 还正在被定义的时候,竟然也可以引用 fib 来定义它本身。在数学中,这是很常见的递归定义,而惰性求值则使得这一数学技巧在程序语言的世界得到了完美的演绎。当然,同样的结构也可以由函数来完成,但 Ruby 的函数并非一级函数,并不能像 Proc 一样被当作闭包绑定到一个局部变量上。这使得这里的赋值语句尤为显眼,更能体现出惰性求值的特性。倘若这里不是闭包,而是用了如 a = a + 1 这样的语句,且 a 在之前又没有定义,那自然就会发生异常了。

布尔逻辑运算符的短路特性,有时也被称为惰性求值,因为它实际上也是 if ... then ... 结构。逻辑或运算时,如果对左边的运算元求值的结果是真,那么就不会继续求右边的运算元的值了。

与惰性求值相对的热情求值,在 Ruby 中也有很多实例。比如,Ruby 的所有字面值,都是被热情求值的。本主题 65 楼曾提到了正则表达式在词法分析时便已进行求值,那就是一种热情求值,其余字面值也均是在词法分析时就构建了相应的对象。另外一个比较明显的例子是字符串的内插求值:
  1. $bar = :zhangsan
  2. str = "#$bar"
  3. $bar = :lisi
  4. p str # => zhangsan
复制代码
此处在字符串中内插了 $bar 这个变量,然而由于是热情求值,在字符串出现后才改变 $bar 的值,为时已晚。
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
110
在线时间
953 小时
注册时间
2007-4-25
帖子
805
87
发表于 2011-2-24 03:57:55 | 只看该作者
如果 Ruby 源文件中包含 __END__ 这个指令,那么在其后的内容都会被当作额外的文本数据,解释器不会对其进行求值。其内容会被初始化到一个 File 对象所表示的流中,并赋给 DATA 这个全局常量。
  1. #coding: GBK

  2. DATA.each { |line| puts line }

  3. __END__
  4. 那是我日夜思念深深爱着的人呐
  5. 到底我该如何表达
  6. 她会接受我吗
  7. 也许永远都不会跟她说出那句话
  8. 注定我要浪迹天涯
  9. 怎么能有牵挂
  10. 梦想总是遥不可及
  11. 是不是应该放弃
  12. 花开花落又是雨季
  13. 春天啊你在哪里
  14. 青春如同奔流的江河
  15. 一去不回来不及道别
  16. 只剩下麻木的我没有了当年的热血
  17. 看那漫天飘零的花朵
  18. 在最美丽的时刻凋谢
  19. 有谁会记得这世界她来过
  20. ……
复制代码
这里是在源文件中嵌入了一段歌词,并通过 Ruby 把歌词打印了出来。

__end__ 指令必须独自占一行,前后不能有别的东西。它的语意是“程序末尾”。

点评

DATA还可以通过回溯指针读取到__END__之前的代码部分  发表于 2011-3-1 09:30
[email protected]:~> repeat 1 fortune
Matz is nice, so we are nice.
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
61
在线时间
24 小时
注册时间
2008-8-5
帖子
1924
86
发表于 2011-2-21 10:33:54 | 只看该作者
Ruby 的块有 do ... end 以及 { ... } 两种语法。国际惯例是:如果块的内容可以在一行写完就使用 { ... },否则使用 do ... end。

  1. 16.times { |i| p i }

  2. 16.times do |i|
  3.   case i
  4.   when 0
  5.     # ...
  6.   when 1
  7.     # ...
  8.   when 2
  9.     # ...
  10.   end
  11. end
复制代码

点评

两者优先级不一样。比如method_a method_b &block。大括号会结合到method_b,而do end会先执行method_a method_b,再传块进去  发表于 2011-3-1 09:32
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
110
在线时间
953 小时
注册时间
2007-4-25
帖子
805
85
发表于 2011-2-20 01:06:59 | 只看该作者
本帖最后由 苏小脉 于 2011-2-20 01:11 编辑

Ruby 1.9.2-p180 前几天发布了,主要修复是 FileUtils 的一个漏洞。

SVN tag:
http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/tags/v1_9_2_180/

Change log:
http://svn.ruby-lang.org/repos/ruby/tags/v1_9_2_180/ChangeLog

下载:
http://ftp.ruby-lang.org/pub/ruby/1.9/ruby-1.9.2-p180.tar.bz2
  SIZE:    8815756 bytes
  MD5:    68510eeb7511c403b91fe5476f250538
  SHA256:
06520c4d4b4512d08000f7dfff11d1fabc1d458c3c289c76a2f1ddb7f5a03f4d

http://ftp.ruby-lang.org/pub/ruby/1.9/ruby-1.9.2-p180.tar.gz
  SIZE:   11158935 bytes
  MD5:    0d6953820c9918820dd916e79f4bfde8
  SHA256:
9027a5abaaadc2af85005ed74aeb628ce2326441874bf3d4f1a842663cde04f4

http://ftp.ruby-lang.org/pub/ruby/1.9/ruby-1.9.2-p180.zip
  SIZE:   12574217 bytes
  MD5:    cf2726e9faa1b84ba798693e649067ab
  SHA256:
65fa1b6b705f6e99a6ff2ae9e122055235525d5577506e1ee8dd3abdaa639961

点评

ruby-lang.org 是手动更新的,有时可能是 Yugui 忘了。直接看 SVN 的 trunk 就保证是最新的。  发表于 2011-2-20 10:32
居然没出现在Ruby-lang的RSS源里,何等师太= =  发表于 2011-2-20 09:03
有些是 BUG,有些是调整之类的,总之是打了这么多个补丁。  发表于 2011-2-20 01:39
修复了42(180-138)漏洞?  发表于 2011-2-20 01:10
[email protected]:~> repeat 1 fortune
Matz is nice, so we are nice.
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册会员

本版积分规则

拿上你的纸笔,建造一个属于你的梦想世界,加入吧。
 注册会员
找回密码

站长信箱:[email protected]|手机版|小黑屋|无图版|Project1游戏制作

GMT+8, 2024-4-27 11:12

Powered by Discuz! X3.1

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表