Show HN: Motif – Scala-like pattern matching with Java 8
github.com
github.com
- https://github.com/aol/cyclops
- https://github.com/poetix/octarine
- (good ol') http://www.functionaljava.org/
The syntax for these libraries is always a little wonky though. If only these libraries also had some sort of syntax preprocessor to make it more palatable. You could call it, I don't know, Scala, or something.
def bimap[C, X[_, _], D](g: Bijection[C, D])(implicit F: Bifunctor[X], evF: F[B] =:= Id[B], evG: G[A] =:= Id[A]): Bijection[X[A, C], X[B, D]] =
bijection(
F.bimap(_)(to(_), g.to(_)): Id[X[B, D]]
, F.bimap(_)(from(_), g.from(_)): Id[X[A, C]]
)It's unlikely that anyone cares about your opinion re: Scala's syntax and cherry-picked abuses thereof. I certainly do not. My comment was an attempt to point out the sarcasm in the root comment.
Have a nice day.
What a coincidence, I do not care about your opinion either!
I used Scala for 4+ years at a company that spent a non-trivial amount of time and resources speeding up its Scala builds (way more than 2000+ classes), sometimes doing sadly controversial things[1] to achieve that speedup. It was a real quality-of-life issue, and one of the reasons that compelled me to leave.
I'm using Java 8 now, and yes it has its warts and is nowhere near Scala wrt functional goodness, but I'm glad to be compiling and iterating a lot more quickly with the ability to use even a subset of the Scala stuff I missed.
[1] https://groups.google.com/d/msg/pants-devel/mcdllXQsYNg/96ZG...
(and FWIW I'd say that 2000+ classes - that's what, 600KLOC? - implies a project that should be split up with clear boundaries (i.e. separate release cycles, documented public APIs between them), if only for developer comprehensibility. How big is a Java project that provides the same amount of functionality, and how long does it take to compile? Crikey, 2000 classes...)
I can't say I understand that strategy completely but I have also never worked on machinery the size and complexity of Facebook or Twitter.
How much time did it take to compile, and how much time does the same 2000+ classes take to compile in Java?
Not often at all.
> I am talking regular development cycle, ie make a change, save/compile, check if it works etc.
sbt[1] supports incremental compilation and projects such as Play[2] leverage this to support "on-the-fly" recompilation while the container remains running.
1 - http://www.scala-sbt.org/0.13/docs/Understanding-Recompilati...
Odd... I just did a full compile of a Scala project I work on which has:
- 259 source files
- Contains dozens of macros[1]
- Results in 2097 classes (includes companion objects and anonymous types)
And it took 75 seconds on my laptop. As I mentioned in another reply, doing a full recompile is rarely needed but was done now to provide quantified metrics.
1 - http://docs.scala-lang.org/overviews/macros/overview.html
You may not be using all of scala's language features. I'm using java's features to the fullest. I compile in 6 seconds. You compile in 75 seconds. You may still prefer that trade off. After working with thousands of scala files (you have 259 source files? That's cute! I wish I could pinch your cheeks!) where a 75 second compile sounds like a fail-fast error, I think I will live happier with what Java 8 has, limited and warted though it may be.
Being a condescending asshole doesn't help you communicate with others. Frankly, it strengthens my opinion that you don't know how to organize a medium-sized project, since being able to do so obviates requiring to compile 2000+ files for each build _in any language_.
LOC isn't what should count though - there are cases where 1 line of Scala offers functionality that would take 10 or more lines of Java to implement.
public class MatchMap<T, U> {
private final Optional<T> opt;
private final U defaultValue;
private final AtomicReference<U> result = new AtomicReference<U>();
private MatchMap(Optional<T> pOpt, U pDefault) {
super();
opt = pOpt;
defaultValue = pDefault;
}
public MatchMap<T, U> whenMatch(Predicate<T> pPred, Function<T, U> pMapFn) {
if (result.get() != null) {
return this;
}
Optional<T> lFiltered = opt.filter(pPred);
if (lFiltered.isPresent()) {
result.set(pMapFn.apply(lFiltered.get()));
}
return this;
}
public MatchMap<T, U> whenEquals(T pExact, Function<T, U> pMapFn) {
return whenMatch(t -> pExact.equals(t), pMapFn);
}
public U resolve() {
return Optional.ofNullable(result.get())
.orElse(defaultValue);
}
public static <T, U> MatchMap<T, U> of (Optional<T> pOpt, U pDefault) {
return new MatchMap<T, U>(pOpt, pDefault);
}
}
The class Match is very similar, but takes consumer instead of Function and has some logic to allow several matches to be executed (if several predicates are ok), or only allow the first match to be executed. MatchMap.of(someOptional, defaultValue)
.whenEquals(MyEnum.VALUEX, v -> someFn(p1, p2))
.whenEquals(MyEnum.VALUEY, v -> otherFn(p1, p2))
.resolve(); match(enumValOpt)
.when(some(eq(MyEnum.VALUEX))).then(() -> someFn(p1, p2))
.when(some(eq(MyEnum.VALUEY))).then(() -> otherFn(p1, p2))
.orElse(defaultValue)
.doMatch();
It's a little longer than your example since there is support for more than just Optional, but it's pretty similar.http://javaslang.com/javadoc/1.2.0/javaslang/control/Match.h...