Ranges are based upon comparisons of what is less than something else.
In fact, if I recall correctly, to generate an array (Range#to_a)
calls next on the start of the range until it reaches the end of the
range. With your range (3..0) it would go [3,4,5...Infinity], so ruby
opts to produce an empty array.
···
On 10/25/07, Just Another Victim of the Ambient Morality wrote:
> What i find strage about ranges is that:
> (0..3).to_a # => [0, 1, 2, 3]
> but
> (3..0).to_a # =>
I find this strange, as well...
Aside from breaking many lines of code, how bad would it be to change
it?
-------------------------------------------
Daniel Brumbaugh Keeney
Devi Web Development
Devi.WebMaster@gMail.com
-------------------------------------------
yes. the most obvious one is needing adjacent entries and/or
self-modification. something along the lines of
pixels.size.times do |i|
pixel = pixels[i]
left = pixels[i - 1]
right = pixels[i + 1]
if left.nil? and condition(right) or
condition(left) and condition(right) or
condition(left) and right.nil?
pixel = transformation left, pixel, right
end
end
What about #each_with_index for this case? Using pixels.size.times and
accessing each element by the yielded integer indexes explicitely
assumes that the index space is continuous - however, the same algorithm
using #each_with_index would only assume that each item yielded by it
has two adjacent neighbors.
min = [a.size, b.size].min
min.times do |i|
something_with a[i] and b[i]
end
which is to say iterating datasets in parallel.
yes there is zip - fantastic if you are into duplicating both datasets
in memory *and* are iterating over n=2 data structures but otherwise
useless.
Hmmm, are you sure that zip duplicates all the involved arrays even if
passed a block?
Yeah, that was dumb of me. That wasn't the point though. I was showing each_index() which was recreated above in two different ways.
James Edward Gray II
···
On Oct 25, 2007, at 12:28 PM, Joel VanderWerf wrote:
James Edward Gray II wrote:
On Oct 25, 2007, at 1:40 AM, Robert Klemme wrote:
Both range versions come in handy, for example, if you need to iterate through an array using an index counter then the triple dot is convenient because you do not need to to math:
for i in 0...ar.size
puts ar[i]
end
#times is an alternative here
ar.size.times do |i|
puts ar[i]
end
>> letters = (0..9).map { |i| (?a + i).chr }
=> ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j"]
>> letters.each_index do |i|
?> puts letters[i]
>> end
a
b
c
d
e
f
g
h
i
j
=> ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j"]
What was that example meant to show? Must be something other than this:
well, frankly, that example is made up but i have tons of image processing code that does that in spirit - the point is that using #each_with_index is going to give you errors: you cannot iterate using map/each/each_with_index *while* also modifying a datastructure - try this:
i certainly abstract that kind of code to yield the pixel and it's neighbors (it doesn't always have them near the edges of an image) but abstracting it will require both iteration by size *and* using random access unless the algorithm is read only. you can see http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ for example of how neighborhood iterators can generally be abstracted - my point is just that the this *type* of problem - iterating while modifying and looking at neighbors - requires an external iterator if one is using the 'obvious' solution.
What about #each_with_index for this case? Using pixels.size.times and
accessing each element by the yielded integer indexes explicitely
assumes that the index space is continuous - however, the same algorithm
using #each_with_index would only assume that each item yielded by it
has two adjacent neighbors.
--
we can deny everything, except that we have the possibility of being better. simply reflect on that.
h.h. the 14th dalai lama
well, frankly, that example is made up but i have tons of image
processing code that does that in spirit - the point is that using #each_with_index is going to give you errors: you cannot iterate using
map/each/each_with_index *while* also modifying a datastructure - try this:
i certainly abstract that kind of code to yield the pixel and it's
neighbors (it doesn't always have them near the edges of an image) but
abstracting it will require both iteration by size *and* using random
access unless the algorithm is read only. you can see http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ for example of
how neighborhood iterators can generally be abstracted - my point is
just that the this *type* of problem - iterating while modifying and
looking at neighbors - requires an external iterator if one is using the
'obvious' solution.
Fair enough. However, the code in question hasn't altered the array of
pixels itself, just the pixel values. It's true that you have to pay
more attention when adding and/or deleting items while iterating.
Hmmm, are you sure that zip duplicates all the involved arrays even if
passed a block?
pretty sure:
cfp:~ > ruby -e' p ObjectSpace.each_object(Array){}; p [4].zip([2]){
break ObjectSpace.each_object(Array){} } '
6
9
6 to start, create 2, zip makes one more = 9
It's sure to create arrays. Those ones that hold the corresponding
values from the original arrays, and only for the duration of the
current iteration. But if you zip two 100-element arrays, it won't
duplicate either simultaneously, it'll just create two-element arrays to
be passed to the block temporarily.