/ravr

Primary LanguageJavaGNU Lesser General Public License v3.0LGPL-3.0

ravr logo

This is a partial port of the Ramda.js functional programming library to work with vavr types.

v0.0.11 (experimental, incomplete)

Adding it to your project

Maven

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>

Gradle

compile 'de.michaelzinn.ravr:ravr:0.0.11'

Curried functions & partial function application

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]

Function composition

You can compose functions in two ways.

Compose

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]

Pipe

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")
);

Functor, Applicative, Monad

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 (experimental)

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)

Other functions

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);

What's included

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

Future plans

Other Ramda functions will be added as needed.

Contributing

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.