Oddly enough, I 'discovered' functional programming in straight Java
(5 at the time), and object-oriented programming in Basic (Blitz Basic
2).
When Odersky taught me Java in '98 he commented on the functional aspects ... and that was 1.2
But that was after several years of Fortran, Modula-2, Lisp, and Miranda... alot of good that turned out to be ;)
One item which I have heard mention recently is that the for loop
syntax is potentially harmful to teach because the for loop with an
index is inherently only processable with a single thread vs the
foreach loop which can potentially use parallel processing.
I use mostly foreach loops but there is one situation in Java where I
seem stuck with using the indexed version. This may be a shortcoming
in Java because the order in which iteration is done does not matter.
The situation is when doing operations which involve copying or
deriving values from one array to another array. The foreach loop in
Java is fine for taking values out of an array but I don't think as
far as I have been able to find out
that these loops can be used for receiving values. In this case the
for loop with the index is used to get an element out of an array at a
given index and the derived value is stored in the destination array
at the same index.
For example:
Type[] types = Type.values();
char[] mnemonics = char[types.length];
for (int index = 0; index < mnemonics.length; index++) {
mnemonics[index] = types[index].getMnemonic();
}
//mnemonics will be an Array[Char]val mnemonics = Type.values map { _.getMnemonic }
//no support for Arrays, so it'll have to be a list, which means primitives can't be stored eitherfinal List<Type> typeList = Arrays.asList(Type.values())final List<Character> mnemonicList = convert(typeList, new PropertyExtractor("mnemonic"));//this needs to work, or we're back to a loop for Character unboxingfinal char[] mnemonics = mnemonicList.toArray(new char[0])
//no support for Arrays, etc, etc.final Function<Type, Character> lookupMnemonic = new Function<Type, Character> {Character apply(Type tpe) { return tpe.getMemonic }}final List<Type> typeList = Arrays.asList(Type.values())final List<Character> mnemonicList = Collections2.transform(typeList, lookupMnemonic)final char[] mnemonics = mnemonicList.toArray(new char[0])
I come across this situation a fair amount but don't think it can be
done in foreach style in Java though I think some kind of closure in
other languages would allow the source to be mapped to the destination
as I understand it.
--
You received this message because you are subscribed to the Google Groups "The Java Posse" group.
To post to this group, send email to java...@googlegroups.com.
To unsubscribe from this group, send email to javaposse+...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/javaposse?hl=en.
import fj.F;
import fj.data.Array;
Integer[] legs = Array(animals).map(new F<Animal, Integer>() {
public Integer f(Animal animal) {
return animal.legs;
}
}).array(Integer.class);
fj = Functional Java.
--
Joseph B. Ottinger
http://enigmastation.com
--
It still looks like it may not be possible yet in core Java without
using google collections or another external library. I suppose the
desire to be able to do this kind of things would be a driver for
wanting to add closure to Java.
I get the principle that what I am really doing is mapping one value
to another value (Remembering Haskell from University) and that order
does not really matter.
If it were an array of 8 values and a machine had 8 cores then
potentially the entire operation could be done together. The theory is
fair enough but I wonder about the overhead of breaking up something
like this over multiple threads and whether for more trivial
operations, the overhead of splitting up the computation and doing it
in parallel might outweigh the time savings of being able to do
parallel batches. I imagine there is some kind of threshold where the
parallel processing benefit is greater than the overhead. It may be a
lower threshold than I realise.
//the .par makes it parallel...val mnemonics = Type.values.par map { _.getMnemonic }
One item which I have heard mention recently is that the for loop
syntax is potentially harmful to teach because the for loop with an
index is inherently only processable with a single thread vs the
foreach loop which can potentially use parallel processing.
I use mostly foreach loops but there is one situation in Java where I
seem stuck with using the indexed version. This may be a shortcoming
in Java because the order in which iteration is done does not matter.
If you have referential integrity (the same function, with the same input always returns the same value, immutability is important here) and the functions have no side-effects (e.g println) then it's mathematically guaranteed that ordering won't matter. You can still have indices, they just don't need to be processed in-order.
For that matter, they needn't be on the same thread, processor or even computer!
This is the very essence of why so many are now advocating functional programming as such a good fit for concurrency.
>
> --
> Cédric
>
> This seems wrong. Just because the loop seems to be parallelizable doesn't mean it is. The compiler needs to know whether your iteration is ordering sensitive or not ("Is it okay if index 3 is treated before index 1?"). This hint is much more meaningful than whether the developer is using an index of foreach. The same applies to closures, LINQ or whatever comprehension walking mechanism you favor.If you have referential integrity (the same function, with the same input always returns the same value, immutability is important here) and the functions have no side-effects (e.g println) then it's mathematically guaranteed that ordering won't matter. You can still have indices, they just don't need to be processed in-order.
for (int a = 0; a < 100; a++)
array[a] = a * 2;
If I extracted a * 2 into a separate method:
for (int a = 0; a < 100; a++)
array[a] = doubleIt(a);
there's only one input, and it would be the same if I parallelised that loop.
Something like your example:
int soFar = 0;
for (int a = 0; a < 100; a++)
array[a] = soFar += a;
Here if I extract a method I get:
int soFar = 0;
for (int a = 0; a < 100; a++) {
soFar = addSome(soFar, a);
array[a] = soFar;
}
(eliding soFar is quite easy, but the problem remains)
This time you aren't calling the same function with the same inputs,
so even though addSome is referentially transparent (i.e., it
describes a function), parallelising it won't work.
2011/1/6 Cédric Beust ♔ <ced...@beust.com>:
2011/1/6 Cédric Beust ♔ <ced...@beust.com>:
Loops where each iteration does not depend on any other iteration can
be safely parallelised. That's the connection
2011/1/6 Cédric Beust ♔ <ced...@beust.com>:
--
All it takes is for the compiler to know what operations are
side-effect-ful and it can do all the necessary analysis.
So, for instance, it's perfectly doable without any hints for Haskell
These things often err on the conservative side, so as to not
introduce problems.
2011/1/6 Cédric Beust ♔ <ced...@beust.com>:
On 6 Jan 2011 20:45, "Cédric Beust ♔" <ced...@beust.com> wrote:
>
>
>
> On Thu, Jan 6, 2011 at 12:37 PM, Ricky Clarkson <ricky.c...@gmail.com> wrote:
>>
>> All it takes is for the compiler to know what operations are
>> side-effect-ful and it can do all the necessary analysis.
>
>
> It's still not enough: the loop might still be parallelizable even though it's performing side effect operations.
>
>>
>> So, for instance, it's perfectly doable without any hints for Haskell
>
>
> Are you sure? Remember: the only important factor here is whether the operations can be safely performed out of order.
>
Got it exactly! You can be certain that any loop is safely parallelizable so long as no iteration depends on a previous one.
This coupling can be direct, such as the addition of values in calculating the fibbonacci sequence (where integer addition exhibits referential integrity), or through side effects, such as printing and list to the console.
Haskell helps here by ensuring a lack of side effects, so it *is* relevant.
If iterations only depend on their index, then you can generate a list of indices first, and transform said list to output values in parallel. Take the example of printing to the console, the output lines could all be generated simultaneously and only printed afterwards, this shows how avoiding side effects helps concurrency.
It's even possible to go further than this. By using a fork-join approach, lines could also be concatenated in parallel, then printed in a single operation.
This is the sort of thing that functional languages can optimise automatically, using monad composition laws to prove when it's safe to parallelize in such a fashion, and doing so by manipulating the AST as an algebraic construct. But that's, admittedly, getting into very advanced territory.
On 11 Jan 2011 18:56, "Amihay Zer-Kavod" <ami...@gmail.com> wrote:
>
> By the way, about the main problem. Scala has a nice (but not very
> recommended) workaround:
>
That's due to change in the very near future.
Enhancements scheduled for the imminent 2.9 release mean that this will soon be the officially recommended way to create an application...
I'm a bit confused as to why Scala programmers have the gall to claim the moral high ground in regards to multi-core programming.
Certainly a language that is very good at letting you write code that runs well on multiple cores will have a function-esque taste, but scala isn't it.For example, scala has enshrined foldLeft and foldRight forever more as core language, by importing both of those by default as operators (i.e. "/:", as a token, is a fold operator in scala unless you go out of your way to unimport it). foldLeft is fundamentally *NOT* parallellizable! Its accumulator based, and accumulator is a magic word. It means: "This code has no hope whatsoever of ever running parallel".
I'd envision a language that truly takes this 'parallelize everywhere' principle seriously to be extensively conc-list based.conc-lists are like lisp's cons-lists (1 head element and a tail list), but instead have lists for both head and tail. A list is thus really a tree. If this tree is reasonably well balanced, operations on it that are not accumulation based can be aggressively parallelized.
By the way, conslists, mainstay of for example lisp, and very much associated with functional languages, are another one of those things that absolutely, positively, cannot be parallelized AT ALL. Looping through such a list takes O(n), and no amount of parallelization can fix that. You can kludge it by storing forward pointers in the list as an implementation detail (i.e. hotspot would be doing that), so another core can jump right in the middle of a list and start from there, but this is frightfully complicated; far more complicated that for example updating the JVM hotspot to recognize foreach loops, check if the code relies on sequential execution, and if not, paralellizing it. (That's not a good idea, see my earlier post, but it can be done).
--You received this message because you are subscribed to the Google Groups "The Java Posse" group.
To post to this group, send email to java...@googlegroups.com.
To unsubscribe from this group, send email to javaposse+...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/javaposse?hl=en.
The confusion is in your head. Scala programmers don't claim that high ground.
> For example, scala has enshrined foldLeft and foldRight forever more as core
> language, by importing both of those by default as operators (i.e. "/:", as
> a token, is a fold operator in scala unless you go out of your way to
> unimport it).
Let's rewrite that without the emotional crap: "Scala has foldLeft and
foldRight (and symbolic versions of those) in the standard library."
Yes, it does, but so what?
Why, are there some inaccurate judgements you might otherwise make
about Java based on those two classes?
java.util.Date is immutable, by the way.
I'm a bit confused as to why Scala programmers have the gall to claim the moral high ground in regards to multi-core programming.
+1
You'd also want to add reliability as a metric (this being one of the core selling points for actors), and compare against data flow concurrency as well.
> --
> Cédric
> I am seeing a lot of claims going unchallenged, such as the fact that
> the actor model is superior to the traditional java.util.concurrent
> API's.
Sadly almost the whole of computing since 1936 has been based on
marketing and advocacy research, with (fortunately) some seriously good
quality engineering from time to time. Basically there is essentially
no science in computer science. So not only is there nothing other than
claims that Actor Model is a good thing, there is nothing other than
claims that CSP is a good thing, likewise dataflow. In fact there is no
experimental evidence that object-oriented is good, that functional is
good, or even structured programming. It's all been opinion. And
marketing.
> I'm keeping my mind open but so far, I haven't seen any blinding proof
> of this claim. What I would really like to see is a non-trivial (i.e.
> requiring a few hundreds of lines of code to solve) concurrent problem
> written with both java.util.concurrent and Actors (might want to throw
> in fork-join in there while we're at it) and a tentatively objective
> analysis of the pros and cons of each approach, on several axes:
> maintainability, testability, readability (more subjective),
> debuggability, etc...
I'll turn it the other way around: advocates of java.util.concurrent
being all that is needed, need to provide proof that, in fact, it is
even capable (*).
Clearly there needs to be a grid of frameworks and problems with a set
of metrics. java.util.concurrent has no special position in this
experiment, it's only special position is that it is in the standard
distribution.
If we can decide on a few problems, and on which version control system
to use, it cannot be beyond the wit of Java Posse folk to create a
repository with all the necessary code. I have made a start (**) at
investigating scaling in a very large number of languages using the
problem of calculating PI via quadrature. This is a trivial,
embarrassingly parallel problem that is amazingly useful in
presentations and training courses, even though it is a microbenchmark
with all the problem that brings (***).
> My gut feeling is telling me that while the Actor/Immutable/lock free
> model appears simpler, it also introduces a radical shift in the way
> you implement your solution that might be detrimental to its
> maintenance on the long run. At the end, you might end up with a
> simple locking model (since there are no locks) but at the expense of
> a more spaghetti-ish structure, since all these actors are now sending
> asynchronous messages to each other and retracing and debugging such a
> flow can be challenging.
Personally I challenge that shared memory multi-threading should have
the position of orthodoxy that it has managed to acrete to itself.
Actor Model is 1973. CSP is 1976-1983. There is the Newsqueak thread
of work leading to Go. Threads came later than this: all of these
merging models were simply thrust aside by the obsession that 1970s
operating systems processes and their inter-process communications
systems were too heavyweight and slow -- even though it may have been
true, it was no reason to invent shared-memory multi-threading as an
application programming necessity.
Basically techniques that are necessary in operating systems programming
have been forced into applications programming technology where they
actually ought to be considered anathema.
Hummm . . . I think I am getting close to a rant. Time to stop.
> Another gut feeling that I haven't been able to shake off is the fact
> that the actor model introduces a single locking choke point (the
> inbox queue) while Java's traditional locking approach allows you to
> position your lock wherever you want, and over an arbitrarily large
> (or small) portion of code. Determining such a locking can be
> challenging, but once you've solved that particular problem, it's hard
> for me to imagine that there are more optimal ways of solving this
> problem.
So use Dataflow instead. Just because Actor <odel is getting a lot of
airplay just now doesn't mean its the only alternative. And of course
there is CSP which actually has a mathematical underpinning, unlike
every other of the alternatives.
For me Actor Model is getting to much mind set, others viable models
need a go to avoid all the advocacy and marketing.
(*) In fact I am a huge advocate of java.util.concurrent for any and
all concurrent and parallel Java programming as anyone who has been in
any of my sessions on this sort of thing can attest to. But . . . that
doesn't make it right. It just makes it less worse.
(**) Bazaar branch rendered by Loggerhead at
http://www.russel.org.uk:8080/Pi_Quadrature, Bazaar branches for
branching at http://www.russel.org.uk/Bazaar/Pi_Quadrature.
(***) And, oh boy, isn't Java and the JVM a right pain when it comes to
microbenchmarking. Bizarrely Scala does not have the same problems Java
has when it comes to priming the JVM JIT, yet no Scala advocate has yet
been able to provide me with a good rationale as to why.
--
Russel.
=============================================================================
Dr Russel Winder t: +44 20 7585 2200 voip: sip:russel...@ekiga.net
41 Buckmaster Road m: +44 7770 465 077 xmpp: rus...@russel.org.uk
London SW11 1EN, UK w: www.russel.org.uk skype: russel_winder
On 14 Jan 2011 13:59, "Reinier Zwitserloot" <rein...@gmail.com> wrote:
>
> Scala's language spec contains almost nothing. If you don't consider the standard import list part and parcel of scala (removing stuff from that list certainly isn't backwards compatible), I just don't know what to say to you (other than perhaps a wry comment on how I should have expected javaposse's resident scala fanboy to be so blind).... but of course, according to you the new library addition of parallel collections ARE enshrined. Pavlov would be pleased. Of course, we've been able to download and work with ParallelArray on JVM languages for a while now, so this isn't exactly new.
>
Parallel collections are enshrined in the fact that there's an entire release of Scala dedicated to adding them.
Folds? Just a couple of methods, and small ones at that.
It would require a very advanced level of doublethink to *not* objectively see a significant difference between the two.
> How does scala encourage side-effect-free methods? You can't even add an assertion of some sort to say: I intended this method to be side-effect-free. Let alone that such this assertion is checked by the compiler. Java doesn't either, but my claim is that the scala programmers claim to be better at this highly parallelizable thing than java. I'm certainly not claiming that java is any better, I'm just trying to say that language doesn't exist yet - scala most assuredly isn't it. Haskell at least has the side-effect-free thing down pat.
>
No, you're right, Scala doesn't have effect tracking yet. But I can assure you that the community is aware of the absence, and it's one of the more interesting features scheduled to be added under the funding of the recently awarded grant.
Currently, the language just goes a long way towards encouraging immutability and freedom from side effects, without actually enforcing them.
Still, this is a definite step up from ignoring the concepts completely (hey, anyone for setter injection?)
> NB: In regards to your spat against java.util.Date, two points: (1) Date has no operators associated with it, and cannot be used without an import statement or an FQN. This makes java.util.Date orders of magnitude less tied in to java (the language) compared to scala (the language). (2) I never claimed java was any better at this multi-core game that scala is. I'm trying to say that your claim that scala is, isn't backed up by much. Attacking java doesn't help you prove your case.
>
I'm not attacking Java. It's a rare Scala programmer who didn't migrate from java, and we all very much recognize Java's strengths.
I am, however, attacking the attitude that it's somehow heretical to even dare comparing java's "perfection" to alternative ideas.
Currently, the language just goes a long way towards encouraging immutability and freedom from side effects
--
You received this message because you are subscribed to the Google Groups "The Java Posse" group.
To post to this group, send email to java...@googlegroups.com.
To unsubscribe from this group, send email to javaposse+...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/javaposse?hl=en.
2011/1/14 Cédric Beust ♔ <ced...@beust.com>How? I really don't see it this way.On Fri, Jan 14, 2011 at 12:56 PM, Kevin Wright <kev.lee...@gmail.com> wrote:
Currently, the language just goes a long way towards encouraging immutability and freedom from side effectsYou can use var or val. You can modify fields inside methods. Only case classes are final.I don't see much in the overall philosophy behind the language that's very different from Java's in terms of immutability, and most defaults are toward mutability.If Scala programs tend to have more immutable structures than Java programs, it's much more because of the discipline of its developers than because the language encourages it.I see this as a good thing, by the way, but I think your claim is just plain incorrect.
--
CédricYou can even make case classes mutable if you mark params as vars. :)mutability is certainly accepted, and can't really be avoided for the kind of *deep* Java interop that's a design goal of java.I'll also agree that `var` isn't inherently harder to write than `val`, though anyone learning from current blogs, books, etc. will find themselves rapidly coming to see var as the lesser used of the two.More specifically though, I was thinking about the collections.If you create a new Map, or List, or Seq, etc, etc. then you'll get an immutable collection by default, mutable versions exist, but have to be explicitly imported.Given how much an "average" program will use a collection of some sort or another, that's a *lot* of encouragement.