Discussion:
[ANN] JDK 8 Crash Course (3/27)
w***@public.gmane.org
2014-03-19 16:48:11 UTC
Permalink
Hi Guys -

As I mentioned at SeaJUG last night, we're doing a meetup/event to celebrate and dive in a bit on the release of JDK 8. It's on Thursday next week, from 3-5pm in Kirkland.


Check out the agenda, directions, registration info, etc. at:
http://www.eventbrite.com/e/jdk-8-crash-course-tickets-10826922617 http://www.eventbrite.com/e/jdk-8-crash-course-tickets-10826922617



Bring your laptop - if you have stuff you'd like to share or Qs, feel free to fire them over in advance.


Hope to see ya there,
-Will


CTO, Dev9
http://www.dev9.com/ http://www.dev9.com/
Joe Bowbeer
2014-03-23 06:14:41 UTC
Permalink
I coded the Anagrams kata(*) using the features of Java 8, and it looks
very fluent. Essentially:

Files.lines(wordsPath).collect(groupingBy(key)).values().filter(v ->
v.size() > 1).forEach(println);

Where "key" is a custom function that returns the canonical form of a given
string.

Code and tests are at bitbucket.org/joebowbeer/anagrams

More on the anagrams kata at http://codekata.com/kata/kata06-anagrams

--Joe
Post by w***@public.gmane.org
Hi Guys -
As I mentioned at SeaJUG last night, we're doing a meetup/event to
celebrate and dive in a bit on the release of JDK 8. It's on Thursday next
week, from 3-5pm in Kirkland.
http://www.eventbrite.com/e/jdk-8-crash-course-tickets-10826922617
Bring your laptop - if you have stuff you'd like to share or Qs, feel free
to fire them over in advance.
Hope to see ya there,
-Will
CTO, Dev9
http://www.dev9.com/
Jason Osgood
2014-03-25 11:51:24 UTC
Permalink
Hi Joe Bowbeer.
Files.lines(wordsPath).collect(groupingBy(key)).values().filter(v -> v.size() > 1).forEach(println);
Nice. Thank you for sharing.

A practice interactive debugging session is on my to do list. I apologize if the following concerns are mooted and I haven’t caught up.

Debugging fluent Builders is pretty easy, particularly in Eclipse when the product class' toString() methods are strategically overridden to ease to inspection.

With lambdas, I’m concerned with debugging intermediate results, stepping through implementations of new Stream interface. Especially in IntelliJ; I really miss Eclipse’s default debugging data view, hoping to learn the IntelliJ “trick” for same.

I also continue to be frustrated by Java debugging not explicitly showing return values from methods. So I often create temporary variables to return, just so I have break point opportunity to inspect.


Cheers, Jason
Joe Bowbeer
2014-03-25 13:14:44 UTC
Permalink
I haven't spent any time debugging these examples -- as I abandoned
debuggers way back when I embraced agile methods. (Right? :-)

But I have puzzled over compiler warnings and errors that didn't seem to
refer to anything that I had written...

Type inference error messages look like gibberish.

One of the features of the jdk8 stream design is that it is easy to switch
between serial and parallel execution, typically by inserting a parallel()
into the expression. My code on bitbucket is highly parallel.

And one of the characteristics of a stream that can affect parallel
execution is the ordered-ness of the stream. Unordered can execute faster
-- probably, but, well, its unordered, which may not be suitable.

Instead of a debugger, I have been wishing for an expression analyzer that
would tell me how my cool, fluent expression will execute. Like a SQL query
analyzer.

This would help me answer the question: Do I need to add unordered() to the
expression, it is it already unordered, because, for example, the collector
is implicitly unordered?
Post by Jason Osgood
Hi Joe Bowbeer.
I coded the Anagrams kata(*) using the features of Java 8, and it looks
Files.lines(wordsPath).collect(groupingBy(key)).values().filter(v ->
v.size() > 1).forEach(println);
Nice. Thank you for sharing.
A practice interactive debugging session is on my to do list. I apologize
if the following concerns are mooted and I haven't caught up.
Debugging fluent Builders is pretty easy, particularly in Eclipse when the
product class' toString() methods are strategically overridden to ease to
inspection.
With lambdas, I'm concerned with debugging intermediate results, stepping
through implementations of new Stream interface. Especially in IntelliJ; I
really miss Eclipse's default debugging data view, hoping to learn the
IntelliJ "trick" for same.
I also continue to be frustrated by Java debugging not explicitly showing
return values from methods. So I often create temporary variables to
return, just so I have break point opportunity to inspect.
Cheers, Jason
Nimret Sandhu
2014-03-25 16:04:41 UTC
Permalink
debugging can be a necessary pain sometimes though - multithreaded code or
other esoteric issues. I've always been interested in "time traveling"
debuggers which let you go back and forth and inspect anything in the
runtime of the app. I've been meaning to play with
http://chrononsystems.com/ at some point.

lambdas, streams, etc are all awesome in jdk 8. It was about time that Java
caught up to some other language features which are popular these days.
Personally, I would have preferred them over generics back in the day.

cheers,
-
Nimret Sandhu
http://www.nimret.org
Post by Joe Bowbeer
I haven't spent any time debugging these examples -- as I abandoned
debuggers way back when I embraced agile methods. (Right? :-)
But I have puzzled over compiler warnings and errors that didn't seem to
refer to anything that I had written...
Type inference error messages look like gibberish.
One of the features of the jdk8 stream design is that it is easy to switch
between serial and parallel execution, typically by inserting a parallel()
into the expression. My code on bitbucket is highly parallel.
And one of the characteristics of a stream that can affect parallel
execution is the ordered-ness of the stream. Unordered can execute faster
-- probably, but, well, its unordered, which may not be suitable.
Instead of a debugger, I have been wishing for an expression analyzer that
would tell me how my cool, fluent expression will execute. Like a SQL query
analyzer.
This would help me answer the question: Do I need to add unordered() to
the expression, it is it already unordered, because, for example, the
collector is implicitly unordered?
Post by Jason Osgood
Hi Joe Bowbeer.
I coded the Anagrams kata(*) using the features of Java 8, and it looks
Files.lines(wordsPath).collect(groupingBy(key)).values().filter(v ->
v.size() > 1).forEach(println);
Nice. Thank you for sharing.
A practice interactive debugging session is on my to do list. I apologize
if the following concerns are mooted and I haven't caught up.
Debugging fluent Builders is pretty easy, particularly in Eclipse when
the product class' toString() methods are strategically overridden to ease
to inspection.
With lambdas, I'm concerned with debugging intermediate results, stepping
through implementations of new Stream interface. Especially in IntelliJ; I
really miss Eclipse's default debugging data view, hoping to learn the
IntelliJ "trick" for same.
I also continue to be frustrated by Java debugging not explicitly showing
return values from methods. So I often create temporary variables to
return, just so I have break point opportunity to inspect.
Cheers, Jason
w***@public.gmane.org
2014-03-25 17:41:45 UTC
Permalink
There's a Chronon Plugin in IntelliJ 13.1, haven't had a chance to try it but looks very interesting. Step Backward FTW. http://blog.jetbrains.com/idea/2014/03/try-chronon-debugger-with-intellij-idea-13-1-eap/ http://blog.jetbrains.com/idea/2014/03/try-chronon-debugger-with-intellij-idea-13-1-eap/



Joe's example is spot on for what I think is very interesting about 8 - you can write code that looks nothing like what you're used to. We saw something similar with a Grails project a while ago - some people wrote stuff that looked like classic Java, others wrote stuff that seemed practically PERL-esqe. Makes tabs vs. spaces look easy. ;)


Cheers,
-Will
Jason Osgood
2014-03-26 20:44:13 UTC
Permalink
Hi Joe.
Post by Joe Bowbeer
I haven't spent any time debugging these examples
I just did. JDK 8 + IntelliJ 13 CE. Utterly baffling. You’d think you’d be able step thru each stage of the lambda evaluation and inspect stuff.

Nope.

At least with IntelliJ, once you enter the bowels of the lambda, all runtime context is lost.

I mostly ignored the lambda discussions. So I’m very bit surprised the lambda implementation uses reflection and runtime byte code generation.

What’s the point? The lengths people go to reimplement LISP, poorly, are truly awe inspiring.

Maybe it’ll make more sense once The Powers that Be roll-in annotations and a LINQ knockoff. I can hardly wait.
Post by Joe Bowbeer
Instead of a debugger, I have been wishing for an expression analyzer that would tell me how my cool, fluent expression will execute. Like a SQL query analyzer.
That’s a boss idea.

It’d cleanly separate declaration from execution. Not so different from how ANTLR 3.x+ has allowed me to cleanly chunk the lex -> parse -> interpret / compile pipeline.
Post by Joe Bowbeer
But I have puzzled over compiler warnings and errors that didn't seem to refer to anything that I had written…
My main complaint exactly. With all this runtime declarative polymetalambda crap, I do not have a mental model how my code works. You end up just reverse engineering a black box thru trial and error. No thank you.
Post by Joe Bowbeer
-- as I abandoned debuggers way back when I embraced agile methods. (Right? :-)
I’ve gone the other direction. I insist on setting a break point, stepping thru the code, and inspecting state. That’s programming. People do all sorts of other things with computers. And all the power to them for their successes. But if you’re not debugging, you’re no longer programming. Along the lines of “wishful thinking is not a plan”.


Cheers, Jason

------------------------------------

Yahoo Groups Links

<*> To visit your group on the web, go to:
http://groups.yahoo.com/group/seajug/

<*> Your email settings:
Individual Email | Traditional

<*> To change settings online go to:
http://groups.yahoo.com/group/seajug/join
(Yahoo! ID required)

<*> To change settings via email:
seajug-digest-***@public.gmane.org
seajug-fullfeatured-***@public.gmane.org

<*> To unsubscribe from this group, send an email to:
seajug-unsubscribe-***@public.gmane.org

<*> Your use of Yahoo Groups is subject to:
https://info.yahoo.com/legal/us/yahoo/utos/terms/
P.Hill
2014-03-31 19:14:32 UTC
Permalink
I mostly ignored the lambda discussions. So I’m very bit surprised the lambda implementation uses reflection and runtime byte code generation.
You make it sound seriously slow, but the reflection and byte generation
to which is you speak only happen once to build the capturing/closure
part of calling the Lamda. It is this glue code which is generated
using reflection and byte code the 1st time the Lambda is called and
becomes what is invoked by the invoke dynamic method.
"The VM will call the metafactory only once per capture site; thereafter
it will link the call site and get out of the way."

The lambda you or I write is generated by the compiler into the class
file. "Non-instance-capturing lambdas are translated to private, static
methods. Instance-capturing lambdas are translated to private instance
methods."

"lambdas that use |this|, |super|, or capture members of the enclosing
instance [are] /instance-capturing lambdas/."

http://cr.openjdk.java.net/~briangoetz/lambda/lambda-translation.html

-Paul
Dennis Sosnoski
2014-03-31 21:28:53 UTC
Permalink
Lambdas are basically just anonymous inner classes, with two important
differences:

1. Greatly reduced class file bloat, since the class file is built at
runtime from data in the containing class, rather than being a separate
file (with its own constant pool and such)
2. Much more concise syntax in the source code.

Along with this are a bunch of other changes to make lambdas more
usable, including static and default methods in interfaces, and of
course the whole stream infrastructure for functional-ish programming
with sequences/collections of values.

- Dennis
Post by P.Hill
I mostly ignored the lambda discussions. So I’m very bit surprised the lambda implementation uses reflection and runtime byte code generation.
You make it sound seriously slow, but the reflection and byte
generation to which is you speak only happen once to build the
capturing/closure part of calling the Lamda. It is this glue code
which is generated using reflection and byte code the 1st time the
Lambda is called and becomes what is invoked by the invoke dynamic method.
"The VM will call the metafactory only once per capture site;
thereafter it will link the call site and get out of the way."
The lambda you or I write is generated by the compiler into the class
file. "Non-instance-capturing lambdas are translated to private,
static methods. Instance-capturing lambdas are translated to private
instance methods."
"lambdas that use |this|, |super|, or capture members of the enclosing
instance [are] /instance-capturing lambdas/."
http://cr.openjdk.java.net/~briangoetz/lambda/lambda-translation.html
-Paul
Jason Osgood
2014-03-31 22:03:53 UTC
Permalink
Hi Paul Hill.
You make it sound seriously slow, but the reflection and byte generation to which is you speak only happen once to build the capturing/closure part of calling the Lamda.
The only thing slow is my cognition. My complaint was that lambdas were black boxes.

I just tried interactive debugging Joe’s anagrams with NetBeans 8. Much better than stock Eclipse Kepler.
http://cr.openjdk.java.net/~briangoetz/lambda/lambda-translation.html
Thanks.


Cheers, Jason
P.Hill
2014-04-01 00:14:45 UTC
Permalink
Post by Jason Osgood
I just tried interactive debugging Joe’s anagrams with NetBeans 8.
Much better than stock Eclipse Kepler.
It would be interesting to see if a break point placed in the lambda
(not in or before any generated closure code) would allow jumping right
past the hidden stuff even in Eclipse. I'll have to try that.

This brings up the challenge of designing a simple enough debugger UI
when many things are all on one line and you want to specify a
breakpoint at the block which is the lambda. Another debugger feature
might allow the user to specify a feature to skip any such generated
closure code when stepping into. Is this what Netbeans provides?

Eclipse has a
Preferences > Java > Debug > Step Filtering
[ ] Filter Synthetic Methods (requires VM support)
It is unchecked be default for me, but I've never played with that setting.
Don't know if any of this new stuff is marked as "synthetic methods.",
but it sounds like it should. The term is used in various discussions
of the code generated.

http://docs.oracle.com/javase/6/docs/api/java/lang/reflect/Member.html#isSynthetic%28%29

-Paul
Steve Lewis
2014-03-27 22:05:07 UTC
Permalink
Having looked at Joe BowBeer's Java 8 Anagrams bitbucket.org/joebowbeer/
anagrams I decides to look at what a Java 7 implementation would look like -
http://bitbucket.org/steve_lewis_/anagrams-jdk-7
The file is more verbose -
my questions -
1) is it more readable
2) My version does the following
a) splits a line of text into words
b) drops punctuation

It would be interesting to see how hard it would be to add those features
to Joe's version
Also look at both - neither has comments for readability and
understandability



-
Scott Shipp
2014-03-27 23:16:19 UTC
Permalink
I reviewed the code and I'll toss in my 2 cents on readability. Mainly: it's hard to say if it is more readable. Probably those of us programming in Java for awhile now will automatically think the JDK 7 and lower type of implementation will be "more readable" simply due to familiarity. I'm reserving my judgment until I can get time to sit down and absorb the lambda way of thinking more.

However, right now I don't like the idea of using Lambda expressions for stuff even as complex as the anagram kata, which is actually fairly simple. Instead, I like lambda's for things like filtering, counting, etc. from a larger collection. You know...stuff like generate all the fibonacci numbers up to some value or count the number of managers in this list of employees. Which is all I ever used the "old" way of passing anonymous classes into method parameters anyway. To my mind, even if something is readable / simple to me, it may not be readable to someone else on the team, maybe a jr dev not yet familiar with the concept? Perhaps it is best for maintenance purposes not to put so much idea-space into one line of code.

On another note, I noticed that your code takes the approach of rolling a private class as a data structure to hold the anagrams. I did this kata last year and instead of doing that I simply made a Map<String, List<String>> to hold the anagrams. You can see this at https://gist.github.com/scottashipp/7680127 with an explanation of the thought process at http://code.scottshipp.com/2013/11/27/given-a-word-file-find-all-words-that-are-anagrams/.

I find this to be simpler and more readable, personally. It basically cuts the solution down to 20 lines of code (the rest of my code is a small timer class and some basic output). However, if you are a developer who doesn't like nesting collections within collections this feels like anathema, I'm sure.

Anyway, my implementation didn't split lines of text into words, either, or do the other things in your guys' like find the longest, etc.

Parting thought: I particularly enjoyed this line in Joe's:
String keyWord = key(word);
Cheers,

Scott



To: seajug-***@public.gmane.org
From: lordjoe2000-***@public.gmane.org
Date: Thu, 27 Mar 2014 15:05:07 -0700
Subject: [seajug] Re: [ANN] JDK 8 Crash Course (3/27)



























Having looked at Joe BowBeer's Java 8 Anagrams bitbucket.org/joebowbeer/anagrams I decides to look at what a Java 7 implementation would look like -
http://bitbucket.org/steve_lewis_/anagrams-jdk-7The file is more verbose -my questions - 1) is it more readable2) My version does the following
a) splits a line of text into words b) drops punctuation
It would be interesting to see how hard it would be to add those features to Joe's version Also look at both - neither has comments for readability and understandability




-
Joe Bowbeer
2014-03-28 00:39:27 UTC
Permalink
One advantage of the fluent stream style is the ease with which parallel
execution can be added: simply add parallel().

It also easily supports lazy evaluation. For example, anagrams(words)
returns all anagrams as a parallel stream, but the computation of the first
anagram for a given word will only do as much work as is needed.
Post by Scott Shipp
it's hard to say if it is more readable. Probably those of us programming
in Java for awhile now will automatically think the JDK 7 and lower type of
implementation will be "more readable" simply due to familiarity. I'm
reserving my judgment until I can get time to sit down and absorb the
lambda way of thinking more.
However, right now I don't like the idea of using Lambda expressions for
stuff even as complex as the anagram kata, which is actually fairly simple.
Instead, I like lambda's for things like filtering, counting, etc. from a
larger collection. You know...stuff like generate all the fibonacci numbers
up to some value or count the number of managers in this list of employees.
Which is all I ever used the "old" way of passing anonymous classes into
method parameters anyway. To my mind, even if something is readable /
simple to me, it may not be readable to someone else on the team, maybe a
jr dev not yet familiar with the concept? Perhaps it is best for
maintenance purposes not to put so much idea-space into one line of code.
On another note, I noticed that your code takes the approach of rolling a
private class as a data structure to hold the anagrams. I did this kata
last year and instead of doing that I simply made a Map<String,
List<String>> to hold the anagrams. You can see this at
https://gist.github.com/scottashipp/7680127 with an explanation of the
thought process at
http://code.scottshipp.com/2013/11/27/given-a-word-file-find-all-words-that-are-anagrams/.
I find this to be simpler and more readable, personally. It basically cuts
the solution down to 20 lines of code (the rest of my code is a small timer
class and some basic output). However, if you are a developer who doesn't
like nesting collections within collections this feels like anathema, I'm
sure.
Anyway, my implementation didn't split lines of text into words, either,
or do the other things in your guys' like find the longest, etc.
String keyWord = key(word);
Cheers,
Scott
------------------------------
Date: Thu, 27 Mar 2014 15:05:07 -0700
Subject: [seajug] Re: [ANN] JDK 8 Crash Course (3/27)
Having looked at Joe BowBeer's Java 8 Anagrams bitbucket.org/joebowbeer/
anagrams I decides to look at what a Java 7 implementation would look like -
http://bitbucket.org/steve_lewis_/anagrams-jdk-7
The file is more verbose -
my questions -
1) is it more readable
2) My version does the following
a) splits a line of text into words
b) drops punctuation
It would be interesting to see how hard it would be to add those features
to Joe's version
Also look at both - neither has comments for readability and
understandability
-
George Smith
2014-03-28 14:38:29 UTC
Permalink
Scott, et all:

I have no doubt I'll start using Lambda once my code base is "allowed to"
(The GWT team committed to support Java8 this year) simply for the
terseness. IMO, the real value that lambdas "help" facilitate are the
Streams, and specifically the Parallel Streams - as Joe pointed out!

As for nested collections, I think Steve & I, have been burned a few to
many times by the need to add stuff to the "model" that then ripples thru
too much code if the "model" is not *encapsulated*. This does not mean
that you don't return simple Lists or Maps, it is just that if you do, then
what they carry should be "model" objects and you should feel very
confident that no additional stuff will need to be added to the
"collection" level of the overall "model" (for example in much of my
current work, I end up carrying "source" metadata for error reporting from
the messages I receive and parse, so that I can return some context about
where the error is in the input message).

While a Kata might not call for this level of "future proofing", my
response is two fold:

1. When something is not a one-off PRIVATE use solution, then you should
code it the best you can (within context) - far too many solutions are just
the happy-case aspect (for concise readability e.g. book examples) but are
treated by many (if not most) as "the" solution!
2. I find that the best way to do the "right" thing most of the time, is
to simply practice it, by doing the "right" thing most of the time!


Apologies for "preachiness".

George
Post by Joe Bowbeer
One advantage of the fluent stream style is the ease with which parallel
execution can be added: simply add parallel().
It also easily supports lazy evaluation. For example, anagrams(words)
returns all anagrams as a parallel stream, but the computation of the first
anagram for a given word will only do as much work as is needed.
Post by Scott Shipp
it's hard to say if it is more readable. Probably those of us programming
in Java for awhile now will automatically think the JDK 7 and lower type of
implementation will be "more readable" simply due to familiarity. I'm
reserving my judgment until I can get time to sit down and absorb the
lambda way of thinking more.
However, right now I don't like the idea of using Lambda expressions for
stuff even as complex as the anagram kata, which is actually fairly simple.
Instead, I like lambda's for things like filtering, counting, etc. from a
larger collection. You know...stuff like generate all the fibonacci numbers
up to some value or count the number of managers in this list of employees.
Which is all I ever used the "old" way of passing anonymous classes into
method parameters anyway. To my mind, even if something is readable /
simple to me, it may not be readable to someone else on the team, maybe a
jr dev not yet familiar with the concept? Perhaps it is best for
maintenance purposes not to put so much idea-space into one line of code.
On another note, I noticed that your code takes the approach of rolling a
private class as a data structure to hold the anagrams. I did this kata
last year and instead of doing that I simply made a Map<String,
List<String>> to hold the anagrams. You can see this at
https://gist.github.com/scottashipp/7680127 with an explanation of the
thought process at
http://code.scottshipp.com/2013/11/27/given-a-word-file-find-all-words-that-are-anagrams/.
I find this to be simpler and more readable, personally. It basically
cuts the solution down to 20 lines of code (the rest of my code is a small
timer class and some basic output). However, if you are a developer who
doesn't like nesting collections within collections this feels like
anathema, I'm sure.
Anyway, my implementation didn't split lines of text into words, either,
or do the other things in your guys' like find the longest, etc.
String keyWord = key(word);
Cheers,
Scott
------------------------------
Date: Thu, 27 Mar 2014 15:05:07 -0700
Subject: [seajug] Re: [ANN] JDK 8 Crash Course (3/27)
Having looked at Joe BowBeer's Java 8 Anagrams bitbucket.org/joebowbeer/
anagrams I decides to look at what a Java 7 implementation would look like -
http://bitbucket.org/steve_lewis_/anagrams-jdk-7
The file is more verbose -
my questions -
1) is it more readable
2) My version does the following
a) splits a line of text into words
b) drops punctuation
It would be interesting to see how hard it would be to add those features
to Joe's version
Also look at both - neither has comments for readability and
understandability
-
--
"And the users exclaimed with a laugh and a taunt: It's just what we
asked for but not what we want." -- Unknown
Scott Shipp
2014-03-28 16:41:04 UTC
Permalink
I'll think it over more. You're not the first I've heard say this and I've also done this myself. For example: boss comes to me, says, "hey we need this tool to monitor this thing that's going on in the database, there will be a little bit of interaction like pause/restart etc. . . don't spend too much time on it, team so-and-so will be writing this into the new other project" (this is the classic statement, right?) Anyway, I coded in a whole layer to get the database interactions encapsulated away even though I wasn't supposed to. If someone wants to move this to a web service or wherever that makes more sense, the code is decoupled...no need to go delaminate all the database access out of the code . . . the kind of thing that drives me insane.
On the other hand...there's "YAGNI!" I'm sure there's a balance that comes with experience where you can make a wise call on what and how much to encapsulate...perhaps I am agreeing with "this does not mean you don't return simple Lists or Maps...[but]... if you do... you should feel very confident..."
Thanks for the thoughts!
Scott

To: seajug-***@public.gmane.org
From: litesoft-***@public.gmane.org
Date: Fri, 28 Mar 2014 07:38:29 -0700
Subject: Re: [seajug] Re: [ANN] JDK 8 Crash Course (3/27)



























Scott, et all:
I have no doubt I'll start using Lambda once my code base is "allowed to" (The GWT team committed to support Java8 this year) simply for the terseness. IMO, the real value that lambdas "help" facilitate are the Streams, and specifically the Parallel Streams - as Joe pointed out!

As for nested collections, I think Steve & I, have been burned a few to many times by the need to add stuff to the "model" that then ripples thru too much code if the "model" is not encapsulated. This does not mean that you don't return simple Lists or Maps, it is just that if you do, then what they carry should be "model" objects and you should feel very confident that no additional stuff will need to be added to the "collection" level of the overall "model" (for example in much of my current work, I end up carrying "source" metadata for error reporting from the messages I receive and parse, so that I can return some context about where the error is in the input message).

While a Kata might not call for this level of "future proofing", my response is two fold:When something is not a one-off PRIVATE use solution, then you should code it the best you can (within context) - far too many solutions are just the happy-case aspect (for concise readability e.g. book examples) but are treated by many (if not most) as "the" solution!

I find that the best way to do the "right" thing most of the time, is to simply practice it, by doing the "right" thing most of the time!

Apologies for "preachiness".

George

On Thu, Mar 27, 2014 at 5:39 PM, Joe Bowbeer <joe.bowbeer-***@public.gmane.org> wrote:



























One advantage of the fluent stream style is the ease with which parallel execution can be added: simply add parallel().
It also easily supports lazy evaluation. For example, anagrams(words) returns all anagrams as a parallel stream, but the computation of the first anagram for a given word will only do as much work as is needed.


On Mar 27, 2014 4:16 PM, "Scott Shipp" <scottashipp-1ViLX0X+***@public.gmane.org> wrote:

























I reviewed the code and I'll toss in my 2 cents on readability. Mainly: it's hard to say if it is more readable. Probably those of us programming in Java for awhile now will automatically think the JDK 7 and lower type of implementation will be "more readable" simply due to familiarity. I'm reserving my judgment until I can get time to sit down and absorb the lambda way of thinking more.



However, right now I don't like the idea of using Lambda expressions for stuff even as complex as the anagram kata, which is actually fairly simple. Instead, I like lambda's for things like filtering, counting, etc. from a larger collection. You know...stuff like generate all the fibonacci numbers up to some value or count the number of managers in this list of employees. Which is all I ever used the "old" way of passing anonymous classes into method parameters anyway. To my mind, even if something is readable / simple to me, it may not be readable to someone else on the team, maybe a jr dev not yet familiar with the concept? Perhaps it is best for maintenance purposes not to put so much idea-space into one line of code.



On another note, I noticed that your code takes the approach of rolling a private class as a data structure to hold the anagrams. I did this kata last year and instead of doing that I simply made a Map<String, List<String>> to hold the anagrams. You can see this at https://gist.github.com/scottashipp/7680127 with an explanation of the thought process at http://code.scottshipp.com/2013/11/27/given-a-word-file-find-all-words-that-are-anagrams/.



I find this to be simpler and more readable, personally. It basically cuts the solution down to 20 lines of code (the rest of my code is a small timer class and some basic output). However, if you are a developer who doesn't like nesting collections within collections this feels like anathema, I'm sure.



Anyway, my implementation didn't split lines of text into words, either, or do the other things in your guys' like find the longest, etc.

Parting thought: I particularly enjoyed this line in Joe's:


String keyWord = key(word);
Cheers,

Scott



To: seajug-***@public.gmane.org


From: lordjoe2000-***@public.gmane.org
Date: Thu, 27 Mar 2014 15:05:07 -0700
Subject: [seajug] Re: [ANN] JDK 8 Crash Course (3/27)



























Having looked at Joe BowBeer's Java 8 Anagrams bitbucket.org/joebowbeer/anagrams I decides to look at what a Java 7 implementation would look like -


http://bitbucket.org/steve_lewis_/anagrams-jdk-7The file is more verbose -my questions - 1) is it more readable

2) My version does the following
a) splits a line of text into words b) drops punctuation
It would be interesting to see how hard it would be to add those features to Joe's version Also look at both - neither has comments for readability and understandability






-
--
"And the users exclaimed with a laugh and a taunt: It's just what we asked for but not what we want." -- Unknown
P.Hill
2014-04-01 06:48:41 UTC
Permalink
George didn't say no collections out, just not collections of collections"
Post by Scott Shipp
This does not mean that you don't return simple Lists or Maps, it is
just that if you do, then what _they carry_ should be "model"
Post by Scott Shipp
objects and you should feel very confident that no additional stuff
will need to be added to the "collection" level of the overall "model".'

Also consider_telling_ the top-level enclosing class to do something
useful instead of simply handing something out it when you _ask _to get
it, then maybe you'll just not have most requests that would return
collections of collections. This is supposed to be the "tell-don't-ask"
rule, but I usually can't remember which verb is the simple one and
which one implies just getting. I was proud of myself this time, I
actually wrote the above sentences correctly without looking. :-)

"you should endeavor to /tell/ objects what you want them_to do_; do not
_/ask/___them questions _about their state_, make a decision, and then
tell them what to do." --http://pragprog.com/articles/tell-dont-ask

I would add the: do not have a caller _/ask/___an object _about its
state,_ just so the caller can do the work of filtering or combining the
state(s). It is these
operations on any collection that help to suggest collections often need
to be encapsulated, so that the useful operations appear with the
collection.
I know I am not as good as I should be on good tell vs. ask design.

-Paul
Post by Scott Shipp
On the other hand...there's "YAGNI!" I'm sure there's a balance that
comes with experience where you can make a wise call on what and how
much to encapsulate...perhaps I am agreeing with "this does not mean
you don't return simple Lists or Maps...[but]... if you do... you
should feel very confident..."
Scott Shipp
2014-04-01 16:02:39 UTC
Permalink
Due to a desire to answer Steve's question seriously, I've been experimenting with lambdas and comparing/contrasting the old SAM way versus the new Lambda way. The main example I wanted to try for myself was something I mentioned earlier, generating any series of numbers: https://gist.github.com/scottashipp/9916656

TL;DR - Lambdas are cool and yes, they are more readable as far as usage within the bounds of what they were designed to do.

Based on this experiment, I found a number of interesting observations:

1. It is more readable to do it the Lambda way, if you are using Lambdas the way they are designed.

2. It is not more readable if you abuse it. There were some things I tried where I think I found the limits of lambdas, at least in this particular case.

3. For this particular case of simply listing numbers to the screen in series order, .parallel() doesn't work...your numbers come back out of order...but this showed me how powerful parallel() could be when you might be doing something like updating objects in a collection, where order is not important.

4. The Lambda version is more expressive (more nerdy at least) if you like lines like "generateValue.andThen(format).apply(i)".

5. Speaking of the chained functions feature, that is really nice. Although I didn't do it in this example, you can see how abstracting the formatting completely away would be really helpful. In the Java 7 version, the method takes a "NumberFormat" object. But in the Java 8 version, it just takes a function which might encapsulate any kind of behavior. Sure, sure, if you really needed this in J7 you could easily create your own subclass of NumberFormat but there you are again writing way more code than you probably need to do something that is conceptually simple.

6. Lambdas are so horizontal, that you either keep them on one line which potentially runs past the right side of your screen or you break them up onto separate lines, in which case I wonder how much it really "solves the vertical problem."

This is mostly syntactic sugar but in the best sense. I think this actually accomplishes something for the developer in terms of the conceptual idea in the code matching the way you might actually think about. (Yes I know it is not ALL syntactic sugar since there are new scope rules, the potential for lazy evaluation, etc.)

Now for a question: does anyone know if Java 8 has anything like the Haskell "take" keyword (see example at http://mdickens.me/2013/12/16/those_weird_haskell_features_are_actually_useful/ )? That would be even better.

Scott


To: seajug-***@public.gmane.org
From: scottashipp-1ViLX0X+***@public.gmane.org
Date: Thu, 27 Mar 2014 16:16:19 -0700
Subject: RE: [seajug] Re: [ANN] JDK 8 Crash Course (3/27)





























I reviewed the code and I'll toss in my 2 cents on readability. Mainly: it's hard to say if it is more readable. Probably those of us programming in Java for awhile now will automatically think the JDK 7 and lower type of implementation will be "more readable" simply due to familiarity. I'm reserving my judgment until I can get time to sit down and absorb the lambda way of thinking more.

However, right now I don't like the idea of using Lambda expressions for stuff even as complex as the anagram kata, which is actually fairly simple. Instead, I like lambda's for things like filtering, counting, etc. from a larger collection. You know...stuff like generate all the fibonacci numbers up to some value or count the number of managers in this list of employees. Which is all I ever used the "old" way of passing anonymous classes into method parameters anyway. To my mind, even if something is readable / simple to me, it may not be readable to someone else on the team, maybe a jr dev not yet familiar with the concept? Perhaps it is best for maintenance purposes not to put so much idea-space into one line of code.

On another note, I noticed that your code takes the approach of rolling a private class as a data structure to hold the anagrams. I did this kata last year and instead of doing that I simply made a Map<String, List<String>> to hold the anagrams. You can see this at https://gist.github.com/scottashipp/7680127 with an explanation of the thought process at http://code.scottshipp.com/2013/11/27/given-a-word-file-find-all-words-that-are-anagrams/.

I find this to be simpler and more readable, personally. It basically cuts the solution down to 20 lines of code (the rest of my code is a small timer class and some basic output). However, if you are a developer who doesn't like nesting collections within collections this feels like anathema, I'm sure.

Anyway, my implementation didn't split lines of text into words, either, or do the other things in your guys' like find the longest, etc.

Parting thought: I particularly enjoyed this line in Joe's:
String keyWord = key(word);
Cheers,

Scott



To: seajug-***@public.gmane.org
From: lordjoe2000-***@public.gmane.org
Date: Thu, 27 Mar 2014 15:05:07 -0700
Subject: [seajug] Re: [ANN] JDK 8 Crash Course (3/27)



























Having looked at Joe BowBeer's Java 8 Anagrams bitbucket.org/joebowbeer/anagrams I decides to look at what a Java 7 implementation would look like -
http://bitbucket.org/steve_lewis_/anagrams-jdk-7The file is more verbose -my questions - 1) is it more readable2) My version does the following
a) splits a line of text into words b) drops punctuation
It would be interesting to see how hard it would be to add those features to Joe's version Also look at both - neither has comments for readability and understandability




-
Joe Bowbeer
2014-04-01 16:20:43 UTC
Permalink
Check out forEachOrdered, and the Ordering examples at the link below:

http://docs.oracle.com/javase/tutorial/collections/streams/parallelism.html

I think limit(n) is similar to Haskell's 'take'. There is also a skip(k).
Post by Scott Shipp
Due to a desire to answer Steve's question seriously, I've been
experimenting with lambdas and comparing/contrasting the old SAM way versus
the new Lambda way. The main example I wanted to try for myself was
https://gist.github.com/scottashipp/9916656
TL;DR - Lambdas are cool and yes, they are more readable as far as usage
within the bounds of what they were designed to do.
1. It *is* more readable to do it the Lambda way, if you are using
Lambdas the way they are designed.
2. It is *not* more readable if you abuse it. There were some things I
tried where I think I found the limits of lambdas, at least in this
particular case.
3. For this particular case of simply listing numbers to the screen in
series order, .parallel() doesn't work...your numbers come back out of
order...but this showed me how powerful parallel() could be when you might
be doing something like updating objects in a collection, where order is
not important.
4. The Lambda version is more expressive (more nerdy at least) if you like
lines like "generateValue.andThen(format).apply(i)".
5. Speaking of the chained functions feature, that is really nice.
Although I didn't do it in this example, you can see how abstracting the
formatting completely away would be really helpful. In the Java 7 version,
the method takes a "NumberFormat" object. But in the Java 8 version, it
just takes a function which might encapsulate any kind of behavior. Sure,
sure, if you really needed this in J7 you could easily create your own
subclass of NumberFormat but there you are again writing way more code than
you probably need to do something that is conceptually simple.
6. Lambdas are so horizontal, that you either keep them on one line which
potentially runs past the right side of your screen or you break them up
onto separate lines, in which case I wonder how much it really "solves the
vertical problem."
This is *mostly *syntactic sugar but in the best sense. I think this
actually accomplishes something for the developer in terms of the
conceptual idea in the code matching the way you might actually think
about. (Yes I know it is not ALL syntactic sugar since there are new scope
rules, the potential for lazy evaluation, etc.)
Now for a question: does anyone know if Java 8 has anything like the
Haskell "take" keyword (see example at
http://mdickens.me/2013/12/16/those_weird_haskell_features_are_actually_useful/)? That would be even better.
Scott
------------------------------
Date: Thu, 27 Mar 2014 16:16:19 -0700
Subject: RE: [seajug] Re: [ANN] JDK 8 Crash Course (3/27)
it's hard to say if it is more readable. Probably those of us programming
in Java for awhile now will automatically think the JDK 7 and lower type of
implementation will be "more readable" simply due to familiarity. I'm
reserving my judgment until I can get time to sit down and absorb the
lambda way of thinking more.
However, right now I don't like the idea of using Lambda expressions for
stuff even as complex as the anagram kata, which is actually fairly simple.
Instead, I like lambda's for things like filtering, counting, etc. from a
larger collection. You know...stuff like generate all the fibonacci numbers
up to some value or count the number of managers in this list of employees.
Which is all I ever used the "old" way of passing anonymous classes into
method parameters anyway. To my mind, even if something is readable /
simple to me, it may not be readable to someone else on the team, maybe a
jr dev not yet familiar with the concept? Perhaps it is best for
maintenance purposes not to put so much idea-space into one line of code.
On another note, I noticed that your code takes the approach of rolling a
private class as a data structure to hold the anagrams. I did this kata
last year and instead of doing that I simply made a Map<String,
List<String>> to hold the anagrams. You can see this at
https://gist.github.com/scottashipp/7680127 with an explanation of the
thought process at
http://code.scottshipp.com/2013/11/27/given-a-word-file-find-all-words-that-are-anagrams/.
I find this to be simpler and more readable, personally. It basically cuts
the solution down to 20 lines of code (the rest of my code is a small timer
class and some basic output). However, if you are a developer who doesn't
like nesting collections within collections this feels like anathema, I'm
sure.
Anyway, my implementation didn't split lines of text into words, either,
or do the other things in your guys' like find the longest, etc.
String keyWord = key(word);
Cheers,
Scott
------------------------------
Date: Thu, 27 Mar 2014 15:05:07 -0700
Subject: [seajug] Re: [ANN] JDK 8 Crash Course (3/27)
Having looked at Joe BowBeer's Java 8 Anagrams bitbucket.org/joebowbeer/
anagrams I decides to look at what a Java 7 implementation would look like -
http://bitbucket.org/steve_lewis_/anagrams-jdk-7
The file is more verbose -
my questions -
1) is it more readable
2) My version does the following
a) splits a line of text into words
b) drops punctuation
It would be interesting to see how hard it would be to add those features
to Joe's version
Also look at both - neither has comments for readability and
understandability
-
Scott Shipp
2014-04-02 19:43:19 UTC
Permalink
Fair enough. If you're talking about just Fibonacci...and not including import statements or what have you...I can get it down to two lines of Java:

static UnaryOperator<Integer> fibonacci;
IntStream.range(0,11).map(fibonacci = i -> { return i == 0 || i == 1 ? 1 : fibonacci.applyAsInt(i - 2) + fibonacci.applyAsInt(i - 1); }).parallel().forEachOrdered(e -> System.out.printf("%s ", e));

Maybe someone else can even help reduce it further...

Scott

To: seajug-***@public.gmane.org
From: kgignatyev-***@public.gmane.org
Date: Wed, 2 Apr 2014 11:49:29 -0700
Subject: Re: [seajug] [ANN] JDK 8 Crash Course (3/27)



























Sorry, could not resist ;)In Scala it is only 2 lines of code
http://stackoverflow.com/questions/9864497/generate-a-sequence-of-fibonacci-number-in-scala



On Wed, Apr 2, 2014 at 10:46 AM, Scott Shipp <scottashipp-1ViLX0X+***@public.gmane.org> wrote:





























Now I'm really hooked on this lambda business. I just updated my gist with newly learned code. (https://gist.github.com/scottashipp/9916656)


New comparison based on lines of code:
Lines of code in Java 7 - 70
Lines of code in Java 8 - 37

Scott

To: seajug-***@public.gmane.org

From: joe.bowbeer-***@public.gmane.org
Date: Tue, 1 Apr 2014 09:20:43 -0700
Subject: Re: [seajug] [ANN] JDK 8 Crash Course (3/27)


























Check out forEachOrdered, and the Ordering examples at the link below:

http://docs.oracle.com/javase/tutorial/collections/streams/parallelism.html



I think limit(n) is similar to Haskell's 'take'. There is also a skip(k).

On Tuesday, April 1, 2014, Scott Shipp <scottashipp-1ViLX0X+***@public.gmane.org> wrote:

























Due to a desire to answer Steve's question seriously, I've been experimenting with lambdas and comparing/contrasting the old SAM way versus the new Lambda way. The main example I wanted to try for myself was something I mentioned earlier, generating any series of numbers: https://gist.github.com/scottashipp/9916656



TL;DR - Lambdas are cool and yes, they are more readable as far as usage within the bounds of what they were designed to do.

Based on this experiment, I found a number of interesting observations:

1. It is more readable to do it the Lambda way, if you are using Lambdas the way they are designed.



2. It is not more readable if you abuse it. There were some things I tried where I think I found the limits of lambdas, at least in this particular case.

3. For this particular case of simply listing numbers to the screen in series order, .parallel() doesn't work...your numbers come back out of order...but this showed me how powerful parallel() could be when you might be doing something like updating objects in a collection, where order is not important.



4. The Lambda version is more expressive (more nerdy at least) if you like lines like "generateValue.andThen(format).apply(i)".

5. Speaking of the chained functions feature, that is really nice. Although I didn't do it in this example, you can see how abstracting the formatting completely away would be really helpful. In the Java 7 version, the method takes a "NumberFormat" object. But in the Java 8 version, it just takes a function which might encapsulate any kind of behavior. Sure, sure, if you really needed this in J7 you could easily create your own subclass of NumberFormat but there you are again writing way more code than you probably need to do something that is conceptually simple.



6. Lambdas are so horizontal, that you either keep them on one line which potentially runs past the right side of your screen or you break them up onto separate lines, in which case I wonder how much it really "solves the vertical problem."



This is mostly syntactic sugar but in the best sense. I think this actually accomplishes something for the developer in terms of the conceptual idea in the code matching the way you might actually think about. (Yes I know it is not ALL syntactic sugar since there are new scope rules, the potential for lazy evaluation, etc.)



Now for a question: does anyone know if Java 8 has anything like the Haskell "take" keyword (see example at http://mdickens.me/2013/12/16/those_weird_haskell_features_are_actually_useful/ )? That would be even better.



Scott


To: seajug-***@public.gmane.org
From: scottashipp-1ViLX0X+***@public.gmane.org

Date: Thu, 27 Mar 2014 16:16:19 -0700
Subject: RE: [seajug] Re: [ANN] JDK 8 Crash Course (3/27)





























I reviewed the code and I'll toss in my 2 cents on readability. Mainly: it's hard to say if it is more readable. Probably those of us programming in Java for awhile now will automatically think the JDK 7 and lower type of implementation will be "more readable" simply due to familiarity. I'm reserving my judgment until I can get time to sit down and absorb the lambda way of thinking more.



However, right now I don't like the idea of using Lambda expressions for stuff even as complex as the anagram kata, which is actually fairly simple. Instead, I like lambda's for things like filtering, counting, etc. from a larger collection. You know...stuff like generate all the fibonacci numbers up to some value or count the number of managers in this list of employees. Which is all I ever used the "old" way of passing anonymous classes into method parameters anyway. To my mind, even if something is readable / simple to me, it may not be readable to someone else on the team, maybe a jr dev not yet familiar with the concept? Perhaps it is best for maintenance purposes not to put so much idea-space into one line of code.



On another note, I noticed that your code takes the approach of rolling a private class as a data structure to hold the anagrams. I did this kata last year and instead of doing that I simply made a Map<String, List<String>> to hold the anagrams. You can see this at https://gist.github.com/scottashipp/7680127 with an explanation of the thought process at http://code.scottshipp.com/2013/11/27/given-a-word-file-find-all-words-that-are-anagrams/.



I find this to be simpler and more readable, personally. It basically cuts the solution down to 20 lines of code (the rest of my code is a small timer class and some basic output). However, if you are a developer who doesn't like nesting collections within collections this feels like anathema, I'm sure.



Anyway, my implementation didn't split lines of text into words, either, or do the other things in your guys' like find the longest, etc.

Parting thought: I particularly enjoyed this line in Joe's:


String keyWord = key(word);
Cheers,

Scott



To: seajug-***@public.gmane.org
From: lordjoe2000-***@public.gmane.org


Date: Thu, 27 Mar 2014 15:05:07 -0700
Subject: [seajug] Re: [ANN] JDK 8 Crash Course (3/27)



























Having looked at Joe BowBeer's Java 8 Anagrams bitbucket.org/joebowbeer/anagrams I decides to look at what a Java 7 implementation would look like -


http://bitbucket.org/steve_lewis_/anagrams-jdk-7The file is more verbose -my questions - 1) is it more readable

2) My version does the following
a) splits a line of text into words b) drops punctuation
It would be interesting to see how hard it would be to add those features to Joe's version Also look at both - neither has comments for readability and understandability






-
--
Konstantin Ignatyev

PS: If this is a typical day on planet Earth, humans will add fifteen million tons of carbon to the atmosphere, destroy 115 square miles of tropical rainforest, create seventy-two miles of desert, eliminate between forty to one hundred species, erode seventy-one million tons of topsoil, add 2,700 tons of CFCs to the stratosphere, and increase their population by 263,000


Bowers, C.A. The Culture of Denial: Why the Environmental Movement Needs a Strategy for Reforming Universities and Public Schools. New York: State University of New York Press, 1997: (4) (5) (p.206)
Konstantin Ignatyev
2014-04-02 18:49:29 UTC
Permalink
Sorry, could not resist ;)
In Scala it is only 2 lines of code

http://stackoverflow.com/questions/9864497/generate-a-sequence-of-fibonacci-number-in-scala
Post by Scott Shipp
Now I'm really hooked on this lambda business. I just updated my gist with
newly learned code. (https://gist.github.com/scottashipp/9916656)
Lines of code in Java 7 - 70
Lines of code in Java 8 - 37
Scott
------------------------------
Date: Tue, 1 Apr 2014 09:20:43 -0700
Subject: Re: [seajug] [ANN] JDK 8 Crash Course (3/27)
http://docs.oracle.com/javase/tutorial/collections/streams/parallelism.html
I think limit(n) is similar to Haskell's 'take'. There is also a skip(k).
Due to a desire to answer Steve's question seriously, I've been
experimenting with lambdas and comparing/contrasting the old SAM way versus
the new Lambda way. The main example I wanted to try for myself was
https://gist.github.com/scottashipp/9916656
TL;DR - Lambdas are cool and yes, they are more readable as far as usage
within the bounds of what they were designed to do.
1. It *is* more readable to do it the Lambda way, if you are using
Lambdas the way they are designed.
2. It is *not* more readable if you abuse it. There were some things I
tried where I think I found the limits of lambdas, at least in this
particular case.
3. For this particular case of simply listing numbers to the screen in
series order, .parallel() doesn't work...your numbers come back out of
order...but this showed me how powerful parallel() could be when you might
be doing something like updating objects in a collection, where order is
not important.
4. The Lambda version is more expressive (more nerdy at least) if you like
lines like "generateValue.andThen(format).apply(i)".
5. Speaking of the chained functions feature, that is really nice.
Although I didn't do it in this example, you can see how abstracting the
formatting completely away would be really helpful. In the Java 7 version,
the method takes a "NumberFormat" object. But in the Java 8 version, it
just takes a function which might encapsulate any kind of behavior. Sure,
sure, if you really needed this in J7 you could easily create your own
subclass of NumberFormat but there you are again writing way more code than
you probably need to do something that is conceptually simple.
6. Lambdas are so horizontal, that you either keep them on one line which
potentially runs past the right side of your screen or you break them up
onto separate lines, in which case I wonder how much it really "solves the
vertical problem."
This is *mostly *syntactic sugar but in the best sense. I think this
actually accomplishes something for the developer in terms of the
conceptual idea in the code matching the way you might actually think
about. (Yes I know it is not ALL syntactic sugar since there are new scope
rules, the potential for lazy evaluation, etc.)
Now for a question: does anyone know if Java 8 has anything like the
Haskell "take" keyword (see example at
http://mdickens.me/2013/12/16/those_weird_haskell_features_are_actually_useful/)? That would be even better.
Scott
------------------------------
Date: Thu, 27 Mar 2014 16:16:19 -0700
Subject: RE: [seajug] Re: [ANN] JDK 8 Crash Course (3/27)
it's hard to say if it is more readable. Probably those of us programming
in Java for awhile now will automatically think the JDK 7 and lower type of
implementation will be "more readable" simply due to familiarity. I'm
reserving my judgment until I can get time to sit down and absorb the
lambda way of thinking more.
However, right now I don't like the idea of using Lambda expressions for
stuff even as complex as the anagram kata, which is actually fairly simple.
Instead, I like lambda's for things like filtering, counting, etc. from a
larger collection. You know...stuff like generate all the fibonacci numbers
up to some value or count the number of managers in this list of employees.
Which is all I ever used the "old" way of passing anonymous classes into
method parameters anyway. To my mind, even if something is readable /
simple to me, it may not be readable to someone else on the team, maybe a
jr dev not yet familiar with the concept? Perhaps it is best for
maintenance purposes not to put so much idea-space into one line of code.
On another note, I noticed that your code takes the approach of rolling a
private class as a data structure to hold the anagrams. I did this kata
last year and instead of doing that I simply made a Map<String,
List<String>> to hold the anagrams. You can see this at
https://gist.github.com/scottashipp/7680127 with an explanation of the
thought process at
http://code.scottshipp.com/2013/11/27/given-a-word-file-find-all-words-that-are-anagrams/.
I find this to be simpler and more readable, personally. It basically cuts
the solution down to 20 lines of code (the rest of my code is a small timer
class and some basic output). However, if you are a developer who doesn't
like nesting collections within collections this feels like anathema, I'm
sure.
Anyway, my implementation didn't split lines of text into words, either,
or do the other things in your guys' like find the longest, etc.
String keyWord = key(word);
Cheers,
Scott
------------------------------
Date: Thu, 27 Mar 2014 15:05:07 -0700
Subject: [seajug] Re: [ANN] JDK 8 Crash Course (3/27)
Having looked at Joe BowBeer's Java 8 Anagrams bitbucket.org/joebowbeer/
anagrams I decides to look at what a Java 7 implementation would look like -
http://bitbucket.org/steve_lewis_/anagrams-jdk-7
The file is more verbose -
my questions -
1) is it more readable
2) My version does the following
a) splits a line of text into words
b) drops punctuation
It would be interesting to see how hard it would be to add those features
to Joe's version
Also look at both - neither has comments for readability and
understandability
-
--
Konstantin Ignatyev

PS: If this is a typical day on planet Earth, humans will add fifteen
million tons of carbon to the atmosphere, destroy 115 square miles of
tropical rainforest, create seventy-two miles of desert, eliminate between
forty to one hundred species, erode seventy-one million tons of topsoil,
add 2,700 tons of CFCs to the stratosphere, and increase their population
by 263,000

Bowers, C.A. The Culture of Denial: Why the Environmental Movement Needs a
Strategy for Reforming Universities and Public Schools. New York: State
University of New York Press, 1997: (4) (5) (p.206)
Scott Shipp
2014-04-02 17:46:46 UTC
Permalink
Now I'm really hooked on this lambda business. I just updated my gist with newly learned code. (https://gist.github.com/scottashipp/9916656)

New comparison based on lines of code:
Lines of code in Java 7 - 70
Lines of code in Java 8 - 37

Scott

To: seajug-***@public.gmane.org
From: joe.bowbeer-***@public.gmane.org
Date: Tue, 1 Apr 2014 09:20:43 -0700
Subject: Re: [seajug] [ANN] JDK 8 Crash Course (3/27)


























Check out forEachOrdered, and the Ordering examples at the link below:

http://docs.oracle.com/javase/tutorial/collections/streams/parallelism.html


I think limit(n) is similar to Haskell's 'take'. There is also a skip(k).

On Tuesday, April 1, 2014, Scott Shipp <scottashipp-1ViLX0X+***@public.gmane.org> wrote:
























Due to a desire to answer Steve's question seriously, I've been experimenting with lambdas and comparing/contrasting the old SAM way versus the new Lambda way. The main example I wanted to try for myself was something I mentioned earlier, generating any series of numbers: https://gist.github.com/scottashipp/9916656


TL;DR - Lambdas are cool and yes, they are more readable as far as usage within the bounds of what they were designed to do.

Based on this experiment, I found a number of interesting observations:

1. It is more readable to do it the Lambda way, if you are using Lambdas the way they are designed.


2. It is not more readable if you abuse it. There were some things I tried where I think I found the limits of lambdas, at least in this particular case.

3. For this particular case of simply listing numbers to the screen in series order, .parallel() doesn't work...your numbers come back out of order...but this showed me how powerful parallel() could be when you might be doing something like updating objects in a collection, where order is not important.


4. The Lambda version is more expressive (more nerdy at least) if you like lines like "generateValue.andThen(format).apply(i)".

5. Speaking of the chained functions feature, that is really nice. Although I didn't do it in this example, you can see how abstracting the formatting completely away would be really helpful. In the Java 7 version, the method takes a "NumberFormat" object. But in the Java 8 version, it just takes a function which might encapsulate any kind of behavior. Sure, sure, if you really needed this in J7 you could easily create your own subclass of NumberFormat but there you are again writing way more code than you probably need to do something that is conceptually simple.


6. Lambdas are so horizontal, that you either keep them on one line which potentially runs past the right side of your screen or you break them up onto separate lines, in which case I wonder how much it really "solves the vertical problem."


This is mostly syntactic sugar but in the best sense. I think this actually accomplishes something for the developer in terms of the conceptual idea in the code matching the way you might actually think about. (Yes I know it is not ALL syntactic sugar since there are new scope rules, the potential for lazy evaluation, etc.)


Now for a question: does anyone know if Java 8 has anything like the Haskell "take" keyword (see example at http://mdickens.me/2013/12/16/those_weird_haskell_features_are_actually_useful/ )? That would be even better.


Scott


To: seajug-***@public.gmane.org
From: scottashipp-1ViLX0X+***@public.gmane.org

Date: Thu, 27 Mar 2014 16:16:19 -0700
Subject: RE: [seajug] Re: [ANN] JDK 8 Crash Course (3/27)





























I reviewed the code and I'll toss in my 2 cents on readability. Mainly: it's hard to say if it is more readable. Probably those of us programming in Java for awhile now will automatically think the JDK 7 and lower type of implementation will be "more readable" simply due to familiarity. I'm reserving my judgment until I can get time to sit down and absorb the lambda way of thinking more.


However, right now I don't like the idea of using Lambda expressions for stuff even as complex as the anagram kata, which is actually fairly simple. Instead, I like lambda's for things like filtering, counting, etc. from a larger collection. You know...stuff like generate all the fibonacci numbers up to some value or count the number of managers in this list of employees. Which is all I ever used the "old" way of passing anonymous classes into method parameters anyway. To my mind, even if something is readable / simple to me, it may not be readable to someone else on the team, maybe a jr dev not yet familiar with the concept? Perhaps it is best for maintenance purposes not to put so much idea-space into one line of code.


On another note, I noticed that your code takes the approach of rolling a private class as a data structure to hold the anagrams. I did this kata last year and instead of doing that I simply made a Map<String, List<String>> to hold the anagrams. You can see this at https://gist.github.com/scottashipp/7680127 with an explanation of the thought process at http://code.scottshipp.com/2013/11/27/given-a-word-file-find-all-words-that-are-anagrams/.


I find this to be simpler and more readable, personally. It basically cuts the solution down to 20 lines of code (the rest of my code is a small timer class and some basic output). However, if you are a developer who doesn't like nesting collections within collections this feels like anathema, I'm sure.


Anyway, my implementation didn't split lines of text into words, either, or do the other things in your guys' like find the longest, etc.

Parting thought: I particularly enjoyed this line in Joe's:

String keyWord = key(word);
Cheers,

Scott



To: seajug-***@public.gmane.org
From: lordjoe2000-***@public.gmane.org

Date: Thu, 27 Mar 2014 15:05:07 -0700
Subject: [seajug] Re: [ANN] JDK 8 Crash Course (3/27)



























Having looked at Joe BowBeer's Java 8 Anagrams bitbucket.org/joebowbeer/anagrams I decides to look at what a Java 7 implementation would look like -

http://bitbucket.org/steve_lewis_/anagrams-jdk-7The file is more verbose -my questions - 1) is it more readable
2) My version does the following
a) splits a line of text into words b) drops punctuation
It would be interesting to see how hard it would be to add those features to Joe's version Also look at both - neither has comments for readability and understandability





-
Douglas Pearson
2014-03-28 07:01:35 UTC
Permalink
I read both versions and I have to say that for me the Java 8 version is
the more readable one - and I haven't spent even 5 mins with Java 8 yet.

For me the brevity of the Java 8 implementation actually makes it simpler
to see how the methods are fitting together and hence how it works overall.
The problem I find for many chunks of Java code is trying to figure out
how it's pieced together - not what each element does.

Doug
Post by Steve Lewis
Having looked at Joe BowBeer's Java 8 Anagrams bitbucket.org/joebowbeer/
anagrams I decides to look at what a Java 7 implementation would look like -
http://bitbucket.org/steve_lewis_/anagrams-jdk-7
The file is more verbose -
my questions -
1) is it more readable
2) My version does the following
a) splits a line of text into words
b) drops punctuation
It would be interesting to see how hard it would be to add those features
to Joe's version
Also look at both - neither has comments for readability and
understandability
-
Steve Lewis
2014-04-03 17:40:37 UTC
Permalink
OK - this may be a rant on Readable code -
even before the days when we had Lambdas (last week) I believed that
complex lines of code where multiple functions were a very bad idea - that
might diminish the lines of code but at an enormous cost in readability and
maintainability.

Here is a a fairly typical line from a C++ program I am forced to do
maintenance on
sums[ord] += root4[m--]*(pows[ord][k] =
pows[ord/2][k]*pows[(ord&1)+(ord/2)][k]);

- look how compact - just ONE LINE OF CODE

Yes we can collapse many ideas into a single line of code
consider the game of life as a single line of APL
http://catpad.net/michael/apl/
or an entry from the obfuscated C contest
main(a,b)char**b;{int
c=1,d=c,e=a-d;for(;e;e--)_(e)<_(c)?c=e:_(e)>_(d)?d=e:7;
while(++e<a)printf("\xe2\x96%c",129+(**b=8*(_(e)-_(c))/(_(d)-_(c))));}


Look at Scott's code

Sure he can do everything in one line of code -
On the other hand I challenge anyong to explain in detail exactly
what that one line is doing - or more spscificallly how the line might be
modified -
for exanple to print all Fibonnacci numbers less than 10,000

A novice Java programmer can not only read the Old way and explain the
function of every line but make modifications
Any reader of this group can do so - try to do that with the 'newer' way


===================================================
The New 'better' way

System.out.printf("%nFirst 10 Fibonacci Numbers:%n");
IntStream.range(0,11).map(fibonacci = i -> { return i == 0 || i == 1 ? 1 :
fibonacci.applyAsInt(i - 2) + fibonacci.applyAsInt(i - 1);
}).parallel().forEachOrdered(e -> System.out.printf("%s ", e));

===================================================
The 'Old' better way


interface Generator {
double calculateNthInSeries(int n);
}
//see http://code.scottshipp.com/2013/06/25/fun-with-fibonacci/
static final Generator FIBONACCI = new Generator() {
public double calculateNthInSeries(int n) {
int a = 0;
int b = 1;
for(int i = 0; i < n; i++) {
a = b - a;
b = b + a;
}
return a;
}
};
public static List<String> generateSeries(int startingFrom, int howMany,
NumberFormat f, Generator g) {
String nextInSeries;
List<String> theSeries = new ArrayList<>();
for(int i = startingFrom; i < startingFrom + howMany; i++) {
nextInSeries =f.format(g.calculateNthInSeries(i));
theSeries.add(nextInSeries);
}
return theSeries;
}

======================================================
//Use of a static constant callback
System.out.printf("%nFirst 10 Fibonacci Numbers:%n");
for(String s : generateSeries(1, 10, myFormat, FIBONACCI)) {
System.out.printf("%s ", s);
}

I have always felt that maintenance represents teh majority of our work
and that readability is an important part of that
My friends who like Python love code like
var fib = FIBONACCI;
var format = SimpleFormal;
var answer = generateSeries( tartingFrom, howMany, format, fib)

I find the following more readable and we have not even gone to
collapsing many ideas to one unreadable line of code
Generator fib = FIBONACCI;
NumberFormat format = SimpleFormal;
List<String> answer = generateSeries( tartingFrom, howMany, format, fib)
Dennis Sosnoski
2014-04-03 20:57:41 UTC
Permalink
That was my initial reaction, too, Steve. But Scott has a comment on the
Github code "Gist is apparently not appreciating my Notepad++ tab
settings. Sorry guys.". His email says 37 lines for the Java 8 version,
while what shows on Github is 26 lines, so I suspect what happened is
his line breaks were not preserved when he checked in the code.

With appropriate line breaks I find the fluent style very readable.
Working with Scala helps. :-)

Assuming I'm correct, it's probably a good idea to reformat the code to
what you wanted with another editor and update the Github repository, Scott!

Regards,

- Dennis
Post by Steve Lewis
OK - this may be a rant on Readable code -
even before the days when we had Lambdas (last week) I believed that
complex lines of code where multiple functions were a very bad idea -
that might diminish the lines of code but at an enormous cost in
readability and maintainability.
Here is a a fairly typical line from a C++ program I am forced to do
maintenance on
sums[ord] += root4[m--]*(pows[ord][k] =
pows[ord/2][k]*pows[(ord&1)+(ord/2)][k]);
- look how compact - just ONE LINE OF CODE
Yes we can collapse many ideas into a single line of code
consider the game of life as a single line of APL
http://catpad.net/michael/apl/
or an entry from the obfuscated C contest
main(a,b)char**b;{int
c=1,d=c,e=a-d;for(;e;e--)_(e)<_(c)?c=e:_(e)>_(d)?d=e:7;
while(++e<a)printf("\xe2\x96%c",129+(**b=8*(_(e)-_(c))/(_(d)-_(c))));}
Look at Scott's code
Sure he can do everything in one line of code -
On the other hand I challenge anyong to explain in detail
exactly what that one line is doing - or more spscificallly how the
line might be modified -
for exanple to print all Fibonnacci numbers less than 10,000
A novice Java programmer can not only read the Old way and explain
the function of every line but make modifications
Any reader of this group can do so - try to do that with the 'newer' way
===================================================
The New 'better' way
System.out.printf("%nFirst 10 Fibonacci Numbers:%n");
IntStream.range(0,11).map(fibonacci = i -> { return i == 0 || i == 1 ?
1 : fibonacci.applyAsInt(i - 2) + fibonacci.applyAsInt(i - 1);
}).parallel().forEachOrdered(e -> System.out.printf("%s ", e));
===================================================
The 'Old' better way
interface Generator {
double calculateNthInSeries(int n);
}
//see http://code.scottshipp.com/2013/06/25/fun-with-fibonacci/
static final Generator FIBONACCI = new Generator() {
public double calculateNthInSeries(int n) {
int a = 0;
int b = 1;
for(int i = 0; i < n; i++) {
a = b - a;
b = b + a;
}
return a;
}
};
public static List<String> generateSeries(int startingFrom, int
howMany, NumberFormat f, Generator g) {
String nextInSeries;
List<String> theSeries = new ArrayList<>();
for(int i = startingFrom; i < startingFrom + howMany; i++) {
nextInSeries =f.format(g.calculateNthInSeries(i));
theSeries.add(nextInSeries);
}
return theSeries;
}
======================================================
//Use of a static constant callback
System.out.printf("%nFirst 10 Fibonacci Numbers:%n");
for(String s : generateSeries(1, 10, myFormat, FIBONACCI)) {
System.out.printf("%s ", s);
}
I have always felt that maintenance represents teh majority of our
work and that readability is an important part of that
My friends who like Python love code like
var fib = FIBONACCI;
var format = SimpleFormal;
var answer = generateSeries( tartingFrom, howMany, format, fib)
I find the following more readable and we have not even gone to
collapsing many ideas to one unreadable line of code
Generator fib = FIBONACCI;
NumberFormat format = SimpleFormal;
List<String> answer = generateSeries( tartingFrom, howMany, format, fib)
Scott Shipp
2014-04-07 16:00:08 UTC
Permalink
I actually edited the Gist after quoting the initial number of lines and the number of lines was reduced from 37 to 26. I figured after solving the challenge from Konstantin Ignatyev's post I would go ahead and drop the solution on the gist.
I did not write this as production code or to demonstrate what I think is clean and readable code, so it shouldn't be judged accordingly. You're free to discuss it as an example case of what to do, what not to do, etc. if you wish. Just know that I wasn't trying to win style awards. I was toying about with lambdas. :-)

Initially, I did not do either of the following:
a) use recursion as solution for Fibonnacci (performs terrible)b) put it all on one line
That being said, even though I wouldn't commit this code anywhere serious, I don't really feel another developer should have much trouble with understanding exactly what this is doing. It is pretty straightforward. It uses the new API without any weird bells and whistles.
Taking the line piece by piece, you can decipher according to the API at http://docs.oracle.com/javase/8/docs/api/java/util/stream/IntStream.html :
1) IntStream - "A sequence of primitive int-valued elements supporting sequential and parallel
aggregate operations"
2) .range(0,11) - "Returns a sequential ordered IntStream from startInclusive
(inclusive) to endExclusive (exclusive) by an incremental step of
1."
3) .map() - "Returns a stream consisting of the results of applying the given
function to the elements of this stream."
4) Inside the .map is a common Fibonacci function...if you haven't done Fibonacci since high school or whatever (this was someone's comment), you can review at http://rosettacode.org/wiki/Fibonacci_sequence
5) .parallel() - Joe Bowbeer has discussed this several times already. API states: "Returns an equivalent stream that is parallel."
6) .forEachOrdered() - Also thanks to Joe Bowbeer, take the random stream returned from parallel and put it in order.
7) e -> System.out.printf("%s ", e) - the part inside the forEachOrdered...I don't think I need to explain what this is doing.
Hope that clears the air,
Scott
To: seajug-***@public.gmane.org
From: dms-WAiJhE/vqclWk0Htik3J/***@public.gmane.org
Date: Fri, 4 Apr 2014 09:57:41 +1300
Subject: Re: [seajug] [ANN] JDK 8 Crash Course (3/27)






























That was my initial reaction, too,
Steve. But Scott has a comment on the Github code "Gist is
apparently not appreciating my Notepad++ tab settings. Sorry
guys.". His email says 37 lines for the Java 8 version, while what
shows on Github is 26 lines, so I suspect what happened is his
line breaks were not preserved when he checked in the code.



With appropriate line breaks I find the fluent style very
readable. Working with Scala helps.
:-)



Assuming I'm correct, it's probably a good idea to reformat the
code to what you wanted with another editor and update the Github
repository, Scott!



Regards,



- Dennis



On 04/04/2014 06:40 AM, Steve Lewis wrote:







OK - this may be a rant on Readable code -
even before the days when we had Lambdas (last week) I
believed that complex lines of code where multiple functions
were a very bad idea - that might diminish the lines of code
but at an enormous cost in readability and maintainability.



Here is a a fairly typical line from a C++ program I am
forced to do maintenance on

sums[ord]
+= root4[m--]*(pows[ord][k] =
pows[ord/2][k]*pows[(ord&1)+(ord/2)][k]);




- look how compact - just ONE LINE OF CODE

Yes we can collapse many ideas into a single line of
code
consider the game of life as a single line of APL http://catpad.net/michael/apl/
or an
entry from the obfuscated C contest
main(a,b)char**b;{int
c=1,d=c,e=a-d;for(;e;e--)_(e)<_(c)?c=e:_(e)>_(d)?d=e:7;
while(++e<a)printf("\xe2\x96%c",129+(**b=8*(_(e)-_(c))/(_(d)-_(c))));}


Look at Scott's code


Sure he can do everything in one line of code -
On the other hand I challenge anyong to explain in
detail exactly what that one line is doing - or more
spscificallly how the line might be modified -
for
exanple to print all Fibonnacci numbers less than 10,000

A
novice Java programmer can not only read the Old way and
explain the function of every line but make modifications
Any
reader of this group can do so - try to do that with the
'newer' way


===================================================
The New 'better' way



System.out.printf("%nFirst
10 Fibonacci Numbers:%n");
IntStream.range(0,11).map(fibonacci
= i -> { return i == 0 || i == 1 ? 1 :
fibonacci.applyAsInt(i - 2) + fibonacci.applyAsInt(i - 1);
}).parallel().forEachOrdered(e -> System.out.printf("%s
", e));



===================================================
The 'Old' better way




interface
Generator {
double
calculateNthInSeries(int n);
}

//see http://code.scottshipp.com/2013/06/25/fun-with-fibonacci/
static
final Generator FIBONACCI = new Generator() {
public
double calculateNthInSeries(int n) {
int a =
0;
int b =
1;
for(int i
= 0; i < n; i++) {
a = b -
a;
b = b +
a;
}
return a;
}
};

public
static List<String> generateSeries(int startingFrom,
int howMany, NumberFormat f, Generator g) {
String
nextInSeries;
List<String>
theSeries = new ArrayList<>();
for(int i
= startingFrom; i < startingFrom + howMany; i++) {
nextInSeries
=f.format(g.calculateNthInSeries(i));
theSeries.add(nextInSeries);
}
return
theSeries;
}


======================================================
//Use of
a static constant callback
System.out.printf("%nFirst
10 Fibonacci Numbers:%n");

for(String s
: generateSeries(1, 10, myFormat, FIBONACCI)) {
System.out.printf("%s
", s);
}



I have always felt that maintenance represents teh
majority of our work and that readability is an important
part of that

My
friends who like Python love code like

var fib =
FIBONACCI;
var
format = SimpleFormal;

var answer =
generateSeries( tartingFrom, howMany, format, fib)




I find the following more readable and we have not
even gone to collapsing many ideas to one unreadable line of
code

Generator
fib = FIBONACCI;
NumberFormat
format = SimpleFormal;
List<String>
answer = generateSeries( tartingFrom, howMany, format,
fib)

Loading...