Effectively final

Tim Fox timvolpe at gmail.com
Thu Aug 18 09:42:09 PDT 2011


On 18/08/11 17:34, Howard Lovatt wrote:
> This thread is called "effectively final"; how are Actors an argument 
> in favor of capuring mutable state? Since the last thing you want to 
> do with Actors is pass something mutable as part of the message!
If you want a concrete example please take a look at this project: 
https://github.com/purplefox/node.x
>
> On 18/08/2011, at 11:00 PM, Tim Fox <timvolpe at gmail.com 
> <mailto:timvolpe at gmail.com>> wrote:
>
>> On 18/08/11 16:30, Howard Lovatt wrote:
>>> On 16/08/2011, at 10:45 PM, Tim Fox <timvolpe at gmail.com 
>>> <mailto:timvolpe at gmail.com>> wrote:
>>>
>>>> The point I was making was in response to your assertion that 
>>>> inherently serial code will become less common as time goes on. 
>>>> Actors frameworks (and other hybrid frameworks like node.x) are all 
>>>> based around inherently serial code, and I don't see them dying out 
>>>> yet.
>>>
>>> I don't get what you are driving at, you have been posting that 
>>> Lambdas should capture mutable local variables and have given Actors 
>>> as an example of why that is necessary.
>> No, I didn't give actors as an example of why lambdas should mutate 
>> local vars, I gave actors as a counterpoint to your assertion that 
>> serial code will become less common as time came on (Actor code is 
>> all serial and these frameworks are gaining in popularity)
>>
>> The point I was trying to make, in a nutshell, was this:
>>
>> Conventional wisdom Java concurrency involves letting many threads 
>> execute your objects and using synchronization and what-not to make 
>> those objects threadsafe. This is difficult. Concurrent programming 
>> is hard.
>>
>> There are other ways of making scalable concurrent systems that don't 
>> involve having your code executed by multiple threads concurrently. 
>> (Actor model is one example of this, there are others) This is very 
>> desirable, since if you don't have to worry about making your code 
>> threadsafe, you can open up to a legion of web developers who 
>> otherwise would find concurrency too hard.
>>
>> My bet is the latter type of concurrent systems will eventually 
>> become more popular. So... if in this future, developers will be 
>> writing islands of single threaded coded, then it's safe to use 
>> lambdas that mutate local vars in those islands since zero race 
>> conditions are guaranteed.
>>
>> So far from being a throwback to the 50s, lambdas which mutate local 
>> vars could be a very useful tool for the next generation of 
>> frameworks. And if Java does not support such lambdas it will be 
>> sidelined as a good programming language for these kinds of frameworks.
>>
>> Allowing such mutation would allow you to implement "node.js-like" 
>> frameworks on the JVM. This is already possible in JS/Ruby/Groovy/etc 
>> but is currently very clunky in Java because of lack of lambdas - but 
>> even with Java 8 proposed lambdas it would still be clunky because of 
>> the effectively-final rule.
>>
>>
>>> What I demonstrated, was that for Actors you wouldn't use Lambdas 
>>> but classes and therefore your argument that Lambdas should capture 
>>> local mutables because of Actors is non sequitur.
>>>
>>> Now you seem to be saying that you were talking about particular 
>>> styles of code. Are you arguing about capturing mutables or not?
>>>
>>> PS Capturing a mutable variable in an Actor and passing it via 
>>> message to another actor is problematic. Again indicating that 
>>> Lambdas should not capture mutable state.
>>>
>>> PPS Also note that Scala has introduced map/reduce style collections 
>>> (presumably because people prefer these to Actors - which it already 
>>> has). Again map/reduce is best suited to not capturing mutable 
>>> variables.
>>>
>>>> Quite the opposite, I see them getting more popular :)
>>>>
>>>> On 16/08/11 16:25, Howard Lovatt wrote:
>>>>> I don't see that the actor or FJ type frameworks are effected 
>>>>> much, because the messages are immutable, e.g. a standard actor 
>>>>> example:
>>>>>
>>>>> http://java.dzone.com/articles/scala-threadless-concurrent
>>>>>
>>>>> Recoded in Java would be something like this:
>>>>>
>>>>> public class Actor extends FJTask {
>>>>>   private Queue messages ...
>>>>>   public void accept( final Object message ) ...
>>>>>   public Object acceptAndReply( final Object message ) ...
>>>>>   public Future<Object> acceptAndReplyLater( final Object message 
>>>>> ) ...
>>>>>   protected void reply( final Object response ) ...
>>>>> protected Object getMessage() ...
>>>>> }
>>>>>
>>>>> |10.||public class Accumulator ||extends| |Actor {|
>>>>> |11.||public void run() {|
>>>>> |12.||int sum = ||0;|
>>>>> |13.||for(;;) {|
>>>>> |14.|final Object message = getMessage();
>>>>> |15.|if ( message instanceof |Accumulate ) { ||  sum += 
>>>>> ((Accumulate)message).n; ||}|
>>>>> |16.|else if ( message instanceof |Reset ) { sum = ||0; }|
>>>>> |17.|else if ( message instanceof Total ) {  reply(sum);  break;
>>>>> |18.||}|
>>>>> |19.||}|
>>>>> |20.||}|
>>>>> |21.||}|
>>>>>
>>>>>
>>>>> The lambdas might prove useful for the messages, that are 
>>>>> immutable anyway, but the actors themselves would always be 
>>>>> instances of a class because you need to be able to create more 
>>>>> actors as the program runs and you can't do this with a lambda (or 
>>>>> a closure many other language). As I said at the beginning I don't 
>>>>> see that an Actor framework would change much one way or the other 
>>>>> if Lambdas could mutate a variable or not.
>>>>>
>>>>> Cheers,
>>>>>
>>>>>  -- Howard.
>>>>>
>>>>> Sent from my iPad
>>>>>
>>>>> On 16/08/2011, at 6:57 PM, Tim Fox <timvolpe at gmail.com 
>>>>> <mailto:timvolpe at gmail.com>> wrote:
>>>>>
>>>>>> On 16/08/11 12:36, Howard Lovatt wrote:
>>>>>>> I think the correct decision has been made, inherently serial 
>>>>>>> code will become less common as time goes on.
>>>>>> The growing popularity of actor model implementations (actors of 
>>>>>> course
>>>>>> only allow serial execution of code in the actor), e.g. Erlang 
>>>>>> and Akka,
>>>>>> and the growing popularity of languages which are inherently serial
>>>>>> (e.g. JavaScript) are a clear counterpoint to your argument. Also 
>>>>>> look
>>>>>> at webworkers, node.js. I could go on.
>>>>>>
>>>>>> I'd argue the current trend is quite opposite to what you see. Non
>>>>>> serial code will become unusual (because concurrency is hard), and
>>>>>> serial code will become the norm (because it's easier to code,
>>>>>> especially for the web developer masses). Systems will scale by 
>>>>>> having
>>>>>> multiple "islands" of serial code (e.g. multiple actors in the 
>>>>>> actor model).
>>>>>>
>>>>>> Please note that just because all code is executed serially does not
>>>>>> mean you can't exploit parallelism. You can do fork/join type 
>>>>>> stuff by
>>>>>> sending messages to other "islands" and reassembling the results 
>>>>>> as they
>>>>>> come back.
>>>>>>>  Therefore optimizing new features for parallel execution is the 
>>>>>>> correct path to take and also constant with Java's past of 
>>>>>>> taking existing concepts into the mainstream. When Java was 
>>>>>>> introduced the concentration on objects and garbage collection 
>>>>>>> was not mainstream and was opposed by many. I think the same 
>>>>>>> will happen with mutable data and serial execution and it is 
>>>>>>> nice that Java is once again daring to be different and adhering 
>>>>>>> to the mantra that less is more.
>>>>>>>
>>>>>>> Cheers,
>>>>>>>
>>>>>>>  -- Howard.
>>>>>>>
>>>>>>> Sent from my iPad
>>>>>>>
>>>>>>> On 16/08/2011, at 4:56 PM, Steven Simpson<ss at comp.lancs.ac.uk 
>>>>>>> <mailto:ss at comp.lancs.ac.uk>>  wrote:
>>>>>>>
>>>>>>>> On 16/08/11 01:51, Stephen Colebourne wrote:
>>>>>>>>
>>>>>>>> [snip: lots of syntax options for permitting mutable locals]
>>>>>>>>> int #total = 0;
>>>>>>>>> list.apply(#{item ->   total += item});
>>>>>>>>>
>>>>>>>>> ie. a way to introduce a local variable that can be managed 
>>>>>>>>> safely.
>>>>>>>> For the simple example given, you could translate 'total' into an
>>>>>>>> AtomicInteger, but if there are other variables to be accessed, 
>>>>>>>> you'd
>>>>>>>> have to box them together, and make the whole lambda 
>>>>>>>> synchronize on it,
>>>>>>>> or at least from the first use of the box to the last.  Trying 
>>>>>>>> to patch
>>>>>>>> the call site like this doesn't seem to be particularly 
>>>>>>>> promising.  The
>>>>>>>> alternative is to require List.apply to make additional 
>>>>>>>> guarantees about
>>>>>>>> how it executes the lambda.
>>>>>>>>
>>>>>>>> Would it not be better to let List.apply get on with its potential
>>>>>>>> parallelism, and define other methods that do make extra 
>>>>>>>> guarantees,
>>>>>>>> e.g. that the lambda will be executed serially, or even on the 
>>>>>>>> caller's
>>>>>>>> thread?
>>>>>>>>
>>>>>>>> Tim's cases include, for example, setTimeout(int, Runnable), 
>>>>>>>> which must
>>>>>>>> make such a guarantee, if only informally in its documentation. 
>>>>>>>>  To be
>>>>>>>> more formal:
>>>>>>>>
>>>>>>>>    * Declare setTimeout(int, @Callback Runnable).
>>>>>>>>    * When a lambda is assigned to a @Callback Runnable, allow the
>>>>>>>>      lambda body to mutate locals (without error or warning).
>>>>>>>>    * Don't permit a @Callback Runnable (which is tainted) to be
>>>>>>>>      assigned to a plain Runnable (without error or warning).
>>>>>>>>
>>>>>>>> This way, the likes of List.apply don't have to make any 
>>>>>>>> guarantees,
>>>>>>>> requiring the caller to make corresponding ones (automatically 
>>>>>>>> achieved
>>>>>>>> by not being generally allowed to mutate locals).  Meanwhile, 
>>>>>>>> setTimout
>>>>>>>> makes additional guarantees, to the convenience of the caller, 
>>>>>>>> who is
>>>>>>>> specially permitted to mutate locals.
>>>>>>>>
>>>>>>>> Cheers,
>>>>>>>>
>>>>>>>> Steven
>>>>>>>>
>>>>>>
>>>>>>
>>>>
>>



More information about the lambda-dev mailing list