3

Going through JOOL library from JOOQ which provides lots of Functional Interfaces and Utility classes on Streams.

My question is there are 1-16 parameter functional interfaces supported by this library. Do this makes sense at all? As I have always been in a practice to reduce the number of parameters in a method to 3. Though acceptable number varies according to different thought leaders on it. But no one says 16.

See reference links from StackOverflow itself:

what is the standard number of parameters that a java method should have?

Also, it provides a utility class Seq which looks like is limited to sequential processing only.

Can someone with good past experience using JOOL answer why I should be using JOOL as looks like lots of things it contains are of no use?

Vinay Prajapati
  • 7,199
  • 9
  • 45
  • 86
  • 1
    You should be thankful for 16 parameters. [.NET folks only get 8 for their tuples](https://msdn.microsoft.com/en-us/library/dd386921(v=vs.110).aspx), which clearly isn't enough. – Lukas Eder Dec 14 '17 at 08:48
  • Well I am disappointed first why we need so many and second why can't we make it more generic using varargs or something similar (A tweak might be required at its functionality ) – Vinay Prajapati Dec 14 '17 at 08:53
  • 2
    1) Like most languages, Java doesn't support higher-kinded generics. 2) You'd lose the type safety that is provided by jOOλ. If you don't care about type safety, just pass around `Object[]` and you're set. – Lukas Eder Dec 14 '17 at 09:00
  • that sounds like a better answer. If concerned about type safety create your custom impl or use some external library otherwise use varargs :) – Vinay Prajapati Dec 14 '17 at 09:03

2 Answers2

12

jOOλ author here.

The difficulty you seem to be having is the idea that ordinary methods in business logic and specific library functions are somewhat related. They're not. Let me explain:

An ordinary method in business logic ...

... should indeed not take many more than three arguments, because as soon as you exceed that number, chances are that some of your arguments are strongly connected in a way that it is worth re-designing them into a class.

That's object orientation basics and works well for a variety of use-cases.

A specific method / function in a more technical library ...

... on the other hand is not restricted to such object orientation design principles. In the case of jOOλ, the library actually works around a (several) language limitation(s), in particular the lack of first class tuple support.

Many languages out there (SQL being among the most prominent ones) support tuples, which are just like classes in Java with the difference of:

  • Being structurally typed as opposed to nominally typed
  • Having their attributes ordered (accessible by name and index) as opposed to having them in random order (accessible by name only)

Think of a Tuple16<T1, T2, ..., T16> as the same thing as a Java class with 16 named attributes (and getters / setters, if you like). Think of a Function16<T1, T2, ..., T16, R> as the same thing as a Java method that accepts such a class with 16 named attributes.

So, these differences are of mostly stylistic nature. There's not really a strict advantage of one approach over the other in general.

Now, if you're a functional / declarative programmer who happens to work with Java, the limitations of the Java language and the JDK APIs limit the way you reason about your programs. This is one of the reasons why jOOλ exists, to help these people pretend the Java language actually had tuples and functions applied to tuples, and in order to emulate that, well, jOOλ has to "overload" the same kind of function 16 times - 16 being an arbitrary upper limit (.NET limits tuples to degree 8, Scala limits them to 22).

Answering your specific questions

My question is there are 1-16 parameter functional interfaces supported by this library. Do this makes sense at all?

Yes, even if you usually only use the ones with lesser degree, you will occasionally find a Tuple16<T1, T2, ..., T16> useful, just like when you design classes, which mostly have only a few attributes, you'll find yourself writing an occasional class with 16+ attributes.

Though acceptable number varies according to different thought leaders on it. But no one says 16.

Free your mind from object oriented dogma. There's always a reason why a thought leader says something. It is true in a context, but never universally true. Have you ever written a SQL query with 16 columns? Sure you have. Why is it acceptable in SQL but not in Java?

Also, it provides a utility class Seq which looks like is limited to sequential processing only.

Yes, that's the main design goal. Sequential processing allows for quite a bit of additional functionality that doesn't make sense in parallel processing, yet is dearly missing from the JDK's Stream API.

Can someone with good past experience using JOOL answer why I should be using JOOL as looks like lots of things it contains are of no use?

If you do not see its use, then don't use it. But from your comments (you seem to prefer passing around Object[] over typed tuples), I think you do understand its use, you just don't want to write down the types, because what's an Object[], if not a poor man's, untyped tuple with random degree?

Lukas Eder
  • 211,314
  • 129
  • 689
  • 1,509
5

There is no set number of arguments in a function that I would consider best practice, I think you should use what you need without going to extremes, causing inefficiencies or making your code hard to read. If you find yourself with a function with 10 parameters, think twice if it makes sense (maybe it does).

There are several libraries that use functions that receive 10+ parameters:

The reasons for this is mainly compile-time type checking. Also you could argue improved efficiency, and perceived cleanliness.

Take for example Guava's of function:

ImmutableMap<K,V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4)

which is used like this:

Map<String, Integer> m = ImmutableMap.of("Ashlyn", 127, 
                                         "Abigaile", 128,
                                         "Alexis", 132,
                                         "Ashlynn", 132);

This function, that receives 8 parameters, provides:

Type safety

Because "odd" parameters are checked at compile time to be String and "even" parameters to be Integer). You can't do this with vararg functions because you'll need to declare the varargs parameter as Object..., losing the compile-time type checking.

Efficiency

You could get compile-time type safety by using an intermediate object like:

Map.ofEntries(entry("Ashlyn", 27), 
              entry("Abigaile", 28),
              entry("Alexis", 32),
              entry("Ashlynn", 32))

Which by the way exists in Java 9, but then you would be creating 4 intermediate objects that were not necessary with the 8-parameter version. You would be also creating an extra array object to hold the varargs objects.

Cleanliness

Compare the previous two snippets of code, the inclusion of entry() means more letters to type and read. This can be kind of subjective, but at least I prefer how the code looks without the inclusion of entries.

Why jOOλ?

jOOλ comes into play to account for these Java API deficiencies:

  • You have Function and BiFunction but you can't do something like TriFunction<Integer, String, Boolean, Double>. You'd have to sacrifice one of your parameters (or the type safety altogether) unless you use jOOλ.

  • Java lacks tuples altogether, you need to use either javatuples or jOOλ, unless you want to sacrifice the type safety again.

  • There are other deficiencies in Java's API that are not related to this question but that are addressed by jOOλ like (the one I like the most) having the ability to pass around a lambda that throws checked exceptions.

Daniel
  • 21,933
  • 14
  • 72
  • 101
  • looks like java has stopped to look up for better solutions at Oracle. It's insane to have 20 parameter method. – Vinay Prajapati Dec 14 '17 at 06:03
  • 1
    There are several pitfalls in Java8's new stuff (IMO), but this limitation in varargs comes from Java5 and I imagine it's something hard to fix inside of the JVM (I can't think of a good way to specify a repetitive varargs pattern, and maybe it'll not be so commonly used to justify implementing it). – Daniel Dec 14 '17 at 06:08
  • 1
    @Vinay can you name a prog language that has pair-wise, arbitrary length parameters, enforced at compile-time? The example above shows pretty well why functions with more than a handful parameters can be useful. – Jochen Bedersdorfer Dec 14 '17 at 06:10
  • @JochenBedersdorfer Won't go on that part but would remind of simple development convention when and why we should use Mapstruct or Lombok like libraries :). The answer lies in the fact today we might need more parameters or we improve our compiler so that we can accommodate more parameters but not by providing such external library. On another hand, I am happy to see the solution. Think about what happens when you need a method with 50 parameters and another with 40. Another library? – Vinay Prajapati Dec 14 '17 at 08:58
  • And to my exclamation java 9's 20 parameter theory is not good at all. What if I want a map of 11 K , V pairs? – Vinay Prajapati Dec 14 '17 at 09:01
  • 2
    @VinayPrajapati I agree that having these methods with 20 parameters is not ideal as it's caused by a limitation in Java. But so far this is the best workaround people have found (not just in Java, no language I know of has a perfect solution for this same problem), and we are stuck with that solution for now. Also, about the 11 "K,V" pairs, in that case you'd use the `Map.ofEntries` method, which doesn't have a limit on the number of pairs. – Daniel Dec 14 '17 at 18:52