-
Notifications
You must be signed in to change notification settings - Fork 203
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
#160 let's get rid of List.add() #183
Conversation
@davvd , please review the pull request. |
@super132 Let me find a reviewer for this pull request, thanks for submitting it |
@krzyk review this one,please |
@super132 please merge changes from master to this PR |
/** | ||
* Internal storage to hold the elements from iterables. | ||
*/ | ||
private final transient List<T> storage = new LinkedList<T>(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@super132 why create a storage if we can reuse the original iterables for this? This will waste more memory.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@krzyk , may I know if you mean to initialise it lazily or this storage is not even needed? If it is the later case then how could we reuse storage as this class should not holds any reference to the input iterables.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@super132 why shouldn't this class hold references to the input iterables?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@krzyk, I have questions regarding to holding references as I believe the iterables could be modified outside using remove()
method and the ultimate memory usage would not be higher:
- How are we implement
iterator()
method? Do we need to write a brand new iterator which calls the iterators of the two iterables? - How are the use cases of
Concat
? If there are more use cases that the input iterable will eventually be garbage collected then I think creating one new object would save more memory. I think when we useConcat
, we would be more interested in the end result rather than the input and the input would then be unreferenced. - How would we handle
remove()
method that could be implemented by iterables? If the input iterable is modified by this method then it would affect the concatenated result if we rely on the reference to produce the output.
Thanks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@super132
For now let's leave it as it is and will see what @yegor256 thinks about current design.
- You would create a new iterator that would iterate over the first iterable and after it finishes it would go to the other one
- I don't know that.
- Remove would just throw
UnsupportedOperationException
as it does in some iterators in JDK.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@krzyk, no problem. Thanks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@super132 well, you're not solving the key problem with this implementation. At the moment Concat
class is fetching items from all iterables during constructing. What if they have 1bln item each and the user will do: new Concat(bln, bln).iterator().next();
You will fetch 2 bln items, while the user needs just one.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@yegor256, understood. I would change the implementation for it.
@super132 please see my comments above |
@krzyk, thanks for your comments. I have updated some in the commit. I have some questions regarding to your comments and would you please help take a look of it? Thanks. |
Conflicts: src/main/java/org/takes/rs/RsWithHeaders.java
@yegor256, instead of using |
@@ -136,6 +136,11 @@ | |||
<optional>true</optional> | |||
</dependency> | |||
<dependency> | |||
<groupId>com.google.guava</groupId> | |||
<artifactId>guava</artifactId> | |||
<scope>compile</scope> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we can't use any dependencies in this project
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No problem. I can revert back to previous version.
@super132 again all wrong :) I would suggest you to first draw the design in text and suggest it. we'll discuss. then you will create Java code. looks like you don't understand the idea of functional programming and its application in OOP. I asked you whether you used Guava just to check whether you have any experience in using their "functional" concepts. besides that, your branch is very big in size, I would recommend to make it shorter and use PDD: http://www.yegor256.com/2009/03/04/pdd.html |
@yegor256, I thought it would be ok this time :P I still do not think that the lower case here is a transformation. Let's take a look of the original codes in for (final String header : req.head()) {
if (!header.toLowerCase(Locale.ENGLISH)
.startsWith(prefix)) {
head.add(header);
}
} The logic here is to compare if header does not contain a prefix in a case insensitive manner and output it. And once it passes the condition, the original header, not the one transformed into lower case, is added to the result. Same logic here in the current implementation that I use a If we had to implement it using transformation, then we have to do something like this: new Transform<String, String>(
new Select<String>(
new Transform<String, String>(
req.head(),
new TransformAction.LowerCase()
),
new Condition.Not<String>(
new Condition.StartsWith(prefix)
)
),
new TransformAction.NormalCase()
) The problems in the above implementation are:
As per your comment preivously, this case specific condition should be inline. I generally agree on this approach but what I need to do is to make an inner class in Based on the reasons above, I cannot see this comparison is a transformation, but a case insensitive comparison. If we really needed to implement it in transformation, would you please advise on how to implement transformation that can revert an iterable in lower case to its original case? Should we use inline approach instead of making them general conditions here? Thanks. |
@yegor256, I am happy to create a puzzle for the case insensitive transformation implementaiton. Should I modify my codes based on my comments above (grouping the use of |
@super132 don't worry about qulice complaining about too long anonymous class. You can just suppress this warning, as it's done, for example in I would do it like this: new Select<String>(
req.head(),
new Condition<String>() {
@Override
public boolean fits(String header) {
return header.toLowerCase().startsWith(prefix);
}
}
) |
@yegor256 Thanks for your advice. I have moved the condition to be inline. Please have a check. |
@yegor256, may I know if the latest change is fine for you? Thanks. |
@yegor256 , may I have your opinion on it? It has been pending for 4 days. Thanks. |
@super132 I'll update you tomorrow, sorry for the delay |
@yegor256 , do you mean that I need to implement the Iterator to take in the data source directly instead of the iterator and copy the whole element into a buffer instead? So the ConcatIterator for example will become something like below? class ConcatIterator<E> implements Iterator<E> {
private final Iterable<E> aitr;
private final Iterable<E> bitr;
private final Queue<E> buffer = new LinkedList<E>();
public ConcatIterator(final Iterable<E> alist, final Iterable<E> blist) {
this.aitr = alist;
this.bitr = blist;
}
public boolean hasNext() {
if (this.buffer.isEmpty()) {
//iterate over aitr and bitr and save the item into queue
}
return !this.buffer.isEmpty();
}
public E next() {
if (!this.hasNext()) {
throw new NoSuchElementException("No element");
}
return this.buffer.poll();
}
} But then will it violate the rule you told me before that the iterable and the iterator should be as lazy as possible? The implementation now will do the actual condition check and transformation at the very last moment and using the implementation above, it would not be this lazy and it will scan through all elements even though the caller gets the first element in the end. Or do you want to change the implementation to take in the Another question I have about the implementation of With the questions above, may I confirm with you that would you want to have the implementation like the code block above? Thanks. |
@super132 we're making this pull request too long. You're asking too many questions and I have to spend too much time to educate you. I would suggest to split this pull request into smaller parts. This one is too big and has too many issues. |
@yegor256 , no problem. I will create puzzle on the Iterator design in all 3 iterator that I made and close this one. Would it be better to handle the issues like this? I'm going to do add the puzzle comments if you have no objection. Thanks. |
@super132 in general, we prefer short branches |
@yegor256 , let me split this PR into 3 smaller PRs, which will contain |
@super132 yes, I think this one should be closed |
@elenavolokhova review this ticket please, for compliance with our quality rules |
@davvd This request wasn't merged but performer should be rewarded for review. Quality is acceptable. |
@elenavolokhova thanks a lot, next time everybody should try to make it better |
@elenavolokhova thanks, got it. everybody, please try to make it good next time |
@krzyk just added 10 mins to @elenavolokhova (for QA), payment ID is |
For task #160 , added
Concat
class and another utility classIterableTransform
for header concatenation.