锁定老帖子 主题:inject的疑惑
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (1)
|
|
---|---|
作者 | 正文 |
发表时间:2007-02-27
[1,2,3].inject([]) do |a, item| puts a a << item end 按照ruby的手册,这段的含义是:给a赋初值[],然后对[1,2,3]数组的每个元素,把元素添加到a中。 那么,我的理解,输出应该为: [] [1] [1,2] 但是我错了,实际的输出是: 1 1 2 尤其是第一个1,真让我想去看看ruby的c源码了。 可是,下面这段: [1,2,3].inject(0) do |a, item| puts a a += item end 同样,我的理解,输出应该为: 0 1 3 这次我对了,实际的输出它怎么就是: 0 1 3 有人能告诉我为什么吗? 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2007-02-27
[1,2,3].inject([]) do |a, item| puts a a << item end 没问题啊,你把上面这段代码的puts换成p再看看吧: [1,2,3].inject([]) do |a, item| p a a << item end puts一个数组时它会一行输出一个元素。 |
|
返回顶楼 | |
发表时间:2007-02-28
是我理解错puts了。
引起这段程序的根源是我犯的另一个错,结果给我的提示信息让我误以为应该是那样输出。 谢谢! 不过,还是出道小题,看看我犯过的错还有多少人会同样犯。下面这段代码有什么问题: [1,2,3].inject([]) do |a, item| if item >=2 a << item end end |
|
返回顶楼 | |
发表时间:2007-02-28
dcaoyuan 写道 是我理解错puts了。
引起这段程序的根源是我犯的另一个错,结果给我的提示信息让我误以为应该是那样输出。 谢谢! 不过,还是出道小题,看看我犯过的错还有多少人会同样犯。下面这段代码有什么问题: [1,2,3].inject([]) do |a, item| if item >=2 a << item end end 这个block未返回值,下一次a就变成nil了 |
|
返回顶楼 | |
发表时间:2007-02-28
dcaoyuan 写道 是我理解错puts了。
引起这段程序的根源是我犯的另一个错,结果给我的提示信息让我误以为应该是那样输出。 谢谢! 不过,还是出道小题,看看我犯过的错还有多少人会同样犯。下面这段代码有什么问题: [1,2,3].inject([]) do |a, item| if item >=2 a << item end end 应该是这样吧: [1,2,3].inject([]) do |a, item| if item >=2 a << item else a end end |
|
返回顶楼 | |
发表时间:2007-02-28
对。不能遗漏else。
但是,如果用each: a = [] [1,2,3].each do |a, item| if item >= 2 a << item end end 就没有任何问题,这就是我觉得ruby不一致的地方,看上去比较一致的逻辑块,结果却很不一致。 如果是Erlang,就不可能犯这种错: lists:foldr( fun(Item, A) -> if Item >= 2 -> [Item|A]; true -> A end end, [], [1,2,3]) 这里,true -> A是必须的,否则编译无法通过。而且,选择foldr函数是很自然的,不太可能选择foreach来完成这个事,虽然也可以做到。基本上Erlang不太可能让你写出类似上面这种出错的句子。这也是我认为一门语言应该严谨的地方。 |
|
返回顶楼 | |
发表时间:2007-02-28
如果你这样就说ruby不一致,那ruby就太冤了。
首先,您这段代码 a = [] [1,2,3].each do |a, item| if item >= 2 a << item end end 本身已经有两处写错了,第一,each的block参数a会影响到外围的数组a;第二,上面的item永远被附于nil。 each的最基本用法你都写错了...... 再说each和inject本来就是功能完全不同的方法,使用上有所不同是完全正常的。 |
|
返回顶楼 | |
发表时间:2007-02-28
不好意思,写得太快了,copy/paste,没注意,应该是:
a = [] [1,2,3].each do |item| if item >= 2 a << item end end 我可能属于比较懒的:-) 不太喜欢脑筋转来转去,所以比较喜欢不太容易让我犯错的语言。 ruby可以用很多种方式作同一件事,这是双刃剑。 |
|
返回顶楼 | |
发表时间:2007-02-28
我觉的这并非ruby不一致的问题,inject与each本来就是功能完全不同的方法。
|
|
返回顶楼 | |
发表时间:2007-02-28
1) in ruby, "if" is an EXPRESSION, not STATEMENT. keep this in mind
2) checkout RDoc of "inject": enum.inject(initial) {| memo, obj | block } => obj enum.inject {| memo, obj | block } => obj Combines the elements of enum by applying the block to an accumulator value (memo) and each element in turn. At each step, memo is set to the value returned by the block. The first form lets you supply an initial value for memo. The second form uses the first element of the collection as a the initial value (and skips that element while iterating). 3) i guess this is what you were looking for: a = [1,2,3].select do |x| x >= 2 end |
|
返回顶楼 | |