A first class function is one where the function is available on its own. C, C++, and Ruby allow this approach. Java requires the function to be tied to a class and only provides a metadata representation of it, even if that class is merely a static collection of functions. C# supports first class functions with lambdas (which are based off of lambda calculus) and delegates.
Ruby is one of the languages that truly supports first class functions. The difference is that not only can you define functions on their own, but you can pass them as arguments and invoke methods on them. Check out Ruby's Proc object which is used to represent an arbitrary block of code.
The end result of having first class functions is the fact that it lends to some very powerful and flexible coding constructs. This is distinctly different than hacking around first class functions using the reflection API.
Java doesn't have full support of first class functions. The reflection API can give you some semblance of first class functions if the Method
object is referencing a static
method. In essence you can invoke a static method like this:
Method reference = mathClass.getMethod("sqrt");
// NOTE: the first parameter is for the object instance,
// but for static methods it is ignored
double answer = (double)reference.invoke(null, 4);
As soon as you are working with an instance method, you lose that first class function ability. You might be able to hack together some reflection based delegate support similar to C#, but the resulting code will be much slower. The "delegate" would take care of keeping the object reference for future invocations.
How many lines of code are in the following program?
#include <iostream>
int main()
{
std::cout << "Hello, world!\n";
return 0;
}
You probably answered 7 (or 6 if you didn't count the blank line, or 4 if you didn't count the braces).
Your compiler, however, sees something very different:
~$ cpp hello.cpp | wc
18736 40822 437015
Yes, that's 18.7 KLOC just for a "Hello, world!" program. The C++ compiler has to parse all that. This is a major reason why C++ compilation takes so long compared to other languages, and why modern languages eschew header files.
A better question would be
Why does C++ have header files?
C++ was designed to be a superset of C, so it had to keep header files for backwards compatibility.
OK, so why does C have header files?
Because of its primitive separate compilation model. The object files generated by C compilers don't include any type information, so in order to prevent type errors you need to include this information in your source code.
~$ cat sqrtdemo.c
int main(void)
{
/* implicit declaration int sqrt(int) */
double sqrt2 = sqrt(2);
printf("%f\n", sqrt2);
return 0;
}
~$ gcc -Wall -ansi -lm -Dsqrt= sqrtdemo.c
sqrtdemo.c: In function ‘main’:
sqrtdemo.c:5:5: warning: implicit declaration of function ‘printf’ [-Wimplicit-function-declaration]
sqrtdemo.c:5:5: warning: incompatible implicit declaration of built-in function ‘printf’ [enabled by default]
~$ ./a.out
2.000000
Adding the proper type declarations fixes the bug:
~$ cat sqrtdemo.c
#undef printf
#undef sqrt
int printf(const char*, ...);
double sqrt(double);
int main(void)
{
double sqrt2 = sqrt(2);
printf("%f\n", sqrt2);
return 0;
}
~$ gcc -Wall -ansi -lm sqrtdemo.c
~$ ./a.out
1.414214
Notice that there are no #include
s. But when you use a large number of external functions (which most programs will), manually declaring them gets tedious and error-prone. It's much easier to use header files.
How are modern languages able to avoid header files?
By using a different object file format that includes type information. For example, the Java *.class file format includes "descriptors" that specify the types of fields and method parameters.
This was not a new invention. Earlier (1987), when Borland added separately-compiled "units" to Turbo Pascal 4.0, it chose to use a new *.TPU
format rather than Turbo C's *.OBJ
in order to remove the need for header files.
Best Answer
That's the right answer, though. The language design team (Gosling, Sheridan, Naughton, later Bill Joy, Ken Arnold, etc.) decided headers caused more problems than they solved. So they designed them out, and demonstrated that they could create a perfectly useful language without the need for them.
From Section 2.2.1 of the Java Language Environment white paper:
Redundant definitions, keeping files in sync, conflicting definitions, hidden definitions--none of these occur in Java, because you don't have headers. If you want to see a bare class definition, you can generate one from a .java file directly--e.g. most IDEs will show you the structure of a class in a sidebar, which amounts to the same thing.