This is a partial port of the Ramda.js functional programming library to work with vavr types.
v0.0.11 (experimental, incomplete)
It's not on Maven Central yet, but you can find it in JCenter. First, add JCenter to the repositories in your pom:
<repositories>
<repository>
<id>jcenter</id>
<url>http://jcenter.bintray.com </url>
</repository>
</repositories>
Then you can import it as usual:
<dependencies>
<dependency>
<groupId>de.michaelzinn.ravr</groupId>
<artifactId>ravr</artifactId>
<version>0.0.11</version>
</dependency>
</dependencies>
compile 'de.michaelzinn.ravr:ravr:0.0.11'
Ravr provides two ways to do partial application: Either leave out parameters at the end or use a parameter placeholder:
// All the same
List.of(1, 2, 3).map(x -> add(2, x));
List.of(1, 2, 3).map(add(2, __)); // works but isn't idiomatic
List.of(1, 2, 3).map(add(2)); // use this one instead
// => [3, 4, 5]
// The placeholder should only be used when necessary.
List.of(7, 8, 9).map(subtract(__, 2));
// => [5, 6, 7]
You can compose functions in two ways.
Similar to mathematical composition. This is a vararg function.
// classic Java
map(add(1).compose(multiply(2)).compose(subtract(__, 1)), List(2, 3, 4));
// => [3, 5, 7]
// Ravr style
map(compose(add(1), multiply(2), subtract(__, 1)), List(1, 2, 3));
// => [3, 5, 7]
Same as compose, but with the order inverted. This can be more readable when putting functions on separate lines.
List<String> words = List.of("xSIHTx", "xSIx", "xGNITSERETNIx");
assertThat(
join("... ", words.map(pipe(
Ravr::reverse,
Ravr::toLower,
Ravr::init,
Ravr::tail
))),
is("this... is... interesting")
);
Ravr provides map, ap, and flatMap.
Pattern | Standard name | Ramda name | Ravr name | Type signature |
---|---|---|---|---|
Functor | map | map | map | Functor m => (a -> b) -> m a -> m b |
Applicative | apply | ap | ap | Applicative m => m (a -> b) -> m a -> m b |
Monad | bind | chain | flatMap | Monad m => (a -> m b) -> m a -> m b |
Due to limits in Java's type system these currently only work on Lists, Options, Traversables and Futures.
Lenses only work on types that implement the included Copyable interface, which is a simplified version of the Cloneable interface. The simplest way to implement it is wrapping the clone function:
@Getters // lombok
@Setters // lombok
@AllArgsConstructor // lombok
class Thing implements Copyable<Thing> {
String name;
int quality;
@Override
public Thing copy() {
return safeClone(() -> clone());
}
}
Note: Your IDE might tell you to replace the lambda with a method reference. This might not work because of reasons.
You can create a lens using a pair of getters and setters. You can use the lens in combination with get, set and over:
Lens<Thing, String> name = lens(Thing::getName, Thing::setName);
Lens<Thing, Integer> quality = lens(Thing::getQuality, Thing::setQuality);
Thing lookingGlass = new Thing("looking glass", 5);
get(name, lookingGlass); // "looking glass"
Function1<Thing, Thing>
improve = pipe(
set(name, "ten times better"),
over(quality, multiply(10))
);
Thing betterThing = improve.apply(lookingGlass);
get(quality, betterThing); // 50
get(quality, lookingGlass); // 5 (not changed)
You can concatenate the content of a List<Option<X>> to List<X> with the concatOptions function.
List<String> strings = List(">>>>", "", "====");
pipe(
head(), // List.of(Option.some(">"), Option.none(), Option.some("="))
concatOptions(), // List.of(">", "=")
join(">") // ">>="
).apply(strings);
Icon | Meaning |
---|---|
✅ | Works |
😐 | Works with issues |
Not implemented | |
✖️ | Not planned |
💠 | Bonus function not originally included in Ramda.js |
This list is generated automatically and slightly inaccurate right now.
Status | Function | Note |
---|---|---|
✅ | add | |
addIndex | ||
✅ | adjust | |
✅ | all | |
allPass | ||
✅ | always | |
and | ||
✅ | any | |
anyPass | ||
✅ | ap | |
aperture | ||
✅ | append | |
✅ | apply | |
applySpec | ||
✅ | ap_List | |
✅ | ap_Option | |
✅ | apᐸListᐳ | |
✅ | apᐸOptionᐳ | |
ascend | ||
assoc | ||
✖️ | assocPath | |
binary | ||
bind | ||
both | ||
call | ||
chain | ||
clamp | ||
✖️ | clone | |
comparator | ||
✅ | complement | |
compose | ||
composeK | ||
composeP | ||
✅ | concat | |
💠 | concatOptions | |
cond | ||
construct | ||
constructN | ||
✅ | contains | |
converge | ||
💠 | count | |
countBy | ||
curry | ||
curryN | ||
✅ | dec | |
✅ | defaultTo | |
descend | ||
difference | ||
differenceWith | ||
dissoc | ||
dissocPath | ||
divide | ||
drop | ||
dropLast | ||
dropLastWhile | ||
dropRepeats | ||
dropRepeatsWith | ||
dropWhile | ||
either | ||
empty | ||
endsWith | ||
✅ | eq | |
eqBy | ||
eqProps | ||
equals | ||
evolve | ||
F | ||
✅ | filter | |
find | ||
✅ | findIndex | |
findLast | ||
findLastIndex | ||
✅ | flatMap | |
✅ | flatMap_List | |
✅ | flatMap_Option | |
✅ | flatMapᐸListᐳ | |
✅ | flatMapᐸOptionᐳ | |
flatten | ||
flip | ||
✅ | forEach | |
forEachObjIndexed | ||
fromPairs | ||
✅ | get | |
✅ | groupBy | |
groupWith | ||
gt | ||
gte | ||
has | ||
hasIn | ||
✅ | head | |
✅ | head_String | |
✅ | headᐸStringᐳ | |
identical | ||
✅ | identity | |
✅ | ifElse | |
✅ | inc | |
indexBy | ||
indexOf | ||
init | ||
innerJoin | ||
insert | ||
insertAll | ||
intersection | ||
intersectionWith | ||
intersperse | ||
into | ||
invert | ||
invertObj | ||
invoker | ||
is | ||
isEmpty | ||
isNil | ||
✅ | isNone | Replacement for isNil, returns true for Option.none(). |
✅ | isSome | Replacement for complement(isNil), returns true for Option.some("whatever"). |
✅ | join | |
💠 | joinOption | Like join, except that it returns nothing when joining empty lists. |
juxt | ||
keys | ||
keysIn | ||
last | ||
lastIndexOf | ||
length | ||
✅ | lens | |
lensIndex | ||
lensPath | ||
lensProp | ||
lift | ||
liftN | ||
lt | ||
lte | ||
✅ | map | |
mapAccum | ||
mapAccumRight | ||
💠 | mapLeft | Maps the left side of an Either |
💠 | mapLeft_Either | |
💠 | mapLeftᐸEitherᐳ | |
mapObjIndexed | ||
✅ | map_Either | |
✅ | map_List | |
✅ | map_Option | |
✅ | mapᐸEitherᐳ | |
✅ | mapᐸListᐳ | |
✅ | mapᐸOptionᐳ | |
match | ||
mathMod | ||
max | ||
maxBy | ||
mean | ||
median | ||
memoize | ||
memoizeWith | ||
merge | ||
mergeAll | ||
mergeDeepLeft | ||
mergeDeepRight | ||
mergeDeepWith | ||
mergeDeepWithKey | ||
mergeWith | ||
mergeWithKey | ||
min | ||
minBy | ||
modulo | ||
multiply | ||
nAry | ||
negate | ||
✅ | none | |
✅ | not | |
nth | ||
nthArg | ||
✅ | nullTo | |
o | ||
objOf | ||
of | ||
omit | ||
once | ||
or | ||
✅ | over | |
pair | ||
partial | ||
partialRight | ||
partition | ||
path | ||
pathEq | ||
pathOr | ||
pathSatisfies | ||
pick | ||
pickAll | ||
pickBy | ||
pipe | ||
pipeK | ||
pipeP | ||
pluck | ||
✅ | prepend | |
product | ||
project | ||
prop | ||
propEq | ||
propIs | ||
propOr | ||
props | ||
propSatisfies | ||
✅ | range | |
💠 | rangeC | Closed range |
reduce | ||
reduceBy | ||
reduced | ||
reduceRight | ||
reduceWhile | ||
reject | ||
remove | ||
😐 | repeat | Can't be curried. |
replace | ||
✅ | reverse | |
scan | ||
sequence | ||
✅ | set | |
slice | ||
sort | ||
✅ | sortBy | |
sortWith | ||
split | ||
splitAt | ||
splitEvery | ||
splitWhen | ||
startsWith | ||
subtract | ||
sum | ||
symmetricDifference | ||
symmetricDifferenceWith | ||
T | ||
✅ | tail | |
take | ||
takeLast | ||
takeLastWhile | ||
takeWhile | ||
tap | ||
test | ||
times | ||
✅ | toLower | |
toPairs | ||
toPairsIn | ||
toString | ||
✅ | toUpper | |
transduce | ||
transpose | ||
traverse | ||
trim | ||
tryCatch | ||
✖️ | type | |
unapply | ||
unary | ||
uncurryN | ||
unfold | ||
union | ||
unionWith | ||
uniq | ||
uniqBy | ||
uniqWith | ||
unless | ||
unnest | ||
until | ||
update | ||
useWith | ||
values | ||
valuesIn | ||
view | ||
when | ||
where | ||
whereEq | ||
✅ | without | |
xprod | ||
✅ | zip | |
zipObj | ||
✅ | zipWith | |
_isArrayLike |
Other Ramda functions will be added as needed.
The scope of this library is to port Ramda. Extra functions like concatOptions should be the exception. Contact me on Twitter.
Licensed under the LGPL v3, see the LICENSE file for details.