SlideShare a Scribd company logo
Jamie Allen | Typesafe

What You Need to Know About Lambdas

Wednesday, November 6, 13
Who Am I?
• Director of Consulting for
• User of lambdas on the JVM for ~5 years
@jamie_allen

Wednesday, November 6, 13
Wednesday, November 6, 13
Wednesday, November 6, 13
Wednesday, November 6, 13
I Love Functional Programming!

• Functional Programming is:
• Immutability
• Referential Transparency
• Functions as first-class citizens
Wednesday, November 6, 13
We Want Declarative Code
final List<Integer> numbers =
Arrays.asList(1, 2, 3);
final List<Integer> numbersPlusOne =
Collections.emptyList();
for (Integer number : numbers) {
final Integer numberPlusOne = number + 1;
numbersPlusOne.add(numberPlusOne);
}

Wednesday, November 6, 13
What is a Lambda?
• A function literal
• Not bound to a variable name, can only be
used in the context of where it is defined

• Merely one of many possible

implementations you can use in Functional
Programming

Wednesday, November 6, 13
Java 8
import java.util.List;
import java.util.Arrays;
import java.util.stream.Collectors;
public class LambdaDemo {
public static void main(String... args) {
final List<Integer> numbers =
Arrays.asList(1, 2, 3);

}

}

Wednesday, November 6, 13

λ

final List<Integer> numbersPlusOne =
numbers.stream().map(number -> number + 1).
collect(Collectors.toList());
Nashorn Javascript
#!/usr/bin/env jjs -scripting
var result = [];
var list = new java.util.ArrayList();
list.add(1);
list.add(2);
list.add(3);
list.parallelStream().
map(function(e) e + 1).
forEach(function(t) result.push(t));

Wednesday, November 6, 13

λ
Scala
λ
object LambdaDemo extends App {
val numbers = List(1, 2, 3)
val numbersPlusOne =
numbers.map(number => number + 1)
}

Wednesday, November 6, 13
Clojure
λ
(ns LambdaDemo.core)
(defn -main [& args]
(println(map #(+ % 1) [1, 2, 3])))

Wednesday, November 6, 13
JRuby
require "java"
array = [1, 2, 3]
array.collect! do |n|
n + 1
end

Wednesday, November 6, 13

λ
What is the Problem?

Wednesday, November 6, 13
There Are Caveats

Wednesday, November 6, 13
Not Reusable
• Lambdas are limited in scope to their call
site

• You cannot reuse the functionality
elsewhere

Wednesday, November 6, 13
Not Testable in Isolation
• How can you test code by itself when you
have no identifier through which you can
call it?

• You can only test them by writing more
tests for their enclosing method

Wednesday, November 6, 13
Maintainability
• There is nothing inherently descriptive
about a lambda

• Developers have to read through the entire
lambda to figure out what it is doing

• The more complex the lambda is, the
harder this is to do

• Waste of valuable development time
Wednesday, November 6, 13
Example
• In Scala, I sometimes see code like this:
	
  	
  	
  	
  	
  	
  	
  	
  val	
  next	
  =	
  x.map	
  {
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  case	
  Success(k)	
  =>	
  {
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  deriveValueAsynchronously(worker(initValue))(pec).map	
  {
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  case	
  None	
  =>	
  {
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  val	
  remainingWork	
  =	
  k(Input.EOF)
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  success(remainingWork)
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  None
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  }
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  case	
  Some(read)	
  =>	
  {
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  val	
  nextWork	
  =	
  k(Input.El(read))
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  Some(nextWork)
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  }
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  }(dec)
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  }
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  case	
  _	
  =>	
  {	
  success(it);	
  Future.successful(None)	
  }
	
  	
  	
  	
  	
  	
  	
  	
  }(dec)

Wednesday, November 6, 13

}}

}λ
}λ
}

λ

λ

λ
Wednesday, November 6, 13
Lousy Stack Traces
• Compilers have to come up with generic

names for their representation of lambdas
to run on the JVM, called “name mangling”

• The stack trace output tells you very little
about where the problem occurred

Wednesday, November 6, 13
Java 8
numbers.stream().map(number -> number / 0)
Exception in thread "main" java.lang.ArithmeticException: / by zero
at LambdaDemo.lambda$0(LambdaDemo.java:9)
at LambdaDemo$$Lambda$1.apply(Unknown Source)
at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193)
at java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:948)
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:512)
at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:502)
at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:510)
at LambdaDemo.main(LambdaDemo.java:9)

wat

Wednesday, November 6, 13
Nashorn Javascript
list.parallelStream().
map(function(e) e / 0)
[1, 2, 3]
Infinity,Infinity

Wednesday, November 6, 13
Nashorn Javascript
list.parallelStream().
map(function(e) e / 0)
[1, 2, 3]
Infinity,Infinity

Wednesday, November 6, 13
Favorite Tweet Ever
“JavaScript doesn't have a dark side, but
it does have a dimly lit room full of
angry clowns with rubber mallets.”
- @odetocode, Jan 5, 2010

Wednesday, November 6, 13
Scala
val numbersPlusOne = numbers.map(number => number / 0)
Exception in thread "main" java.lang.ArithmeticException: / by zero
at org.jamieallen.effectiveakka.pattern.extra.LambdaTest$$anonfun$1.apply(LambdaPlayground.scala:23)
at org.jamieallen.effectiveakka.pattern.extra.LambdaTest$$anonfun$1.apply(LambdaPlayground.scala:23)
at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:244)
at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:244)
at scala.collection.immutable.Range.foreach(Range.scala:141)
at scala.collection.TraversableLike$class.map(TraversableLike.scala:244)
at scala.collection.AbstractTraversable.map(Traversable.scala:105)
at org.jamieallen.effectiveakka.pattern.extra.LambdaTest$delayedInit$body.apply(LambdaPlayground.scala:23)
at scala.Function0$class.apply$mcV$sp(Function0.scala:40)
at scala.runtime.AbstractFunction0.apply$mcV$sp(AbstractFunction0.scala:12)
at scala.App$$anonfun$main$1.apply(App.scala:71)
at scala.App$$anonfun$main$1.apply(App.scala:71)
at scala.collection.immutable.List.foreach(List.scala:318)
at scala.collection.generic.TraversableForwarder$class.foreach(TraversableForwarder.scala:32)
at scala.App$class.main(App.scala:71)
at org.jamieallen.effectiveakka.pattern.extra.LambdaTest$.main(LambdaPlayground.scala:22)
at org.jamieallen.effectiveakka.pattern.extra.LambdaTest.main(LambdaPlayground.scala)

wat

Wednesday, November 6, 13
Clojure

println(map #(/ % 0) [1, 2, 3])))

Exception in thread "main" (java.lang.ArithmeticException: Divide by zero
at clojure.lang.Numbers.divide(Numbers.java:156)
at clojure.lang.Numbers.divide(Numbers.java:3671)
at helloclj.core$_main$fn__10.invoke(core.clj:5)
at clojure.core$map$fn__4087.invoke(core.clj:2432)
at clojure.lang.LazySeq.sval(LazySeq.java:42)
at clojure.lang.LazySeq.seq(LazySeq.java:60)
at clojure.lang.RT.seq(RT.java:473)
at clojure.core$seq.invoke(core.clj:133)
at clojure.core$print_sequential.invoke(core_print.clj:46)
at clojure.core$fn__5270.invoke(core_print.clj:140)
at clojure.lang.MultiFn.invoke(MultiFn.java:167)
at clojure.core$pr_on.invoke(core.clj:3266)
at clojure.core$pr.invoke(core.clj:3278)
at clojure.lang.AFn.applyToHelper(AFn.java:161)
at clojure.lang.RestFn.applyTo(RestFn.java:132)
at clojure.core$apply.invoke(core.clj:601)
at clojure.core$prn.doInvoke(core.clj:3311)
at clojure.lang.RestFn.applyTo(RestFn.java:137)
at clojure.core$apply.invoke(core.clj:601)
at clojure.core$println.doInvoke(core.clj:3331)
at clojure.lang.RestFn.invoke(RestFn.java:408)
at helloclj.core$_main.invoke(core.clj:5)
at clojure.lang.Var.invoke(Var.java:411)
...
at clojure.main.main(main.java:37)

wat

Wednesday, November 6, 13
JRuby
array.collect! do |n|
n / 0
ZeroDivisionError: divided by 0
/ at org/jruby/RubyFixnum.java:547
(root) at HelloWorld.rb:11
collect! at org/jruby/RubyArray.java:2385
(root) at HelloWorld.rb:10

not half bad, really

Wednesday, November 6, 13
Difficult Debugging
• Debuggers on the JVM can only

disambiguate code at the source line write your lambdas to leverage this

final List<Integer> numbersPlusOne = numbers.stream().
map(number -> number + 1).collect(Collectors.toList());

NO!

Wednesday, November 6, 13
Digression: Lambdas versus Closures

• In the purest sense, closures are merely

lambdas that close over some state from
outside of their enclosing scope

final int x = 1;
final List<Integer> numbersPlusOne =
numbers.stream().map(number -> number + x).
collect(Collectors.toList());

Wednesday, November 6, 13
Closing Over State

•

Lambdas have access to all variables that are in
scope

•

It is very easy to “close over” something
mutable and cause headaches in multi-threaded
code

•

Java enforces that values to be closed over are
final, but that only affects assignment - you can
still change what is INSIDE that variable (like
the contents of a collection)

Wednesday, November 6, 13
Solution
We want to maintain our ability to program
in a functional style, while having something
maintainable and understandable in
production

Wednesday, November 6, 13
Named Functions?
• Seems like it would help, but it depends on
the compiler and how it manages the
“scope” of that function

• It is possible that stack traces will still not
show the name of the function

Wednesday, November 6, 13
Named Function
object LambdaTest extends App {
val addOneToValue = (x: Int) => x + 1
}

val myList = (1 to 20).map(addOneToValue)

Wednesday, November 6, 13
Named Function Stack Trace
val badFunction = (x: Int) => x / 0
val myList = (1 to 20).map(badFunction)
Exception in thread "main" java.lang.ArithmeticException: / by zero
	
at org.jamieallen.effectiveakka.pattern.extra.LambdaTest$$anonfun$1.apply$mcII$sp(LambdaPlayground.scala:23)
	
at org.jamieallen.effectiveakka.pattern.extra.LambdaTest$$anonfun$2.apply(LambdaPlayground.scala:24)
	
at org.jamieallen.effectiveakka.pattern.extra.LambdaTest$$anonfun$2.apply(LambdaPlayground.scala:24)
	
at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:244)
	
at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:244)
	
at scala.collection.immutable.Range.foreach(Range.scala:141)
	
at scala.collection.TraversableLike$class.map(TraversableLike.scala:244)
	
at scala.collection.AbstractTraversable.map(Traversable.scala:105)
	
at org.jamieallen.effectiveakka.pattern.extra.LambdaTest$delayedInit$body.apply(LambdaPlayground.scala:24)
	
at scala.Function0$class.apply$mcV$sp(Function0.scala:40)
	
at scala.runtime.AbstractFunction0.apply$mcV$sp(AbstractFunction0.scala:12)
	
at scala.App$$anonfun$main$1.apply(App.scala:71)
	
at scala.App$$anonfun$main$1.apply(App.scala:71)
	
at scala.collection.immutable.List.foreach(List.scala:318)
	
at scala.collection.generic.TraversableForwarder$class.foreach(TraversableForwarder.scala:32)
	
at scala.App$class.main(App.scala:71)
	
at org.jamieallen.effectiveakka.pattern.extra.LambdaTest$.main(LambdaPlayground.scala:22)
	
at org.jamieallen.effectiveakka.pattern.extra.LambdaTest.main(LambdaPlayground.scala)

wat

Wednesday, November 6, 13
“Lifting” a Method
• We have the ability in Java 8 and Scala to

“lift” or coerce a method into a function

• The method must meet the contract of the
lambda usage of the compiler, such as only
taking one argument representing the input
of the function

Wednesday, November 6, 13
Stack Trace of a Method
def badFunction = (x: Int) => x / 0
val myList = (1 to 20).map(badFunction)
Exception in thread "main" java.lang.ArithmeticException: / by zero
	
at org.jamieallen.effectiveakka.pattern.extra.LambdaTest$$anonfun$badFunction$1.apply$mcII$sp(LambdaPlayground.scala:23)
	
at org.jamieallen.effectiveakka.pattern.extra.LambdaTest$$anonfun$1.apply(LambdaPlayground.scala:24)
	
at org.jamieallen.effectiveakka.pattern.extra.LambdaTest$$anonfun$1.apply(LambdaPlayground.scala:24)
	
at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:244)
	
at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:244)
	
at scala.collection.immutable.Range.foreach(Range.scala:141)
	
at scala.collection.TraversableLike$class.map(TraversableLike.scala:244)
	
at scala.collection.AbstractTraversable.map(Traversable.scala:105)
	
at org.jamieallen.effectiveakka.pattern.extra.LambdaTest$delayedInit$body.apply(LambdaPlayground.scala:24)
	
at scala.Function0$class.apply$mcV$sp(Function0.scala:40)
	
at scala.runtime.AbstractFunction0.apply$mcV$sp(AbstractFunction0.scala:12)
	
at scala.App$$anonfun$main$1.apply(App.scala:71)
	
at scala.App$$anonfun$main$1.apply(App.scala:71)
	
at scala.collection.immutable.List.foreach(List.scala:318)
	
at scala.collection.generic.TraversableForwarder$class.foreach(TraversableForwarder.scala:32)
	
at scala.App$class.main(App.scala:71)
	
at org.jamieallen.effectiveakka.pattern.extra.LambdaTest$.main(LambdaPlayground.scala:22)
	
at org.jamieallen.effectiveakka.pattern.extra.LambdaTest.main(LambdaPlayground.scala)

Better, but
why $1

Wednesday, November 6, 13
Digression
• You can define your methods like that, but
“def” is not stable - it will reevaluate the
right side of the equals sign and return a
new but identical function each time!
def badFunction = (x: Int) => x / 0

•

Better to stick with simple method syntax instead
def badFunction(x: Int) = x / 0

Wednesday, November 6, 13
Stack Trace of a Stable Method
def badFunction(x: Int) = x / 0
val myList = (1 to 20).map(badFunction)
Exception in thread "main" java.lang.ArithmeticException: / by zero
	
at org.jamieallen.effectiveakka.pattern.extra.LambdaTest$.badFunction(LambdaPlayground.scala:24)
	
at org.jamieallen.effectiveakka.pattern.extra.LambdaTest$$anonfun$1.apply(LambdaPlayground.scala:25)
	
at org.jamieallen.effectiveakka.pattern.extra.LambdaTest$$anonfun$1.apply(LambdaPlayground.scala:25)
	
at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:244)
	
at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:244)
	
at scala.collection.immutable.Range.foreach(Range.scala:141)
	
at scala.collection.TraversableLike$class.map(TraversableLike.scala:244)
	
at scala.collection.AbstractTraversable.map(Traversable.scala:105)
	
at org.jamieallen.effectiveakka.pattern.extra.LambdaTest$delayedInit$body.apply(LambdaPlayground.scala:25)
	
at scala.Function0$class.apply$mcV$sp(Function0.scala:40)
	
at scala.runtime.AbstractFunction0.apply$mcV$sp(AbstractFunction0.scala:12)
	
at scala.App$$anonfun$main$1.apply(App.scala:71)
	
at scala.App$$anonfun$main$1.apply(App.scala:71)
	
at scala.collection.immutable.List.foreach(List.scala:318)
	
at scala.collection.generic.TraversableForwarder$class.foreach(TraversableForwarder.scala:32)
	
at scala.App$class.main(App.scala:71)
	
at org.jamieallen.effectiveakka.pattern.extra.LambdaTest$.main(LambdaPlayground.scala:22)
	
at org.jamieallen.effectiveakka.pattern.extra.LambdaTest.main(LambdaPlayground.scala)

Perfect!

Wednesday, November 6, 13
Benefits
• You can’t close over variables
• Better stack traces
• More debuggable
• More testable
• More maintainable and descriptive
• Reusable
Wednesday, November 6, 13
Rule of Thumb
• Reserve lambda usage for the most basic
expressions

• Externalize anything more significant than
that to methods

Wednesday, November 6, 13
Language Creators
• Language designers and tool producers
need to help us

• At Typesafe, we’re making our Eclipse-based
Scala IDE more lambda-friendly with each
release

Wednesday, November 6, 13
Thank You!

• Questions?

Wednesday, November 6, 13

More Related Content

PDF
20160520 what youneedtoknowaboutlambdas
PDF
Scala : language of the future
PPTX
A Brief Intro to Scala
PPT
Scala Talk at FOSDEM 2009
PDF
Effective Scala (JavaDay Riga 2013)
PDF
DSLs in JavaScript
ODP
A Tour Of Scala
PPTX
Overview of CoffeeScript
20160520 what youneedtoknowaboutlambdas
Scala : language of the future
A Brief Intro to Scala
Scala Talk at FOSDEM 2009
Effective Scala (JavaDay Riga 2013)
DSLs in JavaScript
A Tour Of Scala
Overview of CoffeeScript

What's hot (20)

KEY
Static or Dynamic Typing? Why not both?
PDF
Introduction to Scala for Java Developers
PDF
How to write a TableGen backend
PDF
Ruby Performance - The Last Mile - RubyConf India 2016
PDF
PHP 8.1 - What's new and changed
PPTX
Scala final ppt vinay
PPTX
Scala - The Simple Parts, SFScala presentation
PDF
Scala @ TechMeetup Edinburgh
PDF
Productive Programming in Java 8 - with Lambdas and Streams
PDF
Down the Rabbit Hole: An Adventure in JVM Wonderland
PDF
JRuby 9000 - Optimizing Above the JVM
PPT
Ruby For Java Programmers
ODP
Getting started with Perl XS and Inline::C
ODP
How Xslate Works
ODP
Domain Specific Languages In Scala Duse3
PPTX
Intro to Functional Programming in Scala
PDF
Introduction to Perl and BioPerl
PDF
JRuby and Invokedynamic - Japan JUG 2015
PPTX
Scala fundamentals
Static or Dynamic Typing? Why not both?
Introduction to Scala for Java Developers
How to write a TableGen backend
Ruby Performance - The Last Mile - RubyConf India 2016
PHP 8.1 - What's new and changed
Scala final ppt vinay
Scala - The Simple Parts, SFScala presentation
Scala @ TechMeetup Edinburgh
Productive Programming in Java 8 - with Lambdas and Streams
Down the Rabbit Hole: An Adventure in JVM Wonderland
JRuby 9000 - Optimizing Above the JVM
Ruby For Java Programmers
Getting started with Perl XS and Inline::C
How Xslate Works
Domain Specific Languages In Scala Duse3
Intro to Functional Programming in Scala
Introduction to Perl and BioPerl
JRuby and Invokedynamic - Japan JUG 2015
Scala fundamentals
Ad

Viewers also liked (20)

PPTX
Why other ppl_dont_get_it
PPTX
45 second video proposal
PDF
Real-world polyglot programming on the JVM - Ben Summers (ONEIS)
PDF
Design is a Process, not an Artefact - Trisha Gee (MongoDB)
PPTX
Interactive media applications
PPTX
Interactive media applications
PDF
Are you better than a coin toss? - Richard Warbuton & John Oliver (jClarity)
PDF
Designing and Building a Graph Database Application - Ian Robinson (Neo Techn...
PDF
Little words of wisdom for the developer - Guillaume Laforge (Pivotal)
PDF
Introducing Vert.x 2.0 - Taking polyglot application development to the next ...
PDF
Packed Objects: Fast Talking Java Meets Native Code - Steve Poole (IBM)
PDF
Databases and agile development - Dwight Merriman (MongoDB)
PDF
Streams and Things - Darach Ennis (Ubiquiti Networks)
PDF
Lambda Expressions: Myths and Mistakes - Richard Warburton (jClarity)
PDF
Are Hypermedia APIs Just Hype? - Aaron Phethean (Temenos) & Daniel Feist (Mul...
PDF
Big data from the LHC commissioning: practical lessons from big science - Sim...
PDF
How Windows 10 will change the way we use devices
PPTX
Bringing your app to the web with Dart - Chris Buckett (Entity Group)
PDF
The state of the art biorepository at ILRI
PPT
How Java got its Mojo Back - James Governor (Redmonk)
Why other ppl_dont_get_it
45 second video proposal
Real-world polyglot programming on the JVM - Ben Summers (ONEIS)
Design is a Process, not an Artefact - Trisha Gee (MongoDB)
Interactive media applications
Interactive media applications
Are you better than a coin toss? - Richard Warbuton & John Oliver (jClarity)
Designing and Building a Graph Database Application - Ian Robinson (Neo Techn...
Little words of wisdom for the developer - Guillaume Laforge (Pivotal)
Introducing Vert.x 2.0 - Taking polyglot application development to the next ...
Packed Objects: Fast Talking Java Meets Native Code - Steve Poole (IBM)
Databases and agile development - Dwight Merriman (MongoDB)
Streams and Things - Darach Ennis (Ubiquiti Networks)
Lambda Expressions: Myths and Mistakes - Richard Warburton (jClarity)
Are Hypermedia APIs Just Hype? - Aaron Phethean (Temenos) & Daniel Feist (Mul...
Big data from the LHC commissioning: practical lessons from big science - Sim...
How Windows 10 will change the way we use devices
Bringing your app to the web with Dart - Chris Buckett (Entity Group)
The state of the art biorepository at ILRI
How Java got its Mojo Back - James Governor (Redmonk)
Ad

Similar to What You Need to Know About Lambdas - Jamie Allen (Typesafe) (20)

PDF
What You Need to Know about Lambdas
PDF
What you need to know about Lambdas - Jamie Allen
PDF
Functional Thinking for Java Developers (presented in Javafest Bengaluru)
PDF
Lambda Functions in Java 8
PDF
Programming in Scala: Notes
PPTX
Lambdas puzzler - Peter Lawrey
PDF
Lambda? You Keep Using that Letter
PDF
Functional Thinking - Programming with Lambdas in Java 8
PPTX
Functional Programming In Jdk8
PDF
Scala Paradigms
PDF
Functional Programming in Java 8 - Exploiting Lambdas
PDF
Java 8 lambda expressions
PDF
Java 8
PPTX
Scala, Play 2.0 & Cloud Foundry
PPTX
It's Java Jim, But Not As We Know It!
PPTX
Week-1..................................
PDF
PDF
JSR 335 / java 8 - update reference
PPTX
Softshake 2013: 10 reasons why java developers are jealous of Scala developers
PDF
Java 8 features
What You Need to Know about Lambdas
What you need to know about Lambdas - Jamie Allen
Functional Thinking for Java Developers (presented in Javafest Bengaluru)
Lambda Functions in Java 8
Programming in Scala: Notes
Lambdas puzzler - Peter Lawrey
Lambda? You Keep Using that Letter
Functional Thinking - Programming with Lambdas in Java 8
Functional Programming In Jdk8
Scala Paradigms
Functional Programming in Java 8 - Exploiting Lambdas
Java 8 lambda expressions
Java 8
Scala, Play 2.0 & Cloud Foundry
It's Java Jim, But Not As We Know It!
Week-1..................................
JSR 335 / java 8 - update reference
Softshake 2013: 10 reasons why java developers are jealous of Scala developers
Java 8 features

More from jaxLondonConference (20)

PDF
Garbage Collection: the Useful Parts - Martijn Verburg & Dr John Oliver (jCla...
PDF
Conflict Free Replicated Data-types in Eventually Consistent Systems - Joel J...
PDF
JVM Support for Multitenant Applications - Steve Poole (IBM)
PDF
Java Testing With Spock - Ken Sipe (Trexin Consulting)
PDF
Big Events, Mob Scale - Darach Ennis (Push Technology)
PDF
What makes Groovy Groovy - Guillaume Laforge (Pivotal)
PDF
The Java Virtual Machine is Over - The Polyglot VM is here - Marcus Lagergren...
PDF
Java EE 7 Platform: Boosting Productivity and Embracing HTML5 - Arun Gupta (R...
PPT
Exploring the Talend unified Big Data toolset for sentiment analysis - Ben Br...
PDF
The Curious Clojurist - Neal Ford (Thoughtworks)
PPTX
TDD at scale - Mash Badar (UBS)
PDF
Run Your Java Code on Cloud Foundry - Andy Piper (Pivotal)
PDF
Scaling Scala to the database - Stefan Zeiger (Typesafe)
PDF
Put your Java apps to sleep? Find out how - John Matthew Holt (Waratek)
PPTX
Project Lambda: Functional Programming Constructs in Java - Simon Ritter (Ora...
PPTX
Do You Like Coffee with Your dessert? Java and the Raspberry Pi - Simon Ritte...
PPTX
Large scale, interactive ad-hoc queries over different datastores with Apache...
PDF
Designing Resilient Application Platforms with Apache Cassandra - Hayato Shim...
PPTX
Practical Performance: Understand the Performance of Your Application - Chris...
PDF
How Hailo fuels its growth using NoSQL storage and analytics - Dave Gardner (...
Garbage Collection: the Useful Parts - Martijn Verburg & Dr John Oliver (jCla...
Conflict Free Replicated Data-types in Eventually Consistent Systems - Joel J...
JVM Support for Multitenant Applications - Steve Poole (IBM)
Java Testing With Spock - Ken Sipe (Trexin Consulting)
Big Events, Mob Scale - Darach Ennis (Push Technology)
What makes Groovy Groovy - Guillaume Laforge (Pivotal)
The Java Virtual Machine is Over - The Polyglot VM is here - Marcus Lagergren...
Java EE 7 Platform: Boosting Productivity and Embracing HTML5 - Arun Gupta (R...
Exploring the Talend unified Big Data toolset for sentiment analysis - Ben Br...
The Curious Clojurist - Neal Ford (Thoughtworks)
TDD at scale - Mash Badar (UBS)
Run Your Java Code on Cloud Foundry - Andy Piper (Pivotal)
Scaling Scala to the database - Stefan Zeiger (Typesafe)
Put your Java apps to sleep? Find out how - John Matthew Holt (Waratek)
Project Lambda: Functional Programming Constructs in Java - Simon Ritter (Ora...
Do You Like Coffee with Your dessert? Java and the Raspberry Pi - Simon Ritte...
Large scale, interactive ad-hoc queries over different datastores with Apache...
Designing Resilient Application Platforms with Apache Cassandra - Hayato Shim...
Practical Performance: Understand the Performance of Your Application - Chris...
How Hailo fuels its growth using NoSQL storage and analytics - Dave Gardner (...

Recently uploaded (20)

PDF
Chapter 3 Spatial Domain Image Processing.pdf
PDF
Advanced methodologies resolving dimensionality complications for autism neur...
PDF
Building Integrated photovoltaic BIPV_UPV.pdf
PDF
Encapsulation_ Review paper, used for researhc scholars
PDF
Modernizing your data center with Dell and AMD
DOCX
The AUB Centre for AI in Media Proposal.docx
PDF
Blue Purple Modern Animated Computer Science Presentation.pdf.pdf
PDF
Build a system with the filesystem maintained by OSTree @ COSCUP 2025
PDF
KodekX | Application Modernization Development
PDF
Peak of Data & AI Encore- AI for Metadata and Smarter Workflows
PDF
Agricultural_Statistics_at_a_Glance_2022_0.pdf
PPTX
Big Data Technologies - Introduction.pptx
PDF
Reach Out and Touch Someone: Haptics and Empathic Computing
PPTX
20250228 LYD VKU AI Blended-Learning.pptx
PDF
Mobile App Security Testing_ A Comprehensive Guide.pdf
PDF
Encapsulation theory and applications.pdf
PPTX
A Presentation on Artificial Intelligence
PPTX
Digital-Transformation-Roadmap-for-Companies.pptx
PDF
Empathic Computing: Creating Shared Understanding
PDF
Shreyas Phanse Resume: Experienced Backend Engineer | Java • Spring Boot • Ka...
Chapter 3 Spatial Domain Image Processing.pdf
Advanced methodologies resolving dimensionality complications for autism neur...
Building Integrated photovoltaic BIPV_UPV.pdf
Encapsulation_ Review paper, used for researhc scholars
Modernizing your data center with Dell and AMD
The AUB Centre for AI in Media Proposal.docx
Blue Purple Modern Animated Computer Science Presentation.pdf.pdf
Build a system with the filesystem maintained by OSTree @ COSCUP 2025
KodekX | Application Modernization Development
Peak of Data & AI Encore- AI for Metadata and Smarter Workflows
Agricultural_Statistics_at_a_Glance_2022_0.pdf
Big Data Technologies - Introduction.pptx
Reach Out and Touch Someone: Haptics and Empathic Computing
20250228 LYD VKU AI Blended-Learning.pptx
Mobile App Security Testing_ A Comprehensive Guide.pdf
Encapsulation theory and applications.pdf
A Presentation on Artificial Intelligence
Digital-Transformation-Roadmap-for-Companies.pptx
Empathic Computing: Creating Shared Understanding
Shreyas Phanse Resume: Experienced Backend Engineer | Java • Spring Boot • Ka...

What You Need to Know About Lambdas - Jamie Allen (Typesafe)

  • 1. Jamie Allen | Typesafe What You Need to Know About Lambdas Wednesday, November 6, 13
  • 2. Who Am I? • Director of Consulting for • User of lambdas on the JVM for ~5 years @jamie_allen Wednesday, November 6, 13
  • 6. I Love Functional Programming! • Functional Programming is: • Immutability • Referential Transparency • Functions as first-class citizens Wednesday, November 6, 13
  • 7. We Want Declarative Code final List<Integer> numbers = Arrays.asList(1, 2, 3); final List<Integer> numbersPlusOne = Collections.emptyList(); for (Integer number : numbers) { final Integer numberPlusOne = number + 1; numbersPlusOne.add(numberPlusOne); } Wednesday, November 6, 13
  • 8. What is a Lambda? • A function literal • Not bound to a variable name, can only be used in the context of where it is defined • Merely one of many possible implementations you can use in Functional Programming Wednesday, November 6, 13
  • 9. Java 8 import java.util.List; import java.util.Arrays; import java.util.stream.Collectors; public class LambdaDemo { public static void main(String... args) { final List<Integer> numbers = Arrays.asList(1, 2, 3); } } Wednesday, November 6, 13 λ final List<Integer> numbersPlusOne = numbers.stream().map(number -> number + 1). collect(Collectors.toList());
  • 10. Nashorn Javascript #!/usr/bin/env jjs -scripting var result = []; var list = new java.util.ArrayList(); list.add(1); list.add(2); list.add(3); list.parallelStream(). map(function(e) e + 1). forEach(function(t) result.push(t)); Wednesday, November 6, 13 λ
  • 11. Scala λ object LambdaDemo extends App { val numbers = List(1, 2, 3) val numbersPlusOne = numbers.map(number => number + 1) } Wednesday, November 6, 13
  • 12. Clojure λ (ns LambdaDemo.core) (defn -main [& args] (println(map #(+ % 1) [1, 2, 3]))) Wednesday, November 6, 13
  • 13. JRuby require "java" array = [1, 2, 3] array.collect! do |n| n + 1 end Wednesday, November 6, 13 λ
  • 14. What is the Problem? Wednesday, November 6, 13
  • 16. Not Reusable • Lambdas are limited in scope to their call site • You cannot reuse the functionality elsewhere Wednesday, November 6, 13
  • 17. Not Testable in Isolation • How can you test code by itself when you have no identifier through which you can call it? • You can only test them by writing more tests for their enclosing method Wednesday, November 6, 13
  • 18. Maintainability • There is nothing inherently descriptive about a lambda • Developers have to read through the entire lambda to figure out what it is doing • The more complex the lambda is, the harder this is to do • Waste of valuable development time Wednesday, November 6, 13
  • 19. Example • In Scala, I sometimes see code like this:                val  next  =  x.map  {                    case  Success(k)  =>  {                        deriveValueAsynchronously(worker(initValue))(pec).map  {                            case  None  =>  {                                val  remainingWork  =  k(Input.EOF)                                success(remainingWork)                                None                            }                            case  Some(read)  =>  {                                val  nextWork  =  k(Input.El(read))                                Some(nextWork)                            }                        }(dec)                    }                    case  _  =>  {  success(it);  Future.successful(None)  }                }(dec) Wednesday, November 6, 13 }} }λ }λ } λ λ λ
  • 21. Lousy Stack Traces • Compilers have to come up with generic names for their representation of lambdas to run on the JVM, called “name mangling” • The stack trace output tells you very little about where the problem occurred Wednesday, November 6, 13
  • 22. Java 8 numbers.stream().map(number -> number / 0) Exception in thread "main" java.lang.ArithmeticException: / by zero at LambdaDemo.lambda$0(LambdaDemo.java:9) at LambdaDemo$$Lambda$1.apply(Unknown Source) at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193) at java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:948) at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:512) at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:502) at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708) at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:510) at LambdaDemo.main(LambdaDemo.java:9) wat Wednesday, November 6, 13
  • 23. Nashorn Javascript list.parallelStream(). map(function(e) e / 0) [1, 2, 3] Infinity,Infinity Wednesday, November 6, 13
  • 24. Nashorn Javascript list.parallelStream(). map(function(e) e / 0) [1, 2, 3] Infinity,Infinity Wednesday, November 6, 13
  • 25. Favorite Tweet Ever “JavaScript doesn't have a dark side, but it does have a dimly lit room full of angry clowns with rubber mallets.” - @odetocode, Jan 5, 2010 Wednesday, November 6, 13
  • 26. Scala val numbersPlusOne = numbers.map(number => number / 0) Exception in thread "main" java.lang.ArithmeticException: / by zero at org.jamieallen.effectiveakka.pattern.extra.LambdaTest$$anonfun$1.apply(LambdaPlayground.scala:23) at org.jamieallen.effectiveakka.pattern.extra.LambdaTest$$anonfun$1.apply(LambdaPlayground.scala:23) at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:244) at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:244) at scala.collection.immutable.Range.foreach(Range.scala:141) at scala.collection.TraversableLike$class.map(TraversableLike.scala:244) at scala.collection.AbstractTraversable.map(Traversable.scala:105) at org.jamieallen.effectiveakka.pattern.extra.LambdaTest$delayedInit$body.apply(LambdaPlayground.scala:23) at scala.Function0$class.apply$mcV$sp(Function0.scala:40) at scala.runtime.AbstractFunction0.apply$mcV$sp(AbstractFunction0.scala:12) at scala.App$$anonfun$main$1.apply(App.scala:71) at scala.App$$anonfun$main$1.apply(App.scala:71) at scala.collection.immutable.List.foreach(List.scala:318) at scala.collection.generic.TraversableForwarder$class.foreach(TraversableForwarder.scala:32) at scala.App$class.main(App.scala:71) at org.jamieallen.effectiveakka.pattern.extra.LambdaTest$.main(LambdaPlayground.scala:22) at org.jamieallen.effectiveakka.pattern.extra.LambdaTest.main(LambdaPlayground.scala) wat Wednesday, November 6, 13
  • 27. Clojure println(map #(/ % 0) [1, 2, 3]))) Exception in thread "main" (java.lang.ArithmeticException: Divide by zero at clojure.lang.Numbers.divide(Numbers.java:156) at clojure.lang.Numbers.divide(Numbers.java:3671) at helloclj.core$_main$fn__10.invoke(core.clj:5) at clojure.core$map$fn__4087.invoke(core.clj:2432) at clojure.lang.LazySeq.sval(LazySeq.java:42) at clojure.lang.LazySeq.seq(LazySeq.java:60) at clojure.lang.RT.seq(RT.java:473) at clojure.core$seq.invoke(core.clj:133) at clojure.core$print_sequential.invoke(core_print.clj:46) at clojure.core$fn__5270.invoke(core_print.clj:140) at clojure.lang.MultiFn.invoke(MultiFn.java:167) at clojure.core$pr_on.invoke(core.clj:3266) at clojure.core$pr.invoke(core.clj:3278) at clojure.lang.AFn.applyToHelper(AFn.java:161) at clojure.lang.RestFn.applyTo(RestFn.java:132) at clojure.core$apply.invoke(core.clj:601) at clojure.core$prn.doInvoke(core.clj:3311) at clojure.lang.RestFn.applyTo(RestFn.java:137) at clojure.core$apply.invoke(core.clj:601) at clojure.core$println.doInvoke(core.clj:3331) at clojure.lang.RestFn.invoke(RestFn.java:408) at helloclj.core$_main.invoke(core.clj:5) at clojure.lang.Var.invoke(Var.java:411) ... at clojure.main.main(main.java:37) wat Wednesday, November 6, 13
  • 28. JRuby array.collect! do |n| n / 0 ZeroDivisionError: divided by 0 / at org/jruby/RubyFixnum.java:547 (root) at HelloWorld.rb:11 collect! at org/jruby/RubyArray.java:2385 (root) at HelloWorld.rb:10 not half bad, really Wednesday, November 6, 13
  • 29. Difficult Debugging • Debuggers on the JVM can only disambiguate code at the source line write your lambdas to leverage this final List<Integer> numbersPlusOne = numbers.stream(). map(number -> number + 1).collect(Collectors.toList()); NO! Wednesday, November 6, 13
  • 30. Digression: Lambdas versus Closures • In the purest sense, closures are merely lambdas that close over some state from outside of their enclosing scope final int x = 1; final List<Integer> numbersPlusOne = numbers.stream().map(number -> number + x). collect(Collectors.toList()); Wednesday, November 6, 13
  • 31. Closing Over State • Lambdas have access to all variables that are in scope • It is very easy to “close over” something mutable and cause headaches in multi-threaded code • Java enforces that values to be closed over are final, but that only affects assignment - you can still change what is INSIDE that variable (like the contents of a collection) Wednesday, November 6, 13
  • 32. Solution We want to maintain our ability to program in a functional style, while having something maintainable and understandable in production Wednesday, November 6, 13
  • 33. Named Functions? • Seems like it would help, but it depends on the compiler and how it manages the “scope” of that function • It is possible that stack traces will still not show the name of the function Wednesday, November 6, 13
  • 34. Named Function object LambdaTest extends App { val addOneToValue = (x: Int) => x + 1 } val myList = (1 to 20).map(addOneToValue) Wednesday, November 6, 13
  • 35. Named Function Stack Trace val badFunction = (x: Int) => x / 0 val myList = (1 to 20).map(badFunction) Exception in thread "main" java.lang.ArithmeticException: / by zero at org.jamieallen.effectiveakka.pattern.extra.LambdaTest$$anonfun$1.apply$mcII$sp(LambdaPlayground.scala:23) at org.jamieallen.effectiveakka.pattern.extra.LambdaTest$$anonfun$2.apply(LambdaPlayground.scala:24) at org.jamieallen.effectiveakka.pattern.extra.LambdaTest$$anonfun$2.apply(LambdaPlayground.scala:24) at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:244) at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:244) at scala.collection.immutable.Range.foreach(Range.scala:141) at scala.collection.TraversableLike$class.map(TraversableLike.scala:244) at scala.collection.AbstractTraversable.map(Traversable.scala:105) at org.jamieallen.effectiveakka.pattern.extra.LambdaTest$delayedInit$body.apply(LambdaPlayground.scala:24) at scala.Function0$class.apply$mcV$sp(Function0.scala:40) at scala.runtime.AbstractFunction0.apply$mcV$sp(AbstractFunction0.scala:12) at scala.App$$anonfun$main$1.apply(App.scala:71) at scala.App$$anonfun$main$1.apply(App.scala:71) at scala.collection.immutable.List.foreach(List.scala:318) at scala.collection.generic.TraversableForwarder$class.foreach(TraversableForwarder.scala:32) at scala.App$class.main(App.scala:71) at org.jamieallen.effectiveakka.pattern.extra.LambdaTest$.main(LambdaPlayground.scala:22) at org.jamieallen.effectiveakka.pattern.extra.LambdaTest.main(LambdaPlayground.scala) wat Wednesday, November 6, 13
  • 36. “Lifting” a Method • We have the ability in Java 8 and Scala to “lift” or coerce a method into a function • The method must meet the contract of the lambda usage of the compiler, such as only taking one argument representing the input of the function Wednesday, November 6, 13
  • 37. Stack Trace of a Method def badFunction = (x: Int) => x / 0 val myList = (1 to 20).map(badFunction) Exception in thread "main" java.lang.ArithmeticException: / by zero at org.jamieallen.effectiveakka.pattern.extra.LambdaTest$$anonfun$badFunction$1.apply$mcII$sp(LambdaPlayground.scala:23) at org.jamieallen.effectiveakka.pattern.extra.LambdaTest$$anonfun$1.apply(LambdaPlayground.scala:24) at org.jamieallen.effectiveakka.pattern.extra.LambdaTest$$anonfun$1.apply(LambdaPlayground.scala:24) at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:244) at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:244) at scala.collection.immutable.Range.foreach(Range.scala:141) at scala.collection.TraversableLike$class.map(TraversableLike.scala:244) at scala.collection.AbstractTraversable.map(Traversable.scala:105) at org.jamieallen.effectiveakka.pattern.extra.LambdaTest$delayedInit$body.apply(LambdaPlayground.scala:24) at scala.Function0$class.apply$mcV$sp(Function0.scala:40) at scala.runtime.AbstractFunction0.apply$mcV$sp(AbstractFunction0.scala:12) at scala.App$$anonfun$main$1.apply(App.scala:71) at scala.App$$anonfun$main$1.apply(App.scala:71) at scala.collection.immutable.List.foreach(List.scala:318) at scala.collection.generic.TraversableForwarder$class.foreach(TraversableForwarder.scala:32) at scala.App$class.main(App.scala:71) at org.jamieallen.effectiveakka.pattern.extra.LambdaTest$.main(LambdaPlayground.scala:22) at org.jamieallen.effectiveakka.pattern.extra.LambdaTest.main(LambdaPlayground.scala) Better, but why $1 Wednesday, November 6, 13
  • 38. Digression • You can define your methods like that, but “def” is not stable - it will reevaluate the right side of the equals sign and return a new but identical function each time! def badFunction = (x: Int) => x / 0 • Better to stick with simple method syntax instead def badFunction(x: Int) = x / 0 Wednesday, November 6, 13
  • 39. Stack Trace of a Stable Method def badFunction(x: Int) = x / 0 val myList = (1 to 20).map(badFunction) Exception in thread "main" java.lang.ArithmeticException: / by zero at org.jamieallen.effectiveakka.pattern.extra.LambdaTest$.badFunction(LambdaPlayground.scala:24) at org.jamieallen.effectiveakka.pattern.extra.LambdaTest$$anonfun$1.apply(LambdaPlayground.scala:25) at org.jamieallen.effectiveakka.pattern.extra.LambdaTest$$anonfun$1.apply(LambdaPlayground.scala:25) at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:244) at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:244) at scala.collection.immutable.Range.foreach(Range.scala:141) at scala.collection.TraversableLike$class.map(TraversableLike.scala:244) at scala.collection.AbstractTraversable.map(Traversable.scala:105) at org.jamieallen.effectiveakka.pattern.extra.LambdaTest$delayedInit$body.apply(LambdaPlayground.scala:25) at scala.Function0$class.apply$mcV$sp(Function0.scala:40) at scala.runtime.AbstractFunction0.apply$mcV$sp(AbstractFunction0.scala:12) at scala.App$$anonfun$main$1.apply(App.scala:71) at scala.App$$anonfun$main$1.apply(App.scala:71) at scala.collection.immutable.List.foreach(List.scala:318) at scala.collection.generic.TraversableForwarder$class.foreach(TraversableForwarder.scala:32) at scala.App$class.main(App.scala:71) at org.jamieallen.effectiveakka.pattern.extra.LambdaTest$.main(LambdaPlayground.scala:22) at org.jamieallen.effectiveakka.pattern.extra.LambdaTest.main(LambdaPlayground.scala) Perfect! Wednesday, November 6, 13
  • 40. Benefits • You can’t close over variables • Better stack traces • More debuggable • More testable • More maintainable and descriptive • Reusable Wednesday, November 6, 13
  • 41. Rule of Thumb • Reserve lambda usage for the most basic expressions • Externalize anything more significant than that to methods Wednesday, November 6, 13
  • 42. Language Creators • Language designers and tool producers need to help us • At Typesafe, we’re making our Eclipse-based Scala IDE more lambda-friendly with each release Wednesday, November 6, 13