call operator and orthogonality with existing VM internals

Jakob Praher jp at hapra.at
Tue Mar 9 04:23:40 PST 2010


Dear Neal,

thanks for your reply.


Neal Gafter schrieb:
> Jakob-
>
> I did not see your original message, but I have some thoughts:
Interesting that the mail itself did not hit the list.
>
> o I do not agree that it is practical to blur the distinction between
> statement and expressions in Java's future.
I think there is some dichotomy in language constructs due to the reason 
that features are piled on top of existing constructs. Project lambda 
basically allows you to take a block of statements (with bounded 
variables) as a callable object. So the philosophical issue is whether a 
block should be an expression.

mySychronized( #(Object x) { ... } )
vs
synchronized (x) { }

I meant refactoring as a method to think about our axioms. I have to 
confess I am a little bit torn on the issue as well and I have not come 
up with a good solution to the problem. To me everything boils down to 
the point that we have to syntactically slight modified constructs that 
teach you the opposite (Blocks are statements, Lambdas are expressions) 
and also have constructs such as "synchronized" that also take blocks as 
arguments.

> o The ability to 'shortcut" the call operator x.call(e) as x(e) raises
> some difficult issues with name lookup that have not yet been solved,
> which is why a different syntax is being considered.
Do you have any details on that?
I think another interesting idea would be that if an interface only 
declares one public method this public method name does not have to be 
used as a designator for the method call:

E.g.
interface Runnable {
   public void run() ;
}
Runnable r = ...;
r();

Overloading could be an obstacle to be overcome in this scenario. But by 
defining "one method" as "one method whose signature matches  a given 
call expression".

E.g.
interface RunnableWithOrWithoutArguments {
    public void run(Object o);
    public void run();
}

RunnableWithOrWithoutArguments x = ?;
x();
x(new String());
would both be unambigious.

o Functions as interfaces is one option explored in detail in BGGA.
> The alternative of using MethodHandle is being considered for project
> lambda.
What is your opinion on that? My motivation for functions as interface 
types is out of syntactic taste.

In some way I would favor a joined effort with the dynamic extensions to 
Java. On another note: The lambda project (other than introducing a new 
way to represent function) will not introduce any new bytecode, right? 
E.g. Does a lambda object expose a method that can be invoked 
internally? (E.g. via invokedynamic and friends?).

I will look at BGGA. The nice thing about function as interface the 
familiarity and compatibility with existing interfaces . The downside is 
that different arity is not expressible with current generics. But one 
could generate Function0...FunctionN

> o Currying and method references in the source should not require
> going through type-unsafe intermediaries such as reflection.
>
This was more for illustrative purposes. I chose bind not especially for 
currying but for binding a lambda to an existing method with reflection. 
FCM addresses this issue more type safe.

One could do currying using FCM and lambdas:

Function2<String,MyClass,String> method = MyClass#echo; 
Function1<String,String> f = lambda(String phrase) { return method(new MyClass(),phrase); } 

When should one function be subtype of another funciton?
Does covariancy is an issue for that? Something like that is also harder 
to express with interface types.

-- Jakob

> Cheers,
> Neal
>
> On Mon, Mar 8, 2010 at 9:25 AM, Jakob Praher <jp at hapra.at> wrote:
>> This line
>>   Function<String,String> echo = echoMethod.bind(this);
>> should actually be
>>   Function<String,String> echo = echoMethod.bind(myinstance);
>>
>> Jakob Praher schrieb:
>>> Dear List,
>>>
>>> I was thinking much about the syntax of the upcoming language changes
>>> regarding the introduction of
>>> * first class functions
>>> * first class function types
>>> * lambda expressions ("closures")
>>>
>>> While IMHO the best would be to refactor certain aspects of the language
>>> (e.g. blur the distinction between Statements and Expressions, especially
>>> treat "blocks" as expressions, change the call expressions to allow custom
>>> control flow constructs, ...).
>>>
>>> Since I am realistic in that such changes will not be doable for version
>>> 7, I think one should seek orthogonality and consistency in integrating
>>> these new constructs.
>>>
>>> I would suggest the following:
>>> * Add a call operator (e.g. a special purpose "call" method) that can be
>>> short-cutted to x() instead of x.call(...)
>>> * Treat a function as an instance of java.lang.Function<ReturnType, ArgT1,
>>> ..ArgTn> that implements this call operator
>>> * Add a special keyword "lambda" for creating an instance of a Function
>>> from a Block (this is in the tradition of "synchronized" and friends):
>>>    Function<Integer, Integer> square = lambda(int x) { return x*x ; }
>>>
>>> * Introduce a bind method that converts a method to its lamba form
>>> (currying the this away):
>>>    class MyClass {  String echo(String x ) { return x; } }
>>>    Method echoMethod = myinstance.getClass().getMethod("test");
>>>    Function<String,String> echo = echoMethod.bind(this);
>>>    System.out.println( echo("Hello") );
>>>    System.out.println( echo.call("Hello") );
>>>
>>> Some Reasons:
>>> * Is IMHO more consitent with current Java
>>> * Reflection concepts like Class, Method, ... are "magic VM" instances too
>>> * AtomicInteger.compareAndSet can be internally optimized to single CAS
>>> instruction too
>>>
>>> What do you think about this?
>>>
>>> -- Jakob
>>>
>>>
>>>
>>>
>>>
>>>
>>
>



More information about the lambda-dev mailing list