Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Some interesting additions (Predicates, fixed Javadoc errors, Wrapped/Safe version of Unchecked/Sneaky) #6

Open
magicprinc opened this issue Oct 18, 2022 · 0 comments

Comments

@magicprinc
Copy link
Owner

First of all, thank you very much for your great projects (jOOQ and jOOλ) especially! I really enjoy to use them!

During of a migration of an old legacy project to Java 8 I have made several changes and additions to jOOλ and finally decided to make some of them public, because they could be interesting for broader auditory.

Most of the changes (except fixed errors) are simply "copy into" changes. So I can easily maintain the fork.

If I could do something for you (changes, PR-request) - I am always at your command.
Just one caveat.. As I already mentioned: my English level is "a smart dog" (Dogs understand everything, but can't speak).

A short list of additions:

  1. [completely optional] Gradle 7.5.1 build with Error-Prone
    https://errorprone.info/ - is a great statistical analyzer from Google. It is used at compile time to find problems in code. 

  2. Added Predicates (Predicate0- Predicate16) similar to Functions (Function0- Function16). The API is almost identical.

  3. Fixed Javadoc errors and Error Prone errors. And also some Javadoc and Error Prone warnings. So one can build javadoc.jar without disabling Java DocLint.
    Most of the Javadoc errors falling in three main categories: 
    a) unescaped < and >
    b) "* @see {@link " (e.g. * @see {@link Sneaky#biFunction(CheckedBiFunction)} ) - it must be either * @see  Sneaky#biFunction(CheckedBiFunction) or {@link Sneaky#biFunction(CheckedBiFunction)}. I have decided to go with "{@link" variant.
    c) Wrong order of code and pre tags. It must be pre than code.

  4. Sub-project/branch "jOOL" had one type End-of-lines and "jOOL-java-8" the other. So it wasn't easy to understand: are they the same? Now both branches are identical except 'module-info.java' and build scripts.

  5. Loops.java - tiny funny functional "external" loops. Quick and fast replacement for some nasty repetitive "while" and "for". Can be used occasionally as "poor man's JMH" (There is a version with warm-up and measurement).
    There is also a "multi-/nested for" version, with so many nested for loops as you like. Can be used as "forEach", Iterator or Seq version.
     

  6. [!!!] "Optional" wrapped/alternative/default-value or "Safe" version of Unchecked and Sneaky. Instead of throwing Exception, it optionally logs it and returns some value. 
    org.jooq.lambda.Wrap (a new sibling of Unchecked and Sneaky).
    org.jooq.lambda.Either (a Tuple2 descendant) is used as a Tuple equivalent of Java's Optional.

There are usually three methods for each functional primitive :
e) Function<T,Either<R>> function (CheckedFunction<T,R> unsafeFunction)
h) Function<T,R> function (CheckedFunction<T,R> unsafeFunction, BiFunction<T,Throwable,R> handler)
d) Function<T,R> functionDef (CheckedFunction<T,R> unsafeFunction, R def)

In case of failure (a thrown Throwable):
e) returns "Optional" Either
h) allows user to handle it
d) returns default value
(There is no Supplier version, because version h - can be used in this case either).

As you can also see, it uses more powerful handlers: they receive not only Throwable, but also all original parameters - so they can do something meaningful.

Wrap also has some very useful methods like:
• static boolean run (CheckedRunnable runSafely)
• static <T> Either<T> call (CheckedCallable<T> callSafely)
• static void throwIfError (Throwable t) throws Error, etc..

  1. Safe Runnable and Callable
    They can be used to easily implement similar "safe" behavior.
    One need to override
    V execute () throws Throwable
    or
    void execute () throws Throwable
    and use them as usual Runnable or Callable, but all unhandled Exceptions will be caught and logged.

Interestingly enough, that I didn't introduce dependency to any logger framework, although Slf4j or Log4j will be discovered and used. The official way opened for frameworks such a Spring is used plus static MethodHandle, which allows achieving "direct call" speed of calling Slf4j's and Log4j's Logger.warn. If both slf4j and log4j are absent – System.err will be used.

  1. Unit tests with 100% code coverage of newly added code.

  2. Small Demo project with some impressive examples
    https://github.com/magicprinc/jOOL/blob/main/jOOL/src/test/java/org/jooq/lambda/Demo202210Test.java

  3. [Add Predicate<Tuple[N]<T...>> Tuple.predicate(Predicate[N]<T...>) jOOQ/jOOL#391] Add Predicate<Tuple[N]<T...>> Tuple.predicate(Predicate[N]<T...>)
    Because I already have made Predicate0-16 it was easy to implement.

https://github.com/magicprinc/jOOL
https://github.com/magicprinc/jOOL/tree/feature

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant