Hi all, me again bringing a new implementation idea for the Generators API
in [functor], and looking forward to some thoughts on this :-) There is a separate branch for this issue [1], and here's what has been done. - Split Generator interface into Generator interface and LoopGenerator (abstract class). IMO, this will help in modularization (see this discussion [2]) in the Generators API, as the stop() method and the wrapped generators, for instance, had been added because of the generators created for handling execution flow control (e.g.: GenerateWhile, UntilGenerate, etc). - Moved LoopGenerator and its implementations under the newly created org.apache.commons.functor.generator.loop package. - Moved IntegerRange and LongRange from org.apache.commons.functor.generator.util to the newly created org.apache.commons.functor.generator.range package. - Created a Range API, with a Range interface, a Ranges helper interface and some implementations (including existing IntegerRange and LongRange, and new ones like DoubleRange, FloatRange and CharacterRange). - Added steps different than 1 to Ranges (not the generator interface, as this is related only to ranges). - The Ranges implemented are all Generators too, what is very convenient, as you can use Ranges to both define intervals and/or execute a procedure for each of its elements. I've wrote a sample code using the existing Generators API [3] and wrote the same code for the new Generators API [4]. The API is compatible, but as some packages changed, you have to update existing code (but as [functor] hasn't been released yet, it shouldn't be a problem I believe :-). Both codes produce the same output too (0 1 2 3 4 5 6 7 8 9 ). And here's an example [5] of creating Ranges and using them as Generators. More examples can be found in the tests for the Generator and the Range API's. I've updated the examples page and added tests. I've also updated the parent pom to 26, but as this is not related to the FUNCTOR-14 issue, we can drop this part when merging the code. I'll merge the changes to trunk if everybody thinks this new implementation is better than the current one. A side note: PHP recently got generators too [6], and an interesting thing that I noticed in their Wiki was the discussion about callback functions. After reading the discussion, for me it looks like [functor] generators API is more similar to callback handler. Differently than the Python and PHP implementations with the yield statement. Thank you in advance! [1] https://svn.apache.org/repos/asf/commons/proper/functor/branches/generators-FUNCTOR-14 [2] http://markmail.org/message/nymsk7l64aj4csxi [3] https://gist.github.com/3747204 [4] https://gist.github.com/3747207 [5] https://gist.github.com/3747224 [5] https://wiki.php.net/rfc/generators Bruno P. Kinoshita http://kinoshita.eti.br http://tupilabs.com >________________________________ > From: Matt Benson <gudnabr...@gmail.com> >To: Bruno P. Kinoshita <brunodepau...@yahoo.com.br> >Cc: Commons Developers List <dev@commons.apache.org> >Sent: Wednesday, 6 June 2012 9:56 AM >Subject: Re: [functor] Patch for FUNCTOR-14, new Generators and Ranges > >On Tue, Jun 5, 2012 at 11:48 PM, Bruno P. Kinoshita ><brunodepau...@yahoo.com.br> wrote: >> Hi Matt, >> >> >>> Would there be a type of Range that could not be turned into a >>> Generator given a compatible Step parameter? If not, we could define: >>> >>> interface Range<T, S> { >>> ... >>> Generator<T> toGenerator(S step); >>> } >>> >>> This way, Range itself does not contain a step, but still maintains >>> control over how a step is used to create a generator. >> >> I can't think of any type that could not be turned into a generator given >> the step parameter. But if a range has no step, I think we would have to >> remove the isEmpty(), contains(), containsAll() methods from range >> implementations, as using steps higher than 1, we need to use the step value >> to check if a range is empty or contains a certain element (e.g.: integer >> range (1, 2], step 3, check if contains(2) or isEmpty()). >> > >My thought was that by decoupling a Range from a step, you use only >the bound types/values to determine inclusion of a given value. If a >Generator is created from (1, 2] with step 3, then that Generator will >only return 1, but that doesn't reflect on the Range, IMO. > >Matt > >> >>> Either way, I like the notion that a Range is its own type that just >>> *happens* to either provide access to, or an implementation of, >>> Generator. >> >> +1, let it provide access or be an implementation of Generator. In case we >> do the latter case, I believe isEmpty(), contains() and other methods using >> the step value would be doable. >> >> Regards, >> >> >> Bruno P. Kinoshita >> http://www.kinoshita.eti.br >> http://www.tupilabs.com >> >> On 06/05/2012 11:52 PM, Matt Benson wrote: >>> >>> Hi, Bruno. Likewise, answers inline: >>> >>> On Tue, Jun 5, 2012 at 9:32 PM, Bruno P. Kinoshita >>> <brunodepau...@yahoo.com.br> wrote: >>>> >>>> Hi Matt! >>>> >>>> Thanks for your response! Answers added inline. >>>> >>>> >>>>> 1. Why are a Range's type and step-type potentially different >>>>> (different type variables, etc.)? >>>> >>>> >>>> When I started writing this patch, the range's type and step-type were >>>> the >>>> same (i.e. the interface had only one generics type,<T>), but then I >>>> created the CharacterRange and it didn't work because its range type is >>>> Character and its step-type is Integer (same would happen for a >>>> DateRange). >>> >>> >>> I see; good point. >>> >>>> >>>> What do you think? Maybe with some generics magic or with a different >>>> approach we could remove the step-type? (I would be +1 for this) >>>> >>>> >>>>> 2. Why, if it is a Generator's responsibility to generate items >>>>> subsequent to the lower endpoint, is the step part of the range at >>>>> all? Based on [1], which definition of "range" are we attempting to >>>>> represent? >>>> >>>> >>>> In google guava and java-yield a range is a generator, as it was in >>>> [functor] too (this patch removes the old IntegerRange, a generator of >>>> Integers). >>>> >>>> [functor] has generators that don't require steps (GenerateWhile, >>>> WhileGenerate, UntilGenerate, etc). I think random generators wouldn't >>>> use >>>> steps too (e.g.: RandomIntegerGenerator, USPhoneNumberGenerator, >>>> UUIDGenerator, PrimeNumberGenerator). >>>> >>>> The initial idea of the Range interface, was to have similar behavior as >>>> commons-lang's Range [1], plus being able to define steps and have the >>>> actual process (the yield) being executed by an external agent, a >>>> generator. >>>> In the end, I think the of the Range in my patch would be more like an >>>> Interval [2]?. >>>> >>>> >>>>> The current code seems to implement definition 2 and >>>>> *part* of definition 3, deferring the rest to a corresponding >>>>> Generator. >>>> >>>> >>>> I couldn't have said it better :-) >>>> >>>> >>>>> Settling the question of whether [functor]'s Range is a >>>>> "2-range" or also a "3-range" would seem to dictate our action: do we >>>>> move the step to the generator, or do we make Range calculate each >>>>> item (in which case would it be simpler for Range to implement >>>>> Generator)? >>>> >>>> >>>> After reading your considerations, I now think that it would be better to >>>> maintain the current approach (Range implements a Generator) and try to >>>> implement generators for double, float and character using the actual >>>> interfaces and try to use steps. What do you think? >>> >>> >>> Would there be a type of Range that could not be turned into a >>> Generator given a compatible Step parameter? If not, we could define: >>> >>> interface Range<T, S> { >>> ... >>> Generator<T> toGenerator(S step); >>> } >>> >>> This way, Range itself does not contain a step, but still maintains >>> control over how a step is used to create a generator. >>> >>>> >>>> Do you think we should keep the naming standard IntegerRange/LongRange, >>>> or >>>> change them to IntegerGenerator/LongGenerator? >>> >>> >>> Either way, I like the notion that a Range is its own type that just >>> *happens* to either provide access to, or an implementation of, >>> Generator. >>> >>> br, >>> Matt >>> >>>> >>>> Thank you for reviewing my patch and for the interesting questions! I'm >>>> no >>>> FP expert either, feel free to suggest different ideas, no hard feelings >>>> :) >>>> >>>> [1] >>>> >>>> http://svn.apache.org/viewvc/commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/Range.java?view=markup >>>> [2] http://en.wikipedia.org/wiki/Interval_(mathematics) >>>> >>>> Bruno P. Kinoshita >>>> http://www.kinoshita.eti.br >>>> http://www.tupilabs.com >>>> >>>> >>>> On 06/05/2012 12:08 PM, Matt Benson wrote: >>>>> >>>>> >>>>> Hi, Bruno! >>>>> >>>>> I have some questions: >>>>> >>>>> 1. Why are a Range's type and step-type potentially different >>>>> (different type variables, etc.)? >>>>> 2. Why, if it is a Generator's responsibility to generate items >>>>> subsequent to the lower endpoint, is the step part of the range at >>>>> all? Based on [1], which definition of "range" are we attempting to >>>>> represent? The current code seems to implement definition 2 and >>>>> *part* of definition 3, deferring the rest to a corresponding >>>>> Generator. Settling the question of whether [functor]'s Range is a >>>>> "2-range" or also a "3-range" would seem to dictate our action: do we >>>>> move the step to the generator, or do we make Range calculate each >>>>> item (in which case would it be simpler for Range to implement >>>>> Generator)? >>>>> >>>>> I am by no means an FP or any other type of expert, so feel free to >>>>> show me why I'm wrong on a given point! >>>>> >>>>> br, >>>>> Matt >>>>> >>>>> [1] http://en.wikipedia.org/wiki/Range_(computer_science) >>>>> >>>>> On Mon, Jun 4, 2012 at 11:59 PM, Bruno P. Kinoshita >>>>> <brunodepau...@yahoo.com.br> wrote: >>>>>> >>>>>> >>>>>> Hi all, >>>>>> >>>>>> I've finished a patch for FUNCTOR-14, regarding the Generators API in >>>>>> [functor]. I'd like to hear what others think about what was done >>>>>> before >>>>>> attaching the patch to JIRA: >>>>>> >>>>>> - Didn't change the Generator interface. Although I commented in the >>>>>> issue about removing the stop() and isStopped() methods and moving to a >>>>>> different interface, it would require a major refactoring, as many >>>>>> other >>>>>> generators are built upon this idea. >>>>>> >>>>>> - Created IntegerGenerator, LongGenerator, FloatGenerator, >>>>>> DoubleGenerator and CharacterGenerator. Didn't implement a >>>>>> DateGenerator as >>>>>> it would require more time and a discussion on how to use days, months, >>>>>> years, days of week, etc. >>>>>> >>>>>> - Introduced Ranges, with the following initial ranges: IntegerRange, >>>>>> LongRange, FloatRange, DoubleRange and CharacterRange. This API is >>>>>> quite >>>>>> similar to other existing APIs, with the difference that you can >>>>>> specify the >>>>>> step (like ranges in Matlab) >>>>>> >>>>>> - The generators that use numbers (there are many other generators, >>>>>> like >>>>>> GenerateWhile, GenerateUntil, etc) use ranges to create the series. The >>>>>> objects are created only when the generator is executed, calling a >>>>>> procedure. Like in python, but instead of retrieving the value with a >>>>>> 'yield' statement, we give a procedure to be executed using the value >>>>>> created. >>>>>> >>>>>> - Included tests to cover the changes. >>>>>> >>>>>> - Updated web site examples. >>>>>> >>>>>> All the tests passed, no checkstyle/pmd/findbugs errors. The character >>>>>> range/generator is a very simple, and there are some operations with >>>>>> double/float in the ranges and generators. I keep my code mirrored in >>>>>> github >>>>>> too, in case someone prefers reading it there >>>>>> https://github.com/kinow/functor. >>>>>> >>>>>> Let me know what you think about it :-) >>>>>> >>>>>> Thank you in advance! >>>>>> >>>>>> Bruno P. Kinoshita >>>>>> http://kinoshita.eti.br >>>>>> http://tupilabs.com >>>>>> >>>>>> >>>>>> --------------------------------------------------------------------- >>>>>> To unsubscribe, e-mail: dev-unsubscr...@commons.apache.org >>>>>> For additional commands, e-mail: dev-h...@commons.apache.org >>>>> >>>>> >>>>> >>>>> --------------------------------------------------------------------- >>>>> To unsubscribe, e-mail: dev-unsubscr...@commons.apache.org >>>>> For additional commands, e-mail: dev-h...@commons.apache.org >>>>> >>>> >>> >>> --------------------------------------------------------------------- >>> To unsubscribe, e-mail: dev-unsubscr...@commons.apache.org >>> For additional commands, e-mail: dev-h...@commons.apache.org >>> >> > >--------------------------------------------------------------------- >To unsubscribe, e-mail: dev-unsubscr...@commons.apache.org >For additional commands, e-mail: dev-h...@commons.apache.org > > > > --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@commons.apache.org For additional commands, e-mail: dev-h...@commons.apache.org