London Lambdas Hackday: Developer Practices

Howard Lovatt howard.lovatt at gmail.com
Tue Jul 3 22:49:49 PDT 2012


Re. Chaining

I personally like the chaining style (particularly with the dots lined up).
However, I have found it a pain with the Netbeans debugger because you
can't see the intermediate results. This has often caused me to introduce
variables for all the steps and to return the final array separately (so I
can see what is happening).

Any idea if IDEs and the underlying connection to the JVM will be updated
to support seeing intermediates?

On 4 July 2012 01:13, Brian Goetz <brian.goetz at oracle.com> wrote:

> > 1. addAll vs into
> >
> > A developer had an interable that he wanted to put all the values from
> > into a collection.  He tried to use addAll, but it works over a
> > collection, not an iterable.  He could have used into and flipped
> > dispatch object with the argument, but it wasn't obvious to do that.
> > This might be just a case of 'old habits die hard' but it might also
> > be
>
> Whatever we do here will change when streams are more Iterator-like and
> less Iterable-like.  (This is a big theme for the next round of API
> design, currently in progress in a branch, which should be rolled out
> hopefully soon.)  Would a Stream.concat(otherStream) method do what you
> were thinking of?
>
> > 3.  Some feedback from Martijn:
> >
> > I noticed that I happily started using a chaining idiom in my code, e.g.
> >
> > return students.filter(student -> student.getAge() > 18).into(new
> > ArrayList<>());
> >
> > Given my lack of recent functional programming expertise, I think this
> > is a good thing. But I'm a little concerned that the chaining idiom
> > becomes hard to read for non-functional programmers, some education
> > might be required.  Perhaps in the educational material, samples are
> > laid out like so (each 'chained' method is lined up with the method
> > before it):
> >
> > return students.filter(student -> student.getAge() > 18)
> >                     .into(new ArrayList<>());
>
> Absolutely.  In all our sample code, we use one method per line, with
> the dots lining up.  IDEs mostly support this.
>
> > You might also find Java developers wanting to pull everything back
> > into a local variable, e.g.:
> >
> > List<Student> filteredStudents = new ArrayList<>()
> > return students.filter(student -> student.getAge() >
> 18).into(filteredStudents);
>
> This is a common first impulse of Java developers -- give everything a
> name -- but will probably be overused until people get comfortable with
> chaining.  A major design goal for these libraries has been to enable
> getting rid of the "garbage intermediate variables".  The farther
> between their declaration and use (say, if the chain in the above
> example were longer), the more problematic the garbage variables become.
>
> > Another example pulling the Predicate in locally:
> >
> > Predicate<Student> isLegal = (Student student) -> student.getAge() > 18;
> > return students.filter(isLegal).into(new ArrayList<Student>());
>
> If people want to do this for readability or reuse, that's fine.  (If
> they think there is any performance benefit to it, they're mistaken;
> stateless lambda captures are optimized into constant loads.)
>
> > One other (unecessary?) idiom they might use is assigning back to a
> > collection that is the result of the filter/reduce/map/whatever, e.g.:
> >
> > List<Student> legalStudents = new ArrayList<>();
> > Predicate<Student> isLegal = (Student student) -> student.getAge() > 18;
> > legalStudents = students.filter(isLegal).into(legalStudents);
> > return legalStudents;
> > // as opposed to
> > // return students.filter(isLegal).into(legalStudents);
>
> Right.  These will be hard habits for people to break.
>
> > 4. Type inference
> >
> > IDE or compiler support might be needed to teach developers that Java
> > is smarter than they think with regards to Type inference.  For
> > example a refactor to do the following:
> >
> > // Predicate<Student> isAdult = (Student student) -> student.getAge() >
> 18;
> > // Can be written as:
> > Predicate<Student> isAdult = student -> student.getAge() > 18;
> >
> > Perhaps a -lint option on javac for this kind of thing would be
> > useful?  I guess it ultimately depends on how the expected idiom for
> > writing this code works.
>
> I expect IDEs will auto-suggest for this.
>
> > 5. Function Composition
> >
> > There was a genuine desire from people to have function composition.
> > This was somewhat driven by people with experience of functional
> > programming in other languages, but there were still scenarios where
> > it seemed like the cleanest idiom.  The lack of function types seems
> > to make it hard to introduce function composition in the general case,
> > but is there an expectation that composition methods will be provided
> > for all the functional core library interfaces?
>
> There is some very limited type-specific composition, such as
> Mapper.compose or Predicate.{and,or}.  But I suspect whatever we might
> do in the area of general-purpose composition would be deeply
> disappointing to functies.  So we're unlikely to do much here.
>
>
>
>
>


-- 
  -- Howard.


More information about the lambda-dev mailing list