On 14-03-17, 18:19, Matthew K. wrote:
Firstly, let me preface by saying I’m not attacking. It’s an interesting
problem, I just don’t understand (and I’d like to).
Cool. I’m happy to discuss it. First, forget about iterating Fixnums.
Is that not just an array?
If you know the predetermined list of items, sure it could be an array.
How about we add the following constraints:
- You can’t know when to stop iterating until you fetch the last item.
- It’s prohibitive to prefetch all the items into an array first, and
then traverse it.
- The implementation to fetch the next item, and deciding where to stop
is handled differently for many different configurations and needs to be
passed in externally.
- The iterator needs to do some internal setup before/after yielding
each item.
repeater << num
repeater << num * 10
repeater << num * 100
# step 3:
repeater.each {...}
… except that, in this case, I was able to do it offline, because I
already know what 5, 510, and 5100 are (even though I wrote 100
… oops).
See, there’s too much assumed knowledge all in one place there. I need
to separate responsibilities into 3 places to hide complexity, and each
part knows its own role:
- Getting some external object that we start with (It’s not a simple
Fixnum 5)
- Defining how we need to iterate over it.
- Abstracting that iteration as a simple “each”
Parts 1 and 2 are somewhat related; they have some knowledge &
correspondence with each other but I want to extract a common interface
for the iteration part so it can apply to anything that’s passed in.
This is where my understanding falls down. Is there another actor in
this scenario that I’m missing? I think it would help me if you could
come up with another contrived example that shows how an array is
insufficient. Is the initial value actually a stateful creature that you
don’t want to mutate until calling #each ?
Correct, it is not a single class; it is stateful; stuff happens only
once yielded to each. You get 3 for 3!
yield @num * 100
end
end
What entices me to pass the value and the effective body of #each to
your utility class, instead of just doing it myself? What else do you add?
Your “each” is defined internally in your class. I need that logic to be
passed from a DSL block from a config file. How about this for a
hopefully more revealing example DSL:
repeat do |pages, remote_source|
loop do
pages << remote_source
break if remote_source.data.split("\n").size < 100
remote_source.query_params["page"] += 1
end
end
This is a single example of a data source. There are many like it, but
only some use HTTP with a page query. Another one might get the number
of pages from the remote source and use 1.upto(pg), or list some files
from FTP… it all depends and it’s impossible to hard-code the
iteration logic into my data Provider or its supporting Repeater class.
Make sense?
Andrew V.