Skip to main content

Functions/Methods as first class objects

27 replies [Last post]
dondi_imperial
Offline
Joined: 2004-11-22

I want to see Java be the first (i think) mainstream programming language to treat functions as first class objects. I think now that java 5 supports dynamic instrumentation this will be possible (easy?) to implement, this in a type safe manner, in Mustang.

If we had this feature we would be able to express general concepts/ideas as procedures. This would also clean up a lot of the event handler code that we are so used to. Instead of having to pass a whole object as a listener, when what we really want is to have a function run as events are generated, we just pass in the function.

Dondi

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
jwenting
Offline
Joined: 2003-12-02

> > If you want methods as objects it's already
> available
> > using reflection b.t.w.
>
> Yes but without the clarity and type safety of having
> as first class objects. Plus it is a hack to make
> functions appear more like first class objects.

no, reflection gives you a complete object for a method or variable of any type.
The Method object IS the method.
No need to provide yet another duplicate architecture in the language to do something we can do already.

carlosayam
Offline
Joined: 2004-10-14

> > > If you want methods as objects it's already
> > available
> > > using reflection b.t.w.
> >
> > Yes but without the clarity and type safety of
> having
> > as first class objects. Plus it is a hack to make
> > functions appear more like first class objects.
>
> no, reflection gives you a complete object for a
> method or variable of any type.
> The Method object IS the method.
> No need to provide yet another duplicate architecture
> in the language to do something we can do already.

No, reflection gives you a hack into the Java VM (call it API if you prefer). Functions as "first class objects" means that they are understood-by/part-of the language, i.e. at the syntax level and handled by the compiler not the programmer!

dondi_imperial
Offline
Joined: 2004-11-22

Because Java is now part of the curriculum (at least where I'm from) in most computer science courses an unexpected side effect of adding this feature to Java would be that teachers would be able to teach functional programming using Java. This would decrease the amount of syntax that the student would need to learn (because he/she would not have to learn another language to learn a new concept) and increase the conceptual knowledge that they could gain.

murphee
Offline
Joined: 2003-06-10

So... you want to turn Java into a functional language just so that teachers only have to teach *one* language?

Generally: I think learning several completely different languages (Java: OOP,managed memory; C: structured programming, own memory management; SML: functional, managed memory;,...) is a benefit. It's a nuisance at first, but it broadens your view. At my University (TU Graz) we did exactly that (we got taught: C, SML, Java in that order), and this gives you the best of all worlds. BTW *only* learning Java is not a good idea; students should be exposed to manual memory management at least once in their life, so they can actually see the advantages of managed memory.

dondi_imperial
Offline
Joined: 2004-11-22

> So... you want to turn Java into a functional
> language just so that teachers only have to teach
> *one* language?

No, so I could use it to express common patterns, in a clean and readable way, instead of having to duplicate code.

> Generally: I think learning several completely
> different languages (Java: OOP,managed memory; C:
> structured programming, own memory management; SML:
> functional, managed memory;,...) is a benefit. It's a
> nuisance at first, but it broadens your view. At my
> University (TU Graz) we did exactly that (we got
> taught: C, SML, Java in that order), and this gives
> you the best of all worlds. BTW *only* learning Java
> is not a good idea; students should be exposed to
> manual memory management at least once in their life,
> so they can actually see the advantages of managed
> memory.

I did not say that this is the reason why I feel this should be included in Mustang I was just stating another possible benefit.

Yes I agree that you should "learn" as many different programming languages as you can but sometimes this is not the case. Sometimes Java is the only language that is taught and having this feature in the language will result in having the student learn a different concept in the context of Java.

denisw
Offline
Joined: 2005-01-03

I think the solution would be delegates. They would store fuctions that fullfil the return and parameter type.
Look at this decleration (syntax like in C#):

public delegate void Foo(String bar);

A developer could then write something like:

Foo f = new Foo(somObj.work);
f.call("string");

And fuctions could use those delegates as parameter or return type:

public void bla(Foo f) {
//...
}

matthewthms
Offline
Joined: 2004-06-30

I totally agree with most of whats been said, i.e. it would be a powerful feature, but also could cause problems to new users, in education etc, just an idea, but what about using metadata tags, to mark the function/method passes explicitly? this would stop accidental passing as mentioned above in the C++ example.

pete_kirkham
Offline
Joined: 2003-06-20

>Using function pointers is not a type safe or particulary pretty thing in either of these languages.

Just the other day in C++ I had a bug

bool isSetFlag;

...

bool Foo::isSet () { return isSet; }

rather than

bool Foo::isSet () { return isSetFlag; }

Pete

monika_krug
Offline
Joined: 2004-10-14

I think Sun is right, interfaces are not only sufficient, but better.

Monika.

dondi_imperial
Offline
Joined: 2004-11-22

> I think Sun is right, interfaces are not only
> sufficient, but better.
Sufficient? Yes. Better? Not always.

Interfaces are good and correct in many places but one place where they fall short is where you usually use single method interfaces. What you really want to model in your code is a generic pattern of execution but what you end up is a hierarchical model. While this is good a lot of the time there are some instances when you would want more flexibility.

Dondi

carlosayam
Offline
Joined: 2004-10-14

Also have a look at non-main stream languages (!?) of the ML familly like OCaml, which takes type safety to its last consequences without losing power.

However, I rather prefer a language where I can express patterns without the use of idioms (regular expressions over identifiers)... - yes, I don't like AspectJ approach to this.

I think we need the son of mother Java and father ML (Ocaml)...

No ideas yet either...

jwenting
Offline
Joined: 2003-12-02

Java is object oriented for a reason. What you're proposing would turn it into a procedural language with function pointers, which is what C is all about.

If you want methods as objects it's already available using reflection b.t.w.

dondi_imperial
Offline
Joined: 2004-11-22

> Java is object oriented for a reason. What you're
> proposing would turn it into a procedural language
> with function pointers, which is what C is all
> about.

Actually this is a concept from functional programming. In C function pointers are just ints meaning you can pass in use whatever int value you like in place of a function pointer and the compiler would happily say that your code is valid.

I think the fine folks working on the Java lang can come up with something a lot better than that and incorporate it into the java language in a way that does not break type safety or OOP (Like they did by making primitives non-objects).

> If you want methods as objects it's already available
> using reflection b.t.w.

Yes but without the clarity and type safety of having as first class objects. Plus it is a hack to make functions appear more like first class objects.

denisw
Offline
Joined: 2005-01-03

Actually, C function pointers are a good thing. But they aren't typesafe. Anyway, a function-pointer use like

public void Foo(void bar(String, int)){
//...
}

or

public void Foo(void(String, int) bar){
//preferred by me
}

wouldn't be type-unsafe at all. Variable declerations like

String s = "Some String";
String(int, int) foo = s.substring;
foo(3, 6);

would be possible (although my example is brings no practical advantage...).

dgreenbean
Offline
Joined: 2003-12-08

+1

I am pretty sure there are other languages where functions are first class objects, but I still think this is a major feature missing from Java.

david_hall
Offline
Joined: 2003-06-12

Have you looked at the various open source projects that are working in this area? These are the ones that I know of, and I'd be interested in hearing about any that I've missed, as I maintain a links page to all of the other projects that cover similar ground.

jga: http://jga.sf.net/
mango: http://www.jezuk.co.uk/cgi-bin/view/mango
lambda4j: http://savannah.nongnu.org/projects/lambda4j/
jakarta commons collections: http://jakarta.apache.org/commons/collections/
jakarta commons functor: http://jakarta.apache.org/commons/sandbox/functor/index.html

You might find something in one of these projects that gets fairly close to what you're after.

David Hall
http://jga.sf.net/
http://jroller.com/page/dhall/

dondi_imperial
Offline
Joined: 2004-11-22

> Have you looked at the various open source projects
> that are working in this area? These are the ones
> that I know of, and I'd be interested in hearing
> about any that I've missed, as I maintain a links
> page to all of the other projects that cover similar
> ground.

No but those (I'm guessing of course) are all extensions to the language. I'd rather we have them native to java.

jwenting
Offline
Joined: 2003-12-02

> > Have you looked at the various open source
> projects
> > that are working in this area? These are the
> ones
> > that I know of, and I'd be interested in hearing
> > about any that I've missed, as I maintain a links
> > page to all of the other projects that cover
> similar
> > ground.
>
> No but those (I'm guessing of course) are all
> extensions to the language. I'd rather we have them
> native to java.

Java is extensible using libraries for a reason.

Why not have Sun scour the entire internet and turn EVERY single classfile it finds into a core language feature?
That way everyone would be happy to see his pet project included in the core languate and the opponents of Java would also be happy as the language would have become instantly a behemoth that noone can hope to use.

dondi_imperial
Offline
Joined: 2004-11-22

> Java is extensible using libraries for a reason.
>
> Why not have Sun scour the entire internet and turn
> EVERY single classfile it finds into a core language
> feature?
> That way everyone would be happy to see his pet
> project included in the core languate and the
> opponents of Java would also be happy as the language
> would have become instantly a behemoth that noone can
> hope to use.

Making functions first class objects is different from adding a third party library into the Java API. This introduces a new way to abstract the details of common computational patterns in Java. Currently if you want to abstract a common pattern (say summations) you would have to, step outside Java and, write in some sort of scripting language (Jython, Groovy...). While this way (embedding a scripting language in Java) works it is a workaround. There is ABSOLUTELY no way to do this in the Java language without duplicating code.

I feel that this feature would add something valuable to our Java toolkit and would be a nice addtion to our arsenal in the battle to write cleaner and more readable code.

Dondi

eirikma
Offline
Joined: 2004-04-23

Simula-67, the very first object oriented programming language, had this pretty well sorted out (though some functionality i omit here made GC cumbersome). They had inner methods and method parameters, tools that were very powerfull, especially for working with collections. It is like the power of functional programming with simplicity of java syntax.

Pretty much, the rules (at least the ones i propose being made part of java) are/were as follows:

A:
Anywhere you can have a declaration, you can declare a variable, a class or a procedure (method). That is, in methods, class bodies and object initalizers. In java, this translates to: anywhere you can declare a inner class (even anonymous), you can declare a method.

B:
Methods can have parameters that are primitive types, reference types or methods (classes and objects as well in simula but that was a very stupid mistake). These method-parameters should be fully specified in terms of their parameters and return values (which serves as a verbose type specifier for a method parameter/reference).

C:
A method must have a return value that is a primitve or a reference. methods can have method parameters, but not method return values. Regular function-pointers don't exist. All occurances of the name of a function is an invocation of that function (just as today's java), except for
- the definition of a method (or inner method)
- the declaration of a method parameter
- the passing of a method parameter.

D:
As a consequence, methods can never be passed out of its thread or out of its runtime scope.

E:
methods declared inside methods can have access to all the local variables of its enclosing method, since there is no way the body of the inner method can run without the outer method already being on the callstack. Today, anonymous classes only have access to a copy of the final variables, and that is not the same.

The andvantage is that many uses of heap-allocated iterators and anonymous classes can be omitted. while heap allocation is almost as fast as stack-allocation, it creates a lot of garbage, and thus garbage collections.

The following suggested syntax should demonstrate the power. look at the last line of the last method.
how many heap objects would you need to create today to get the same result in such short code?

// new methods as of jdk 5.0:
interface java.util.Collection {

// invokes "callback" for each member of the set.
// returns this collection

Collection forEach( void callback(E member) );

// invokes "criteria" and removes members of the
// set for which "criteria" returns false.
// returns this collection

Collection filter( boolean criteria( E member ) );

} // end interface Collecition

// demonstration class

class NumberSet {
ArrayList numbers = new ArrayList();

int find2ndSmallest() {
Integer smallest = null, second = null;

// inner method
void CB( Integer i ){
if(smallest == null) {
smallest = i;
return;
}
if( smallest.intValue() >= i.intValue() ){
second = smallest;
smallest = i;
}
} // end inner method

numbers.forEach( CB );
return second.intValue();

} // end outer method

// finds the elements that can be divided by
// the second smallest member

Collection findDivisibleBySecond() {
int second = find2ndSmallest();

boolean divisible(Integer i){
return (i.intValue() % second == 0);
}

return numbers.clone().filter(divisible);

} // end method

} // end class

In theory, one can construct scenarios where it is ambigous if the programmer intends to pass the inner method as a parameter or to call the inner method and pass the result. In practice this problem is just as small as the ambigousness around passing 'null'.

dondi_imperial
Offline
Joined: 2004-11-22

I agree with almost everything you said. One thing I don't agree with is this:
> C:
> A method must have a return value that is a primitve
> or a reference. methods can have method parameters,
> but not method return values. ....
> D:
> As a consequence, methods can never be passed out of
> its thread or out of its runtime scope.

Why would you leave this out? This would indeed add complexity to poorly written programs but woud add a lot off power for those who know/learn how to use them. I'm just being anal here but if you leave this out methods would not be first class objects :D.

Dondi

tjpalmer
Offline
Joined: 2004-07-16

C already has this.

C++, Python, Perl, and others already have this. In the case of Python, at least, it will auto-bind the object context for methods, too. (Limited currying.)

C# mostly has this, too, in the form of delegates (again with limited currying). This was one of the big anti-J++ arguments back in the day. Microsoft wanted type-safe first-class functions, and Sun didn't. Sun said that interfaces are sufficient.

Personally, I'd be fine with Sun's plan, but they really ought to make the should-be-common case of single-method interfaces easier to do.

That might be able to appease both camps.

And I agree that runtime byte code twiddling should be able to keep jar files smaller, too. I don't have an exact proposal or anything, though.

dondi_imperial
Offline
Joined: 2004-11-22

While it could be argued that C and C++ have this the implementation in both of these languages are kludgy and limited at best. Using function pointers is not a type safe or particulary pretty thing in either of these languages.

As for C# yes they do have delegates but delegates force you work with a "special" syntax when dealing with functions. I personally feel that, though this is a bit better than having to use an interface, this is still does no make functions real first-class objects.

Python is not really a mainstream language (not like java and the others mentioned). Perl should be excluded because it is ugly (sorry). :p

What I would want is to be able to use functions as i would any other member of the language. You could say (although this is not really true) that you can already assign a procedure/function to a variable. You do that whe n you define a function. Ie.
[code]class C{
int sqr(int x){
return x * x;
}
}[/code]
You could say that the name sqr(int) is assigned the value {return x * x;}.

Now here is what I would like to see (Note/Disclaimer: It is not the syntax that I am proposing here is the ideas. I'm sure someone could come up with syntax that is a lot better than what I have here):

1. (Implied by the ability to store a function in variables) Annonymous/Literal functions - to be able to use fumctions as unnamed quantities. In scheme lambda is used here. ie.
[code](lambda (x) (* x x))[/code]
I have no idea how the systax would/could/should be in Java but I'm sure someone can help out here. It is not yet apparent why we would want to do this at this point but be patient.

2. We should be able to add sqr(int) to a collection or have an array int sqr(int)[].

3. We should be able to pass sqr(int) to another function.
ie.
[code]int cube(int x, int sqr(int)){
return sqr(x) * x;
}[/code]
4. We should be able to declare functions local to another function. ie.
[code]int iter(String[] arg){
void debug(String a){
System.out.println(a);
}
/* or even better
void debug(String a) = System.out.println;
*/
}[/code]
4. We should be able to return a function from another function. (This is where annonymous functions could come in useful) Consider the following code (stolen from "Structure and Interpretation of Computer Programs" and translated to Java(?)) to compute square roots. [b]Note again it is not the syntax that I am proposing but that these features be added to java.[/b]
[code]class N{
double average(int x, int y){
return (x + y)/2.0;
}
double(int) avgdamp(double(int) f){
/* This is where we could have used an annonymous function instead of defining it. */
double ret(int x){
return average(x, f(x));
}
return ret;
}
/*
* Fixedpoint is left as an exercise for the reader.
* It takes as an argument a function f and a double d
* and applies f repeatedly on d and the result of that
* [i]....f(f(f(f(f(d)))))[/i] until the result of
* subsequent calls does not change or changes less
* than a specified value.
*/
double fixedpoint(double(int) f, int x){
}

double sqrt(int x){
/* Another place for an anon function. */
double f(double y){
return x/y;
}
return fixedpoint(avgdamp(f), 1.0);
}
}[/code]

The point here is that now the code for the sqrt procedure shows clearly that sqrt root is defined in terms of fixedpoint and avgdamp and we did not have to store the results of these function calls in intermediate variables.

Dondi

tjpalmer
Offline
Joined: 2004-07-16

Okay. My example of a mainstream language with this feature should have been JavaScript. I think it has everything you've requested. (And it's a good list of feature requests, I admit.)

tjpalmer
Offline
Joined: 2004-07-16

One more comment. I'm not sure that the Java language itself should pick these features up. Java is already complicated, and I'm not sure how much more change it can take.

kcpeppe
Offline
Joined: 2003-06-15

+1 current syntax for aquiring a Method is a bit of a dog. Wouldn't a notation like MyClass.someMethod that would be resolved to a Method be nice? It would require some thought and experimentation to determine how to deal with all the cases.

pete_kirkham
Offline
Joined: 2003-06-20

The notation for method, field and construct can be all based on the extant one for methods in the API docs- the argument types are needed as part of the method signature, this form is vaguely familiar, and # doesn't conflict with any existing syntax:

AbstractAction#firePropertyChange(String, Object, Object)

But when do you really need this at compile time? Without a library of functional operators (such as applying the method to each element in a collection), it is still difficult to use the method as an object.

Maybe something along the lines of dynamic proxies so that you can then map the methods onto interfaces (whether done by reflection or bytecode generation) without having the boilerplate for executing the method via reflection.