Why are scala functions limited to 22 parameters?
There is no such limit. Even if the standard libraries only define up to Function22, you can define Function23 if you need it, up to the JVM limit. Or you can group arguments into tuples. Or you could just stop pretending that any function takes more than one argument:
a => b => c => d => e => ...
Curried functions can take as many arguments as you want, up to the limit of your stack size.
Functions and tuples are rewritten as objects by the compiler, and only Function0
through Function22
and Tuple0
through Tuple22
are defined. I think the limit of 22 is entirely arbitrary, but the reason for having a limit is not.
Think of it this way: to run a Scala application the classes needed to run it must be present. If the compiler would dynamically create classes for functions then those classes would not be included in the Scala library JAR, so you would have to include them in your application. That could work, but then you would have the problem of what the classes' fully qualified names should be: if they were the same for all apps then you would have clashes since libraries would contain the same classes, and if the names were not the same you would end up with incompatibilities -- functions from libraries wouldn't be the same as functions in your app.
Limit 22 has been dropped in dotty (Scala 3) by Drop function 22 limit #1758:
The limits of 22 for the maximal number of parameters of function types and the maximal number of fields in tuple types have been dropped.
Functions can now have an arbitrary number of parameters. Functions beyond
Function22
are erased to a new traitscala.FunctionXXL
and tuples beyondTuple22
are erased to a new traitscala.TupleXXL
. Both of these are implemented using arrays.
For example,
object drop22limit extends App {
val f23 = (x1: Int, x2: Int, x3: Int, x4: Int, x5: Int, x6: Int, x7: Int, x8: Int, x9: Int, x10: Int, x11: Int, x12: Int, x13: Int, x14: Int, x15: Int, x16: Int, x17: Int, x18: Int, x19: Int, x20: Int, x21: Int, x22: Int, x23: Int) => x1 + x2 + x3 + x4 + x5 + x6 + x7 + x8 + x9 + x10 + x11 + x12 + x13 + x14 + x15 + x16 + x17 + x18 + x19 + x20 + x21 + x22 + x23
val result = f23(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23)
println(result)
}
outputs 276
. For examples of interplay between arbitrary arity tuples and functions see Add generalized tupled functions abstraction #6568
It's mostly arbitrary, but there are some underlying limits on the JVM that dictate roughly what the limit needs to be.
The main issue is pattern-matching on case classes. If a case class allowed to be much bigger then the generated pattern-match code could very easily exceed the maximum valid method size. Everything else (Product, Function, Tuple, ...) just follows the 22-parameter limit that was therefore chosen for case classes.
Also... If you're writing functions/tuples with > 22 parameters then you're probably overdue for a redesign :)