org.organicdesign.fp.StaticImports Maven / Gradle / Ivy
// Copyright 2014-09-22 PlanBase Inc. & Glen Peterson
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package org.organicdesign.fp;
import org.organicdesign.fp.collections.ImList;
import org.organicdesign.fp.collections.ImMap;
import org.organicdesign.fp.collections.ImSet;
import org.organicdesign.fp.collections.ImSortedMap;
import org.organicdesign.fp.collections.ImSortedSet;
import org.organicdesign.fp.collections.PersistentHashMap;
import org.organicdesign.fp.collections.PersistentHashSet;
import org.organicdesign.fp.collections.PersistentTreeMap;
import org.organicdesign.fp.collections.PersistentTreeSet;
import org.organicdesign.fp.collections.PersistentVector;
import org.organicdesign.fp.tuple.Tuple2;
import org.organicdesign.fp.tuple.Tuple3;
import org.organicdesign.fp.xform.Transformable;
import org.organicdesign.fp.xform.Xform;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Map;
/**
A mini data definition language composed of vec(), tup(), map(), set(), plus a converter to make
java.util collections transformable: xform().
import org.organicdesign.fp.StaticImports.*
// Create a new vector of integers
vec(1, 2, 3, 4);
// Create a new set of Strings
set("a", "b", "c");
// Create a tuple of an int and a string (a type-safe heterogeneous container)
tup("a", 1);
// Create a map with a few key value pairs
map(tup("a", 1), tup("b", 2), tup("c", 3);
vec(), map(), and set() are the only three methods
in this project to take varargs. I tried writing out versions that took multiple type-safe
arguments, but IntelliJ presented you with a menu of all of them for auto-completion which
was overwhelming, so I reverted to varargs. Also, varargs relax some type safety rules (variance)
for data definition in a relatively helpful and not very dangerous way.
If you do more Clojure/JSON than Java, you'll find that what's a map (dictionary) in those languages often becomes a tuple in UncleJim.
A true map data structure is homogeneous, meaning that every member has the same type (or same parent type).
Tuples are designed to contain unrelated data types, and enforce those types.
As with any usage of import *, there could be issues if you import 2 different versions of this
file in your classpath. Java needs a data definition language so badly that I think it is worth
the risk. Also, I don't anticipate this file changing much, except to add more tup()
implementations, which shouldn't break anything. Let me know if you find that the danger outweighs
convenience or have advice on what to do about it.
*/
@SuppressWarnings("UnusedDeclaration")
public class StaticImports {
// Prevent instantiation
private StaticImports() { throw new UnsupportedOperationException("No instantiation"); }
/**
Returns a new PersistentHashMap of the given keys and their paired values. Use the tup()
method to define those key/value pairs briefly and easily. This data definition method is one
of the three methods in this project that support varargs.
*/
@SafeVarargs
public static ImMap map(Map.Entry... es) {
if ( (es == null) || (es.length < 1) ) { return PersistentHashMap.empty(); }
return PersistentHashMap.of(Arrays.asList(es));
}
/**
Returns a new PersistentHashSet of the values. This data definition method is one of the three
methods in this project that support varargs.
*/
@SafeVarargs
public static ImSet set(T... items) {
if ( (items == null) || (items.length < 1) ) { return PersistentHashSet.empty(); }
return PersistentHashSet.of(Arrays.asList(items));
}
/**
Returns a new PersistentTreeMap of the specified comparator and the given key/value pairs. Use
the tup() method to define those key/value pairs briefly and easily. The keys are sorted
according to the comparator you provide.
*/
public static ImSortedMap
sortedMap(Comparator super K> c, Iterable> es) {
return PersistentTreeMap.ofComp(c, es);
}
/**
Returns a new PersistentTreeMap of the given comparable keys and their paired values, sorted in
the default ordering of the keys. Use the tup() method to define those key/value pairs briefly
and easily.
*/
public static ,V> ImSortedMap
sortedMap(Iterable> es) {
return PersistentTreeMap.of(es);
}
/** Returns a new PersistentTreeSet of the given comparator and items. */
public static ImSortedSet sortedSet(Comparator super T> comp, Iterable items) {
return Xform.of(items).toImSortedSet(comp);
}
/** Returns a new PersistentTreeSet of the given comparable items. */
public static > ImSortedSet sortedSet(Iterable items) {
return PersistentTreeSet.of(items);
}
/** Returns a new Tuple2 of the given items. */
public static Tuple2 tup(T t, U u) { return Tuple2.of(t, u); }
/** Returns a new Tuple3 of the given items. */
public static Tuple3 tup(T t, U u, V v) { return Tuple3.of(t, u, v); }
/**
Returns a new PersistentVector of the given items. This data definition method is one of the
three methods in this project that support varargs.
*/
@SafeVarargs
static public ImList vec(T... items) {
if ( (items == null) || (items.length < 1) ) { return PersistentVector.empty(); }
return PersistentVector.ofIter(Arrays.asList(items));
}
/**
If you need to wrap a regular Java collection or other iterable outside this project to perform
a transformation on it, this method is the most convenient, efficient way to do so.
*/
public static Transformable xform(Iterable iterable) {
return Xform.of(iterable);
}
}