introduce generate(v0, F) and repeat(N); take(N) replaces error-prone Conditions...
authorGregory.Shrago <gregory.shrago@jetbrains.com>
Tue, 16 Jun 2015 21:12:31 +0000 (00:12 +0300)
committerGregory.Shrago <gregory.shrago@jetbrains.com>
Tue, 16 Jun 2015 21:27:33 +0000 (00:27 +0300)
platform/util-rt/src/com/intellij/openapi/util/Conditions.java
platform/util/src/com/intellij/util/containers/JBIterable.java

index d2740eda21dadaed03dac1a016052f6df90643cd..b6b542602a564b16dff76388f6c236328ea8931a 100644 (file)
@@ -133,16 +133,6 @@ public class Conditions {
     };
   }
 
-  public static <A> Condition<A> countDown(final int n) {
-    return new Condition<A>() {
-      int cur = n;
-      @Override
-      public boolean value(A a) {
-        return cur > 0 && cur -- != 0;
-      }
-    };
-  }
-
   public static <T> Condition<T> cached(Condition<T> c) {
     return new SoftRefCache<T>(c);
   }
index 479e2a74e72319574a6ece18230230a48f46d1e7..387b0ea117f4c17b1e94b3f01c2053fb3d3e733e 100644 (file)
@@ -28,17 +28,18 @@ import org.jetbrains.annotations.Nullable;
 import java.util.*;
 
 /**
- * An in-house version of com.google.common.collect.FluentIterable.
+ * An in-house version of {@code com.google.common.collect.FluentIterable} with some Clojure-like additions.
  *
- * The original JavaDoc:
  * <p/>
- * {@code FluentIterable} provides a rich interface for manipulating {@code Iterable} instances in a
- * chained fashion. A {@code FluentIterable} can be created from an {@code Iterable}, or from a set
- * of elements. The following types of methods are provided on {@code FluentIterable}:
+ * The original JavaDoc ('FluentIterable' replaced by 'JBIterable'):
+ * <p/>
+ * {@code JBIterable} provides a rich interface for manipulating {@code Iterable} instances in a
+ * chained fashion. A {@code JBIterable} can be created from an {@code Iterable}, or from a set
+ * of elements. The following types of methods are provided on {@code JBIterable}:
  * <ul>
- * <li>chained methods which return a new {@code FluentIterable} based in some way on the contents
+ * <li>chained methods which return a new {@code JBIterable} based in some way on the contents
  * of the current one (for example {@link #transform})
- * <li>conversion methods which copy the {@code FluentIterable}'s contents into a new collection or
+ * <li>conversion methods which copy the {@code JBIterable}'s contents into a new collection or
  * array (for example {@link #toList})
  * <li>element extraction methods which facilitate the retrieval of certain elements (for example
  * {@link #last})
@@ -53,8 +54,8 @@ import java.util.*;
  *       .transform(Functions.toStringFunction())
  *       .toList();}</pre>
  * <p/>
- * <p>Anything which can be done using {@code FluentIterable} could be done in a different fashion
- * (often with {@link Iterables}), however the use of {@code FluentIterable} makes many sets of
+ * <p>Anything which can be done using {@code JBIterable} could be done in a different fashion
+ * (often with {@link Iterables}), however the use of {@code JBIterable} makes many sets of
  * operations significantly more concise.
  *
  * @author Marcin Mikosik
@@ -77,8 +78,8 @@ public abstract class JBIterable<E> implements Iterable<E> {
   }
 
   /**
-   * Returns a fluent iterable that wraps {@code iterable}, or {@code iterable} itself if it
-   * is already a {@code FluentIterable}.
+   * Returns a {@code JBIterable} that wraps {@code iterable}, or {@code iterable} itself if it
+   * is already a {@code JBIterable}.
    */
   @NotNull
   public static <E> JBIterable<E> from(@Nullable Iterable<? extends E> iterable) {
@@ -93,7 +94,38 @@ public abstract class JBIterable<E> implements Iterable<E> {
   }
 
   /**
-   * Returns a fluent iterable containing {@code elements} in the specified order.
+   * Returns a {@code JBIterable} that is generated by {@code generator} function applied to a previous element,
+   * the first element is produced by the supplied {@code initial} value.
+   */
+  @NotNull
+  public static <E> JBIterable<E> generate(@Nullable final E initial, @NotNull final Function<? super E, ? extends E> generator) {
+    return new JBIterable<E>() {
+      @Override
+      public Iterator<E> iterator() {
+        return new Iterator<E>() {
+          E cur = initial;
+
+          @Override
+          public boolean hasNext() {
+            return true;
+          }
+
+          @Override
+          public E next() {
+            return cur = generator.fun(cur);
+          }
+
+          @Override
+          public void remove() {
+            throw new UnsupportedOperationException();
+          }
+        };
+      }
+    };
+  }
+
+  /**
+   * Returns a {@code JBIterable} containing {@code elements} in the specified order.
    */
   @NotNull
   public static <E> JBIterable<E> of(E... elements) {
@@ -118,7 +150,7 @@ public abstract class JBIterable<E> implements Iterable<E> {
    */
   @Override
   public String toString() {
-    return "(" + StringUtil.join(takeWhile(Conditions.countDown(50)), ", ") + ")";
+    return "(" + StringUtil.join(take(50), ", ") + ")";
   }
 
   /**
@@ -147,7 +179,7 @@ public abstract class JBIterable<E> implements Iterable<E> {
   }
 
   /**
-   * Returns a fluent iterable whose iterators traverse first the elements of this fluent iterable,
+   * Returns a {@code JBIterable} whose iterators traverse first the elements of this fluent iterable,
    * followed by those of {@code other}. The iterators are not polled until necessary.
    * <p/>
    * <p>The returned iterable's {@code Iterator} supports {@code remove()} when the corresponding
@@ -162,7 +194,7 @@ public abstract class JBIterable<E> implements Iterable<E> {
   }
 
   /**
-   * Returns a fluent iterable whose iterators traverse first the elements of this fluent iterable,
+   * Returns a {@code JBIterable} whose iterators traverse first the elements of this fluent iterable,
    * followed by {@code elements}.
    */
   public final JBIterable<E> append(@NotNull E[] elements) {
@@ -196,6 +228,68 @@ public abstract class JBIterable<E> implements Iterable<E> {
     return (JBIterable<T>)filter(Conditions.instanceOf(type));
   }
 
+  public final JBIterable<E> repeat(final int count) {
+    final JBIterable<E> it = this;
+    return new JBIterable<E>() {
+      @Override
+      public Iterator<E> iterator() {
+        return new Iterator<E>() {
+          int index;
+          Iterator<E> cur = it.iterator();
+
+          @Override
+          public boolean hasNext() {
+            boolean b = cur.hasNext();
+            if (b) return true;
+            if (index >= count || ++ index == count) return false;
+            cur = it.iterator();
+            return cur.hasNext();
+          }
+
+          @Override
+          public E next() {
+            return cur.next();
+          }
+
+          @Override
+          public void remove() {
+            cur.remove();
+          }
+        };
+      }
+    };
+  }
+
+  public final JBIterable<E> take(final int count) {
+    final JBIterable<E> it = this;
+    return new JBIterable<E>() {
+      @Override
+      public Iterator<E> iterator() {
+        final Iterator<E> iterator = it.iterator();
+        return new Iterator<E>() {
+          int index;
+
+          @Override
+          public boolean hasNext() {
+            return index < count && iterator.hasNext();
+          }
+
+          @Override
+          public E next() {
+            E result = iterator.next();
+            index ++;
+            return result;
+          }
+
+          @Override
+          public void remove() {
+            iterator.remove();
+          }
+        };
+      }
+    };
+  }
+
   public final JBIterable<E> takeWhile(@NotNull final Condition<? super E> condition) {
     final JBIterable<E> it = this;
     return new JBIterable<E>() {
@@ -237,7 +331,7 @@ public abstract class JBIterable<E> implements Iterable<E> {
 
 
   /**
-   * Returns a fluent iterable that applies {@code function} to each element of this
+   * Returns a {@code JBIterable} that applies {@code function} to each element of this
    * fluent iterable.
    * <p/>
    * <p>The returned fluent iterable's iterator supports {@code remove()} if this iterable's
@@ -271,7 +365,7 @@ public abstract class JBIterable<E> implements Iterable<E> {
   }
 
   /**
-   * Returns a fluent iterable that applies {@code function} to each element of this
+   * Returns a {@code JBIterable} that applies {@code function} to each element of this
    * fluent iterable and concats the produced iterables in one.
    * <p/>
    * <p>The returned fluent iterable's iterator supports {@code remove()} if an underlying iterable's
@@ -360,7 +454,7 @@ public abstract class JBIterable<E> implements Iterable<E> {
   }
 
   /**
-   * Returns an {@code Map} for which the elements of this {@code FluentIterable} are the keys in
+   * Returns an {@code Map} for which the elements of this {@code JBIterable} are the keys in
    * the same order, mapped to values by the given function. If this iterable contains duplicate
    * elements, the returned map will contain each distinct element once in the order it first
    * appears.