
com.tailoredshapes.underbar.UnderBar Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of ocho Show documentation
Show all versions of ocho Show documentation
Foundational functions inspired by Clojure and underscore.js
package com.tailoredshapes.underbar;
import com.tailoredshapes.underbar.data.Fork;
import com.tailoredshapes.underbar.data.Heap;
import com.tailoredshapes.underbar.exceptions.UnderBarred;
import com.tailoredshapes.underbar.function.RegularFunctions;
import java.util.*;
import java.util.function.*;
import java.util.stream.IntStream;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
import static com.tailoredshapes.underbar.Die.*;
import static com.tailoredshapes.underbar.UnderString.commaSep;
import static java.util.Optional.ofNullable;
import static java.util.stream.Collectors.toList;
public interface UnderBar {
Map, Object> lazyCache = Collections.synchronizedMap(hash());
/**
* Asserts that a collection contains exactly one value and returns it
*/
static T nonce(Iterable ts) {
Iterator i = ts.iterator();
dieUnless(i.hasNext(), () -> "input to 'nonce' cannot be empty");
T result = i.next();
dieIf(i.hasNext(), () -> "input to 'nonce' has length > 1: " + ts);
return result;
}
/**
* Asserts that an array contains exactly one value and returns it
*/
static T nonce(T[] ts) {
dieIfNull(ts, () -> "input to 'nonce' cannot be null");
dieUnless(ts.length == 1, () -> "length of input to 'nonce' must be 1. " + commaSep(list(ts)));
return ts[0];
}
/**
* Returns true if the collection isEmpty
*/
static boolean isEmpty(Collection> coll) {
return coll.isEmpty();
}
static Optional maybe(Iterable ts) {
Iterator i = ts.iterator();
if (!i.hasNext()) {
return Optional.empty();
}
T result = i.next();
dieIf(i.hasNext(), () -> "input to 'nonce' has length > 1: " + ts);
return Optional.of(result);
}
/**
* Executes a runnable if an optional is empty
*/
static void ifAbsent(Optional> maybe, Runnable noT) {
if (!maybe.isPresent())
noT.run();
}
/**
* Checks if a value is null. If it isn't execute a function, otherwise execute a supplier
*/
static R maybeNull(T maybeNull, Function onT, Supplier noT) {
return optionally(ofNullable(maybeNull), onT, noT);
}
/**
* Checks if a optional is present. If it isn't execute a function, otherwise execute a supplier
*/
static R optionally(Optional maybe, Function onT, Supplier noT) {
return maybe.isPresent() ? onT.apply(maybe.get()) : noT.get();
}
/**
* Provides a mechanism for getting the value from a hash, or a default value
*/
static R maybeGet(Map maybe, K k, Function onT, Supplier noT) {
return maybeNull(maybe.get(k), onT, noT);
}
/**
* @return An empty ArrayList
*/
static List emptyList() {
return new ArrayList<>();
}
/**
* Returns an fixed size list apply ts in it
*/
@SafeVarargs
static List list(T... ts) {
return Arrays.asList(ts);
}
/**
* Returns a modifiable list from an iterable
*/
static List list(Iterable ts) {
ArrayList result = new ArrayList<>();
ts.forEach(result::add);
return result;
}
/**
* Returns a modifiable list apply ts in it
*/
@SafeVarargs
static List modifiableList(T... ts) {
List result = new ArrayList<>();
result.addAll(list(ts));
return result;
}
/**
* Creates a new HashSet of ts
*/
@SafeVarargs
static Set set(T... ts) {
return new HashSet<>(Arrays.asList(ts));
}
/**
* Creates a new HashSet of ts from an iterable
*/
static Set set(Iterable ts) {
HashSet result = new HashSet<>();
ts.forEach(result::add);
return result;
}
/**
* Creates a new HashSet of T from an iterable of F using a convertion function
*/
static Set set(Iterable is, Function toT) {
return set(map(is, toT));
}
/**
* Lambda require the objects they mutate to be either effectively final or heap allocated.
* This function heap allocates an object.
*/
static Heap heap(T t) {
return new Heap<>(t);
}
/**
* A convenience function for creating an array
*/
@SafeVarargs
static T[] array(T... ts) {
return ts;
}
/**
* Returns the first member of an iterable collection
*/
static T first(Iterable ts) {
Iterator iterator = ts.iterator();
dieUnless(iterator.hasNext(), () -> "can't take first of empty iterable");
return iterator.next();
}
/**
* Returns the last member of an iterable collection
*/
static T last(List ts) {
dieIf(isEmpty(ts), () -> "can't take last of empty list!");
return ts.get(ts.size() - 1);
}
/**
* Returns the second member of an iterable.
*/
static T second(Iterable ts) {
Iterator iterator = ts.iterator();
iterator.next();
return iterator.next();
}
/**
* Returns everything but the first member of a collection
*/
static List rest(List ts) {
return ts.subList(1, ts.size());
}
/**
* Returns the first n of a collection
*/
static List take(int n, List ts) {
return ts.subList(0, Math.min(n, ts.size()));
}
/**
* Pretty sure this is broken
*/
static Optional takeWhile(Iterable ts, Predicate p) {
for (T next : ts) {
if (p.test(next)) return optional(next);
}
return optional();
}
/**
* Checks for null and size
*/
static boolean hasContent(Collection> coll) {
return coll != null && coll.size() > 0;
}
/**
* Joins one dimensional collections
*/
@SafeVarargs
static List concat(Collection... collections) {
ArrayList result = new ArrayList<>(collections[0]);
for (int i = 1; i < collections.length; i++)
result.addAll(collections[i]);
return result;
}
/**
* A union over N sets
*/
@SafeVarargs
static Set union(Set... s) {
List> sets = list(s);
return stream(sets).reduce((a, b) -> {
a.addAll(b);
return a;
}).get();
}
/**
* The intersection of N sets
*/
@SafeVarargs
static Set intersection(Set... sets) {
Set result = new HashSet<>(sets[0]);
for (int i = 1; i < sets.length; i++) {
result.retainAll(sets[i]);
}
return result;
}
/**
* The difference of N sets
*/
@SafeVarargs
static Set difference(Set... sets) {
Set result = new HashSet<>(sets[0]);
for (int i = 1; i < sets.length; i++) {
result.removeAll(sets[i]);
}
return result;
}
/**
* Join a collection of keys and a collection of values into a hash
*/
static Map zipmap(Collection extends K> keys, Collection extends V> values) {
dieUnless(keys.size() == values.size(), () -> "keys and values must be nonce same size. " + keys.size() + " != " + values.size());
HashMap result = new HashMap<>();
Iterator extends V> vi = values.iterator();
keys.forEach(k -> result.put(k, vi.next()));
return result;
}
/**
* Pairs and lists keys and values from two collections
*/
static List> zip(Collection extends K> keys, Collection extends V> values) {
dieUnless(keys.size() == values.size(), () -> "keys and values must be nonce same size. " + keys.size() + " != " + values.size());
List> result = emptyList();
Iterator extends V> vi = values.iterator();
keys.forEach(k -> result.add(entry(k, vi.next())));
return result;
}
/**
* Like concat, for maps
*/
@SafeVarargs
static Map merge(Map... ms) {
List