Skip to content
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

Collection functions #2267

Merged
merged 2 commits into from
Jul 27, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion vavr/generator/Generator.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2519,7 +2519,7 @@ def generateTestClasses(): Unit = {
@$test
public void shouldCreate${func}From${i}Pairs() {
$MapType<Integer, Integer> map = $func(${(1 to i).gen(j => s"$j, ${j*2}")(", ")});
${(1 to i).gen(j => s"assertThat(map.apply($j)).isEqualTo(${j*2});")("\n")}
${(1 to i).gen(j => s"assertThat(map.get($j).get()).isEqualTo(${j*2});")("\n")}
}
"""
})("\n\n")}
Expand Down
330 changes: 165 additions & 165 deletions vavr/src-gen/test/java/io/vavr/APITest.java

Large diffs are not rendered by default.

20 changes: 15 additions & 5 deletions vavr/src/main/java/io/vavr/collection/IndexedSeq.java
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,21 @@ static <T> IndexedSeq<T> narrow(IndexedSeq<? extends T> indexedSeq) {
@Override
IndexedSeq<T> asJavaMutable(Consumer<? super java.util.List<T>> action);

@Override
default PartialFunction<Integer, T> asPartialFunction() throws IndexOutOfBoundsException {
return new PartialFunction<Integer, T>() {
private static final long serialVersionUID = 1L;
@Override
public T apply(Integer index) {
return get(index);
}
@Override
public boolean isDefinedAt(Integer index) {
return 0 <= index && index < length();
}
};
}

@Override
<R> IndexedSeq<R> collect(PartialFunction<? super T, ? extends R> partialFunction);

Expand Down Expand Up @@ -177,11 +192,6 @@ default int indexOfSlice(Iterable<? extends T> that, int from) {
@Override
IndexedSeq<T> intersperse(T element);

@Override
default boolean isDefinedAt(Integer index) {
return 0 <= index && index < length();
}

@Override
default T last() {
if (isEmpty()) {
Expand Down
22 changes: 16 additions & 6 deletions vavr/src/main/java/io/vavr/collection/LinearSeq.java
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,22 @@ static <T> LinearSeq<T> narrow(LinearSeq<? extends T> linearSeq) {
@Override
LinearSeq<T> asJavaMutable(Consumer<? super java.util.List<T>> action);

@Override
default PartialFunction<Integer, T> asPartialFunction() throws IndexOutOfBoundsException {
return new PartialFunction<Integer, T>() {
private static final long serialVersionUID = 1L;
@Override
public T apply(Integer index) {
return get(index);
}
@Override
public boolean isDefinedAt(Integer index) {
// we can't use length() because of infinite long sequences
return 0 <= index && drop(index).nonEmpty();
}
};
}

@Override
<R> LinearSeq<R> collect(PartialFunction<? super T, ? extends R> partialFunction);

Expand Down Expand Up @@ -160,12 +176,6 @@ default int indexWhere(Predicate<? super T> predicate, int from) {
@Override
LinearSeq<T> intersperse(T element);

@Override
default boolean isDefinedAt(Integer index) {
// we can't use length() because of infinite long sequences
return 0 <= index && drop(index).nonEmpty();
}

@Override
default int lastIndexOfSlice(Iterable<? extends T> that, int end) {
Objects.requireNonNull(that, "that is null");
Expand Down
55 changes: 21 additions & 34 deletions vavr/src/main/java/io/vavr/collection/Map.java
Original file line number Diff line number Diff line change
Expand Up @@ -87,15 +87,13 @@
* <li>{@link #transform(Function)}</li>
* <li>{@link #unzip(BiFunction)}</li>
* <li>{@link #unzip3(BiFunction)}</li>
* <li>{@link #withDefault(Function)}</li>
* <li>{@link #withDefaultValue(Object)}</li>
* </ul>
*
* @param <K> Key type
* @param <V> Value type
* @author Daniel Dietrich, Ruslan Sennov
*/
public interface Map<K, V> extends Traversable<Tuple2<K, V>>, PartialFunction<K, V>, Serializable {
public interface Map<K, V> extends Traversable<Tuple2<K, V>>, Serializable {

long serialVersionUID = 1L;

Expand Down Expand Up @@ -141,9 +139,26 @@ static <K, V> Tuple2<K, V> entry(K key, V value) {
return Tuple.of(key, value);
}

@Override
default V apply(K key) {
return get(key).getOrElseThrow(() -> new NoSuchElementException(String.valueOf(key)));
/**
* Turns this {@code Map} into a {@link PartialFunction} which is defined at a specific index, if this {@code Map}
* contains the given key. When applied to a defined key, the partial function will return
* the value of this {@code Map} that is associated with the key.
*
* @return a new {@link PartialFunction}
* @throws NoSuchElementException when a non-existing key is applied to the partial function
*/
default PartialFunction<K, V> asPartialFunction() throws IndexOutOfBoundsException {
return new PartialFunction<K, V>() {
private static final long serialVersionUID = 1L;
@Override
public V apply(K key) {
return get(key).getOrElseThrow(() -> new NoSuchElementException(String.valueOf(key)));
}
@Override
public boolean isDefinedAt(K key) {
return containsKey(key);
}
};
}

@Override
Expand Down Expand Up @@ -659,29 +674,6 @@ default Iterator<V> valuesIterator() {
return iterator().map(Tuple2::_2);
}

/**
* Turns this map from a partial function into a total function that
* returns a value computed by defaultFunction for all keys
* absent from the map.
*
* @param defaultFunction function to evaluate for all keys not present in the map
* @return a total function from K to T
*/
default Function1<K, V> withDefault(Function<? super K, ? extends V> defaultFunction) {
return k -> get(k).getOrElse(() -> defaultFunction.apply(k));
}

/**
* Turns this map from a partial function into a total function that
* returns defaultValue for all keys absent from the map.
*
* @param defaultValue default value to return for all keys not present in the map
* @return a total function from K to T
*/
default Function1<K, V> withDefaultValue(V defaultValue) {
return k -> get(k).getOrElse(defaultValue);
}

@Override
default <U> Seq<Tuple2<Tuple2<K, V>, U>> zip(Iterable<? extends U> that) {
return zipWith(that, Tuple::of);
Expand Down Expand Up @@ -746,11 +738,6 @@ default <U> Seq<U> zipWithIndex(BiFunction<? super Tuple2<K, V>, ? super Integer
@Override
io.vavr.collection.Iterator<? extends Map<K, V>> grouped(int size);

@Override
default boolean isDefinedAt(K key) {
return containsKey(key);
}

@Override
default boolean isDistinct() {
return true;
Expand Down
34 changes: 23 additions & 11 deletions vavr/src/main/java/io/vavr/collection/Multimap.java
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@
* @param <V> Value type
* @author Ruslan Sennov
*/
public interface Multimap<K, V> extends Traversable<Tuple2<K, V>>, PartialFunction<K, Traversable<V>>, Serializable {
public interface Multimap<K, V> extends Traversable<Tuple2<K, V>>, Serializable {

long serialVersionUID = 1L;

Expand Down Expand Up @@ -154,18 +154,35 @@ static <K, V> Multimap<K, V> narrow(Multimap<? extends K, ? extends V> map) {

// -- non-static API

@Override
default Traversable<V> apply(K key) {
return get(key).getOrElseThrow(NoSuchElementException::new);
}

/**
* Converts this {@code Multimap} to a {@code Map}
*
* @return {@code Map<K, Traversable<V>>}
*/
Map<K, Traversable<V>> asMap();

/**
* Turns this {@code Multimap} into a {@link PartialFunction} which is defined at a specific index, if this {@code Multimap}
* contains the given key. When applied to a defined key, the partial function will return
* the {@link Traversable} of this {@code Multimap} that is associated with the key.
*
* @return a new {@link PartialFunction}
* @throws NoSuchElementException when a non-existing key is applied to the partial function
*/
default PartialFunction<K, Traversable<V>> asPartialFunction() throws IndexOutOfBoundsException {
return new PartialFunction<K, Traversable<V>>() {
private static final long serialVersionUID = 1L;
@Override
public Traversable<V> apply(K key) {
return get(key).getOrElseThrow(NoSuchElementException::new);
}
@Override
public boolean isDefinedAt(K key) {
return containsKey(key);
}
};
}

/**
* Maps this {@code Multimap} to a new {@code Multimap} with different component type by applying a function to its elements.
*
Expand Down Expand Up @@ -318,11 +335,6 @@ default boolean hasDefiniteSize() {
return true;
}

@Override
default boolean isDefinedAt(K key) {
return containsKey(key);
}

@Override
default boolean isDistinct() {
return true;
Expand Down
63 changes: 17 additions & 46 deletions vavr/src/main/java/io/vavr/collection/Seq.java
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,12 @@
* <li>{@link #update(int, Object)}</li>
* </ul>
*
* Conversion:
*
* <ul>
* <li>{@link #asPartialFunction}</li>
* </ul>
*
* Filtering:
*
* <ul>
Expand Down Expand Up @@ -106,7 +112,7 @@
* @param <T> Component type
* @author Daniel Dietrich
*/
public interface Seq<T> extends Traversable<T>, PartialFunction<Integer, T>, Serializable {
public interface Seq<T> extends Traversable<T>, Serializable {

long serialVersionUID = 1L;

Expand Down Expand Up @@ -140,19 +146,6 @@ static <T> Seq<T> narrow(Seq<? extends T> seq) {
* @throws NullPointerException if {@code elements} is null
*/
Seq<T> appendAll(Iterable<? extends T> elements);

/**
* A {@code Seq} is a partial function which returns the element at the specified index by calling
* {@linkplain #get(int)}.
*
* @param index an index
* @return the element at the given index
* @throws IndexOutOfBoundsException if this is empty, index &lt; 0 or index &gt;= length()
*/
@Override
default T apply(Integer index) {
return get(index);
}

/**
* Creates an <strong>immutable</strong> {@link java.util.List} view on top of this {@code Seq},
Expand Down Expand Up @@ -205,6 +198,16 @@ default T apply(Integer index) {
@GwtIncompatible
Seq<T> asJavaMutable(Consumer<? super java.util.List<T>> action);

/**
* Turns this {@code Seq} into a {@link PartialFunction} which is defined at a specific index, if this {@code Seq}
* contains at least index + 1 elements. When applied to a defined index, the partial function will return
* the value of this {@code Seq} at the specified index.
*
* @return a new {@link PartialFunction}
* @throws IndexOutOfBoundsException if this is empty, index &lt; 0 or index &gt;= length()
*/
PartialFunction<Integer, T> asPartialFunction() throws IndexOutOfBoundsException;

@Override
<R> Seq<R> collect(PartialFunction<? super T, ? extends R> partialFunction);

Expand Down Expand Up @@ -585,16 +588,6 @@ default Option<Integer> lastIndexWhereOption(Predicate<? super T> predicate, int
return Collections.indexOption(lastIndexWhere(predicate, end));
}

/**
* Turns this sequence into a plain function returning an Option result.
*
* @return a function that takes an index i and returns the value of
* this sequence in a Some if the index is within bounds, otherwise a None.
*/
default Function1<Integer, Option<T>> lift() {
return i -> (i >= 0 && i < length()) ? Option.some(apply(i)) : Option.none();
}

/**
* Returns the index of the last occurrence of the given element before or at a given end index
* or -1 if this does not contain the given element.
Expand Down Expand Up @@ -1275,28 +1268,6 @@ default <U> U foldRight(U zero, BiFunction<? super T, ? super U, ? extends U> f)
@Override
<U> Seq<U> zipWithIndex(BiFunction<? super T, ? super Integer, ? extends U> mapper);

/**
* Turns this sequence from a partial function into a total function that
* returns defaultValue for all indexes that are out of bounds.
*
* @param defaultValue default value to return for out of bound indexes
* @return a total function from index to T
*/
default Function1<Integer, T> withDefaultValue(T defaultValue) {
return i -> (i >= 0 && i < length()) ? apply(i) : defaultValue;
}

/**
* Turns this sequence from a partial function into a total function that
* returns a value computed by defaultFunction for all indexes that are out of bounds.
*
* @param defaultFunction function to evaluate for all out of bounds indexes.
* @return a total function from index to T
*/
default Function1<Integer, T> withDefault(Function<? super Integer, ? extends T> defaultFunction) {
return i -> (i >= 0 && i < length()) ? apply(i) : defaultFunction.apply(i);
}

@Override
default boolean isSequential() {
return true;
Expand Down
16 changes: 1 addition & 15 deletions vavr/src/main/java/io/vavr/collection/Set.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
*/
package io.vavr.collection;

import io.vavr.Function1;
import io.vavr.PartialFunction;
import io.vavr.Tuple3;
import io.vavr.Tuple2;
Expand Down Expand Up @@ -82,7 +81,7 @@
* @param <T> Component type
* @author Daniel Dietrich, Ruslan Sennov
*/
public interface Set<T> extends Traversable<T>, Function1<T, Boolean>, Serializable {
public interface Set<T> extends Traversable<T>, Serializable {

long serialVersionUID = 1L;

Expand Down Expand Up @@ -116,19 +115,6 @@ static <T> Set<T> narrow(Set<? extends T> set) {
*/
Set<T> addAll(Iterable<? extends T> elements);

/**
* Tests if a given {@code element} is contained in this {@code Set}.
* <p>
* This method is equivalent to {@link #contains(Object)}.
*
* @param element the element to test for membership.
* @return {@code true} if the given {@code element} is contained, {@code false} otherwise.
*/
@Override
default Boolean apply(T element) {
return contains(element);
}

/**
* Calculates the difference between this set and another set.
* <p>
Expand Down
12 changes: 12 additions & 0 deletions vavr/src/test/java/io/vavr/MatchTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
package io.vavr;

import io.vavr.collection.List;
import io.vavr.collection.Set;
import io.vavr.control.Either;
import io.vavr.control.Option;
import io.vavr.control.Option.Some;
Expand Down Expand Up @@ -339,6 +340,17 @@ public void shouldDecomposeListWithNonEmptyTail() {
}
*/

// -- Set

@Test
public void shouldDecomposeSet() {
final Set<String> abc = Set("abc");
final Set<String> result = Match(abc).of( // Does not compile: the Java inference engine sees abc as a Function1<String, Boolean> before a Set<String> thus expects result to be of type Boolean
Case($(), () -> abc)
);
assertThat(result).isEqualTo(abc);
}

// -- Validation

@Test
Expand Down
Loading