Ruby ruby 条件区间的问题

windwiny · 2013年01月07日 · 最后由 windwiny 回复于 2013年01月07日 · 3504 次阅读

vs = (1..9).to_a => [1, 2, 3, 4, 5, 6, 7, 8, 9]

v1 = vs.select { |n| if n==3..n==6 then 1 end } => [3, 4, 5, 6]

v2 = vs.select { |n| if n==2..n==16 then 1 end } => [2, 3, 4, 5, 6, 7, 8, 9]

v3 = vs.select { |n| if n==3..n==6 then 1 end } => [1, 2, 3, 4, 5, 6]

v1 和 v3 的区间条件是一样的, 但是结果不一样, v3 的输出值被 v2 的区间条件影响了, 为什么会这样?

我在 Irb 里面试的 v1 和 v3d 的结果一样呀,你是不是弄错了呀?

不会吧。实验是一样的。

没有这个可能性呀

我是用 1.9.3p362 版的, 确实有这个问题,用 p327 就正常

#4 楼 @windwiny

boolean range 的值和上下文相关的, 很容易出问题

!!(false..false) #=> false
!!(true..false)
!!(false..false) #=> true

所以已经不推荐了, 用 vs.select{ |n| (3..6).cover? n }

#5 楼 @luikore

你说 “boolean range 的值和上下文相关的, 很容易出问题” 这句话怎么理解? 有什么文档和书描述这个吗?

你用的也是 1.9.3p362 这个版本吧, p327 就没这个问题。

#6 楼 @windwiny 不管 p327 还是 p362, range 作为逻辑条件都是上下文相关的:

http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html

You can use a Ruby range as a boolean expression. A range such as exp1..exp2 will evaluate as false until exp1 becomes true. The range will then evaluate as true until exp2 becomes true. Once this happens, the range resets, ready to fire again

#7 楼 @luikore

这里还是有问题吧, 在不同的 select 块里,怎么还是相同的上下文,就看 ruby 以前版本和最新版本行为不一致,这也是 bug 吧?

#8 楼 @windwiny 不, 在代码里行为是一致的, 真正原因是 irb 的实现改了, 如果用 ruby 跑结果是一样的:

vs = (1..9).to_a

p(v1 = vs.select { |n| if n==3..n==6 then 1 end })
# => [3, 4, 5, 6]

p(v2 = vs.select { |n| if n==2..n==16 then 1 end })
# => [2, 3, 4, 5, 6, 7, 8, 9]

p(v3 = vs.select { |n| if n==3..n==6 then 1 end })
# => [3, 4, 5, 6]

#9 楼 @luikore

I 服了你,这都能发现。确实不是 ruby 解释器的问题,是 irb 的问题,pry 好像依赖 irb,也有问题。

需要 登录 后方可回复, 如果你还没有账号请 注册新账号