On Wed, 2011-06-29 at 14:04 +0100, Maciej Piechotka wrote: > On Wed, 2011-06-29 at 13:11 +0200, Quikee wrote: > > Hi, > > > > I intended to write this for quite some time - I am sorry that it took so long. > > > > No problem. > > > I have looked at the implementation and proposal for "functional > > iterators" and I have some remarks and things I really don't like. > > > > - Implementation directly on iterator interface: Even if it is legal > > to do it in GObject I don't like that the interface contains the > > implementation and then you are forced to override it in your > > implementation just to do something different. This is for example > > also the reason for the existence of AbstractCollection and co. > > because neither I nor Didier did not want to put code into the > > interface. I hope you will also change this for the iterators. > > > > Well - possibly due to different background I like virtual method in > interfaces (i.e. like classes in Haskell). They allow to change > interface w/out breaking API (breaking ABI however). > > > - Stream function: Stream function is for me just a implementation > > detail how the functional iterators are implemented. I don't think it > > is wise to force it into the interface of iterator. They should be > > available but only as a special type of iterator or something similar > > that is just used as the implementation and hidden on the interface. I > > also don't think there will be a lot of people that will write its own > > functional operator anyway. I must also say that I don't like that > > stream operation as it is very hard to read what exactly it does and > > how it works. The performance might also be an issue as functional > > programming languages are heavily optimised for (tail) recursion and > > lambda but vala is not. Still if the stream operation is just regarded > > as a implementation detail I don't mind. > > > > The stream function was written for performance reason. The Vala does > not optimize the virtual calls at all so they perform slowly as Java or > C# would do. Vala have no static or dynamic type analysis and therefore > each call to interface goes through 1-2 jumps by function pointers. > > For exact numbers see: > > https://bugzilla.gnome.org/show_bug.cgi?id=645850#c4 > > It is written mostly for implemantators as it: > > - Allows to reuse of code across functions (like map etc.) therefore > making life of people implementing new combinators easier (i.e. Jurg, > Dider, mine, ...). I agree that it is small benefit and therefore it was > not in original spec. > - As a side effect it allows to implement all functional methods to be > implemented efficiently by just reimplementing forall and stream. As it > generally have huge impact (virtual calls are heavy in Vala, virtual > calls to interfaces via abstract classes are even more). > > As shown in the data I've linked it have the some constant overhead > (which quickly outperform other methods except .get for array). > > In short - it is implementation detail but important one from > performance POV (yes, I was surprised by benefits of forall). > > > - Call to iterator() before executing an functional operation is not > > elegant. Each collection could have functional operations directly > > accessible as well and just could delegate to the iterator when it is > > called. > > > > Hmm. +1? > > What about something like Stream interface from which both Collection > and Iterator inherit? > > Edit: it seems you call it Functional. I'm not particulary happy with > either of names. > > > - In my opinion a functional operation is in itself an special > > iterator not an additional method on iterator itself. I don't like > > that I can call iterator() and do next() next() next() and afterwards > > call a functional operator. What can I expect in such an case? > > Ok. There was take and skip operators in spec which get lost. > > it would be something like: > > iterator().skip(3).map(func) > > > > Also > > there is nothing preventing an Iterator to never end the iteration > > (not in any implementation in libgee but doable with a custom > > iterator). What can I expect in such a case from an functional > > iterator? > > > > They produces elements as they go. So say there is iterator returning: > > iter = [1, 2, 3, 4, ....] > > iter.map((x) => {return x + 1;}) returns > > [2, 3, 4, 5, ...] > > iter.scan((x, y) => {return x + y}, 0) returns > > [0, 1, 3, 6, 10, ...] > > > I hope you don't take this negatively this is my personal opinion and > > I also may be wrong. :) Generally I like the interface. > > > > No. It would be... well stupid if I sent RFC/call for consensus > expecting only positive feedback. Well - ok, I do hope everything is > fine with my original design ;) but from my experience negative, but > constructive, feedback is the most valuable one. > > > I have also implemented how I think the functional iterators should be > > implemented (however I am not totally happy with the code but it > > should be good enough as an example). > > The code is available as a clone of your repository in gitorious in: > > http://gitorious.org/~quikee/libgee/quikees-mpiechotkas-libgee/commits/functional-iterators > > > > To be honest I don't like the separation of FunctionalIterator and > Iterator. Every iterator is, conceptually, functional iterator. There is > no iterator for which you cannot define meaningfully map function. > Sorry for double-posting. Also - your implementation uses foreach by default which is a bad idea from performance POV as mentioned before. (Namely 20x performance degradation for 1023 element array). > > Regards, Tomaž > > Regards Regards
Attachment:
signature.asc
Description: This is a digitally signed message part