SlideShare une entreprise Scribd logo
1  sur  49
Télécharger pour lire hors ligne
@knight_cloud
What You Need to
Know About Lambdas
Ryan Knight
Senior Consultant | Typesafe
Acknowledgement
• Material originally created by Jamie Allen	

• @jamie_allen
• Modified by Ryan Knight	

• @knight_cloud
I Love Functional Programming!
• Functional Programming is:	

• Immutability	

• Referential Transparency	

• Functions as first-class citizens	

• Eliminating side effects
Why Functional Programming?
• Foundation for Reactive Programming	

• Requires Callbacks to handle Events and
Async Results	

• Avoid Inner Classes	

• Higher-Level of Abstraction	

• Define the What not the How
Imperative 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);
}
We Want Declarative Code
• Remove temporary lists - List<Integer>
numbersPlusOne = Collections.emptyList();	

• Remove looping - for (Integer number : numbers)	

• Focus on what - x+1
What is a Lambda?
• A function literal - fixed value in the code.	

• 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
Java 8 Lambdas
• Functional Interface that defines a Single
Abstract Method	

• Target Type of the Lambda is the Functional
Interface 	

• java.util.function - Package with standard
Functional Interfaces
Java 8 Function Example
@FunctionalInterface
public interface Function<T, R> {
!
/**
* Applies this function to the given argument.
*
* @param t the function argument
* @return the function result
*/
R apply(T t);
Target Type of Lambda
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);
!
final List<Integer> numbersPlusOne =
numbers.stream().map(number -> number + 1).
collect(Collectors.toList());
}
}
λ
Scala
• Have a Function Type used to represent the
Lambda	

• map(f:Integer => Integer)	

• Creates a Function underneath the covers
Scala
object LambdaDemo extends App {
val numbers = List(1, 2, 3)
val numbersPlusOne =
numbers.map(number => number + 1)
}
λ
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));
λ
Clojure
(ns LambdaDemo.core)
(defn -main [& args]
(println(map #(+ % 1) [1, 2, 3])))
λ
JRuby
require "java"
!
array = [1, 2, 3]
array.collect! do |n|
n + 1
end
λ
What is the Problem?
There Are Caveats
Not Reusable
• Lambdas are limited in scope to their call
site	

• You cannot reuse the functionality
elsewhere
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
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
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)	
  
}
} }}}
λλ
λ
λ
λ
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
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
Nashorn Javascript
list.parallelStream().
map(function(e) e / 0)
!
[1, 2, 3]
Infinity,Infinity
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
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
Clojureprintln(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
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
Difficult Debugging
• Debuggers on the JVM are getting better -
still hard to debug Lambdas
final List<Integer> numbersPlusOne = numbers.stream().
map(number -> number + 1).collect(Collectors.toList());
NO!
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());
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)
Solution
We want to maintain our ability to program
in a functional style, while having something
maintainable and understandable in
production
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
Named Function
final Function<Integer, Integer> addOneToValue
= number -> number / 0;
!
final List<Integer> numbersPlusOne =
numbers.stream()
.map(addOneToValue)
.collect(Collectors.toList());
Named Function Stack Trace
final Function<Integer, Integer> addOneToValue
= number -> number / 0;
!
final List<Integer> numbersPlusOne =
numbers.stream().map(addOneToValue)
.collect(Collectors.toList());
!
!
Exception in thread "main" java.lang.ArithmeticException: / by zero	
	 at demoFuncs.BadExamples.lambda$main$0(BadExamples.java:15)	
	 at demoFuncs.BadExamples$$Lambda$1/1044036744.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:499)	
	 at demoFuncs.BadExamples.main(BadExamples.java:20)
wat
“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
Stack Trace of a Method	

Java 8
public static Integer addOneToValue(Integer number) {
return number / 0;
}
!
final List<Integer> numbersPlusOne =
numbers.stream()
.map(BadExamples::addOneToValue)
.collect(Collectors.toList());
!
Exception in thread "main" java.lang.ArithmeticException: / by zero	
	 at demoFuncs.BadExamples.addOneToValue(BadExamples.java:12)	
	 at demoFuncs.BadExamples$$Lambda$1/1826771953.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:499)	
	 at demoFuncs.BadExamples.main(BadExamples.java:23)
Much
Better!
Stack Trace of a Method	

Scala
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
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
def badFunction(x: Int) = x / 0
• Better to stick with simple method syntax instead
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!
Benefits
• You can’t close over variables	

• Better stack traces	

• More debuggable	

• More testable	

• More maintainable and descriptive	

• Reusable
Rule of Thumb
• Reserve lambda usage for the most basic
expressions	

• Externalize anything more significant than
that to methods
Java 8 Futures
final CompletableFuture<Object> cacheFuture = CompletableFuture
.supplyAsync(() -> {
return cacheRetriever.getCustomer(id);
});
!
cacheFuture.thenApply(customer -> dbService.getOrders(customer))
• java.util.concurrent.CompletableFuture	

• Future operation specified as a Function 	

• Callback specified as Function when the Future
completes
Java 8 vs. Scala
• Scala Functions are a first-class citizens	

• Scala compiler can infer type of Function	

• Java 8 Lambdas mapped to Functional
Interfaces	

• Weaker Type Inference - Can only infer
type based on left hand side of assignment
operator
Java 8 vs. Scala
• Scala still targeting Java 1.6	

• Creates synthetic class to represent Lambda	

• Java 8 Lambdas leverage invoke dynamic	

• Avoids creating synthetic classes	

• http://www.takipiblog.com/2014/01/16/compiling-lambda-
expressions-scala-vs-java-8/
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 - Smart stepping into Lambdas 	

• IntelliJ - Smart Step Into
ThankYou!
• Questions?

Contenu connexe

Tendances

Intro to Functional Programming in Scala
Intro to Functional Programming in ScalaIntro to Functional Programming in Scala
Intro to Functional Programming in ScalaShai Yallin
 
Learning Functional Programming Without Growing a Neckbeard
Learning Functional Programming Without Growing a NeckbeardLearning Functional Programming Without Growing a Neckbeard
Learning Functional Programming Without Growing a NeckbeardKelsey Gilmore-Innis
 
Java 8 lambda expressions
Java 8 lambda expressionsJava 8 lambda expressions
Java 8 lambda expressionsLogan Chien
 
RESTful API using scalaz (3)
RESTful API using scalaz (3)RESTful API using scalaz (3)
RESTful API using scalaz (3)Yeshwanth Kumar
 
"How was it to switch from beautiful Perl to horrible JavaScript", Viktor Tur...
"How was it to switch from beautiful Perl to horrible JavaScript", Viktor Tur..."How was it to switch from beautiful Perl to horrible JavaScript", Viktor Tur...
"How was it to switch from beautiful Perl to horrible JavaScript", Viktor Tur...Fwdays
 
Demystifying functional programming with Scala
Demystifying functional programming with ScalaDemystifying functional programming with Scala
Demystifying functional programming with ScalaDenis
 
Category theory, Monads, and Duality in the world of (BIG) Data
Category theory, Monads, and Duality in the world of (BIG) DataCategory theory, Monads, and Duality in the world of (BIG) Data
Category theory, Monads, and Duality in the world of (BIG) Datagreenwop
 
Ajax and JavaScript Bootcamp
Ajax and JavaScript BootcampAjax and JavaScript Bootcamp
Ajax and JavaScript BootcampAndreCharland
 
JavaScript - Chapter 6 - Basic Functions
 JavaScript - Chapter 6 - Basic Functions JavaScript - Chapter 6 - Basic Functions
JavaScript - Chapter 6 - Basic FunctionsWebStackAcademy
 
Metaprogramming in Scala 2.10, Eugene Burmako,
Metaprogramming  in Scala 2.10, Eugene Burmako, Metaprogramming  in Scala 2.10, Eugene Burmako,
Metaprogramming in Scala 2.10, Eugene Burmako, Vasil Remeniuk
 
Functional programming in Scala
Functional programming in ScalaFunctional programming in Scala
Functional programming in ScalaDamian Jureczko
 
Swift internals
Swift internalsSwift internals
Swift internalsJung Kim
 
Introduction to Functional Programming in JavaScript
Introduction to Functional Programming in JavaScriptIntroduction to Functional Programming in JavaScript
Introduction to Functional Programming in JavaScripttmont
 

Tendances (20)

Intro to Functional Programming in Scala
Intro to Functional Programming in ScalaIntro to Functional Programming in Scala
Intro to Functional Programming in Scala
 
Learning Functional Programming Without Growing a Neckbeard
Learning Functional Programming Without Growing a NeckbeardLearning Functional Programming Without Growing a Neckbeard
Learning Functional Programming Without Growing a Neckbeard
 
Java 8 lambda expressions
Java 8 lambda expressionsJava 8 lambda expressions
Java 8 lambda expressions
 
RESTful API using scalaz (3)
RESTful API using scalaz (3)RESTful API using scalaz (3)
RESTful API using scalaz (3)
 
Introduction to java 8 stream api
Introduction to java 8 stream apiIntroduction to java 8 stream api
Introduction to java 8 stream api
 
"How was it to switch from beautiful Perl to horrible JavaScript", Viktor Tur...
"How was it to switch from beautiful Perl to horrible JavaScript", Viktor Tur..."How was it to switch from beautiful Perl to horrible JavaScript", Viktor Tur...
"How was it to switch from beautiful Perl to horrible JavaScript", Viktor Tur...
 
Java 8: the good parts!
Java 8: the good parts!Java 8: the good parts!
Java 8: the good parts!
 
Demystifying functional programming with Scala
Demystifying functional programming with ScalaDemystifying functional programming with Scala
Demystifying functional programming with Scala
 
Category theory, Monads, and Duality in the world of (BIG) Data
Category theory, Monads, and Duality in the world of (BIG) DataCategory theory, Monads, and Duality in the world of (BIG) Data
Category theory, Monads, and Duality in the world of (BIG) Data
 
Beyond java8
Beyond java8Beyond java8
Beyond java8
 
Ajax and JavaScript Bootcamp
Ajax and JavaScript BootcampAjax and JavaScript Bootcamp
Ajax and JavaScript Bootcamp
 
JavaScript - Chapter 6 - Basic Functions
 JavaScript - Chapter 6 - Basic Functions JavaScript - Chapter 6 - Basic Functions
JavaScript - Chapter 6 - Basic Functions
 
Scala fundamentals
Scala fundamentalsScala fundamentals
Scala fundamentals
 
Java Generics - by Example
Java Generics - by ExampleJava Generics - by Example
Java Generics - by Example
 
Java gets a closure
Java gets a closureJava gets a closure
Java gets a closure
 
Metaprogramming in Scala 2.10, Eugene Burmako,
Metaprogramming  in Scala 2.10, Eugene Burmako, Metaprogramming  in Scala 2.10, Eugene Burmako,
Metaprogramming in Scala 2.10, Eugene Burmako,
 
Functional programming in Scala
Functional programming in ScalaFunctional programming in Scala
Functional programming in Scala
 
Swift internals
Swift internalsSwift internals
Swift internals
 
Introduction to Functional Programming in JavaScript
Introduction to Functional Programming in JavaScriptIntroduction to Functional Programming in JavaScript
Introduction to Functional Programming in JavaScript
 
Scala vs Ruby
Scala vs RubyScala vs Ruby
Scala vs Ruby
 

En vedette

Presentajon e twinning 2011
Presentajon e twinning 2011Presentajon e twinning 2011
Presentajon e twinning 2011Eva Rekkedal
 
Animoto For Teachers
Animoto For TeachersAnimoto For Teachers
Animoto For Teacherslezlieharris
 
Cuemlenin Oe Eleri
Cuemlenin Oe EleriCuemlenin Oe Eleri
Cuemlenin Oe Eleriyardimt
 
(Chris tringham) empire life presentation
(Chris tringham) empire life presentation(Chris tringham) empire life presentation
(Chris tringham) empire life presentationctringham
 
Norwegian answers to town mystery
Norwegian answers to town mysteryNorwegian answers to town mystery
Norwegian answers to town mysteryEva Rekkedal
 
Dilbilgisi
DilbilgisiDilbilgisi
Dilbilgisiyardimt
 
Norwegian mystery no 7
Norwegian mystery no 7Norwegian mystery no 7
Norwegian mystery no 7Eva Rekkedal
 
What is sustainable enterprise and why do we need it?
What is sustainable enterprise and why do we need it?What is sustainable enterprise and why do we need it?
What is sustainable enterprise and why do we need it?Jeremy Williams
 
Merita Citit a evoluat in favoarea ta
Merita Citit a evoluat in favoarea taMerita Citit a evoluat in favoarea ta
Merita Citit a evoluat in favoarea taCarla Alman
 
Solution of the French mystery
Solution of the French mysterySolution of the French mystery
Solution of the French mysteryEva Rekkedal
 
powerpoint skills !
powerpoint skills !powerpoint skills !
powerpoint skills !jgirdner02
 
Are you a life-long learner?
Are you a life-long learner?Are you a life-long learner?
Are you a life-long learner?Jeremy Williams
 
16 paragrafın anlatım yönü-anlatım özellikleri
16 paragrafın anlatım yönü-anlatım özellikleri16 paragrafın anlatım yönü-anlatım özellikleri
16 paragrafın anlatım yönü-anlatım özellikleriyardimt
 
Geo-Enabling DoD Business Transformation: The Defense Installation Spatial Da...
Geo-Enabling DoD Business Transformation: The Defense Installation Spatial Da...Geo-Enabling DoD Business Transformation: The Defense Installation Spatial Da...
Geo-Enabling DoD Business Transformation: The Defense Installation Spatial Da...California Wildlife Conservation Board
 

En vedette (20)

Presentajon e twinning 2011
Presentajon e twinning 2011Presentajon e twinning 2011
Presentajon e twinning 2011
 
Hot Chocolate
Hot ChocolateHot Chocolate
Hot Chocolate
 
Animoto For Teachers
Animoto For TeachersAnimoto For Teachers
Animoto For Teachers
 
Cuemlenin Oe Eleri
Cuemlenin Oe EleriCuemlenin Oe Eleri
Cuemlenin Oe Eleri
 
(Chris tringham) empire life presentation
(Chris tringham) empire life presentation(Chris tringham) empire life presentation
(Chris tringham) empire life presentation
 
Mystery 2: Town
Mystery 2: Town Mystery 2: Town
Mystery 2: Town
 
Norwegian answers to town mystery
Norwegian answers to town mysteryNorwegian answers to town mystery
Norwegian answers to town mystery
 
Dilbilgisi
DilbilgisiDilbilgisi
Dilbilgisi
 
Norwegian mystery no 7
Norwegian mystery no 7Norwegian mystery no 7
Norwegian mystery no 7
 
Rw Newsletter24
Rw Newsletter24Rw Newsletter24
Rw Newsletter24
 
What is sustainable enterprise and why do we need it?
What is sustainable enterprise and why do we need it?What is sustainable enterprise and why do we need it?
What is sustainable enterprise and why do we need it?
 
Merita Citit a evoluat in favoarea ta
Merita Citit a evoluat in favoarea taMerita Citit a evoluat in favoarea ta
Merita Citit a evoluat in favoarea ta
 
Solution of the French mystery
Solution of the French mysterySolution of the French mystery
Solution of the French mystery
 
powerpoint skills !
powerpoint skills !powerpoint skills !
powerpoint skills !
 
Thurrockv9
Thurrockv9Thurrockv9
Thurrockv9
 
Haiku
HaikuHaiku
Haiku
 
Are you a life-long learner?
Are you a life-long learner?Are you a life-long learner?
Are you a life-long learner?
 
16 paragrafın anlatım yönü-anlatım özellikleri
16 paragrafın anlatım yönü-anlatım özellikleri16 paragrafın anlatım yönü-anlatım özellikleri
16 paragrafın anlatım yönü-anlatım özellikleri
 
Geo-Enabling DoD Business Transformation: The Defense Installation Spatial Da...
Geo-Enabling DoD Business Transformation: The Defense Installation Spatial Da...Geo-Enabling DoD Business Transformation: The Defense Installation Spatial Da...
Geo-Enabling DoD Business Transformation: The Defense Installation Spatial Da...
 
Isimler
IsimlerIsimler
Isimler
 

Similaire à What You Need to Know about Lambdas

20160520 what youneedtoknowaboutlambdas
20160520 what youneedtoknowaboutlambdas20160520 what youneedtoknowaboutlambdas
20160520 what youneedtoknowaboutlambdasshinolajla
 
What you need to know about Lambdas - Jamie Allen
What you need to know about Lambdas - Jamie AllenWhat you need to know about Lambdas - Jamie Allen
What you need to know about Lambdas - Jamie Allenjaxconf
 
What You Need to Know About Lambdas - Jamie Allen (Typesafe)
What You Need to Know About Lambdas - Jamie Allen (Typesafe)What You Need to Know About Lambdas - Jamie Allen (Typesafe)
What You Need to Know About Lambdas - Jamie Allen (Typesafe)jaxLondonConference
 
Taxonomy of Scala
Taxonomy of ScalaTaxonomy of Scala
Taxonomy of Scalashinolajla
 
Modern Programming in Java 8 - Lambdas, Streams and Date Time API
Modern Programming in Java 8 - Lambdas, Streams and Date Time APIModern Programming in Java 8 - Lambdas, Streams and Date Time API
Modern Programming in Java 8 - Lambdas, Streams and Date Time APIGanesh Samarthyam
 
Effective Scala (JavaDay Riga 2013)
Effective Scala (JavaDay Riga 2013)Effective Scala (JavaDay Riga 2013)
Effective Scala (JavaDay Riga 2013)mircodotta
 
Scala for Java Programmers
Scala for Java ProgrammersScala for Java Programmers
Scala for Java ProgrammersEric Pederson
 
Scala @ TechMeetup Edinburgh
Scala @ TechMeetup EdinburghScala @ TechMeetup Edinburgh
Scala @ TechMeetup EdinburghStuart Roebuck
 
BASE Meetup: "Analysing Scala Puzzlers: Essential and Accidental Complexity i...
BASE Meetup: "Analysing Scala Puzzlers: Essential and Accidental Complexity i...BASE Meetup: "Analysing Scala Puzzlers: Essential and Accidental Complexity i...
BASE Meetup: "Analysing Scala Puzzlers: Essential and Accidental Complexity i...Andrew Phillips
 
Scala Up North: "Analysing Scala Puzzlers: Essential and Accidental Complexit...
Scala Up North: "Analysing Scala Puzzlers: Essential and Accidental Complexit...Scala Up North: "Analysing Scala Puzzlers: Essential and Accidental Complexit...
Scala Up North: "Analysing Scala Puzzlers: Essential and Accidental Complexit...Andrew Phillips
 
Real Time Big Data Management
Real Time Big Data ManagementReal Time Big Data Management
Real Time Big Data ManagementAlbert Bifet
 
Scala clojure techday_2011
Scala clojure techday_2011Scala clojure techday_2011
Scala clojure techday_2011Thadeu Russo
 
Scala Talk at FOSDEM 2009
Scala Talk at FOSDEM 2009Scala Talk at FOSDEM 2009
Scala Talk at FOSDEM 2009Martin Odersky
 
Static or Dynamic Typing? Why not both?
Static or Dynamic Typing? Why not both?Static or Dynamic Typing? Why not both?
Static or Dynamic Typing? Why not both?Mario Camou Riveroll
 
whats new in java 8
whats new in java 8 whats new in java 8
whats new in java 8 Dori Waldman
 
Functional Programming With Scala
Functional Programming With ScalaFunctional Programming With Scala
Functional Programming With ScalaKnoldus Inc.
 

Similaire à What You Need to Know about Lambdas (20)

20160520 what youneedtoknowaboutlambdas
20160520 what youneedtoknowaboutlambdas20160520 what youneedtoknowaboutlambdas
20160520 what youneedtoknowaboutlambdas
 
What you need to know about Lambdas - Jamie Allen
What you need to know about Lambdas - Jamie AllenWhat you need to know about Lambdas - Jamie Allen
What you need to know about Lambdas - Jamie Allen
 
What You Need to Know About Lambdas - Jamie Allen (Typesafe)
What You Need to Know About Lambdas - Jamie Allen (Typesafe)What You Need to Know About Lambdas - Jamie Allen (Typesafe)
What You Need to Know About Lambdas - Jamie Allen (Typesafe)
 
Taxonomy of Scala
Taxonomy of ScalaTaxonomy of Scala
Taxonomy of Scala
 
Modern Programming in Java 8 - Lambdas, Streams and Date Time API
Modern Programming in Java 8 - Lambdas, Streams and Date Time APIModern Programming in Java 8 - Lambdas, Streams and Date Time API
Modern Programming in Java 8 - Lambdas, Streams and Date Time API
 
Effective Scala (JavaDay Riga 2013)
Effective Scala (JavaDay Riga 2013)Effective Scala (JavaDay Riga 2013)
Effective Scala (JavaDay Riga 2013)
 
Scala for Java Programmers
Scala for Java ProgrammersScala for Java Programmers
Scala for Java Programmers
 
Scala @ TechMeetup Edinburgh
Scala @ TechMeetup EdinburghScala @ TechMeetup Edinburgh
Scala @ TechMeetup Edinburgh
 
BASE Meetup: "Analysing Scala Puzzlers: Essential and Accidental Complexity i...
BASE Meetup: "Analysing Scala Puzzlers: Essential and Accidental Complexity i...BASE Meetup: "Analysing Scala Puzzlers: Essential and Accidental Complexity i...
BASE Meetup: "Analysing Scala Puzzlers: Essential and Accidental Complexity i...
 
Scala Up North: "Analysing Scala Puzzlers: Essential and Accidental Complexit...
Scala Up North: "Analysing Scala Puzzlers: Essential and Accidental Complexit...Scala Up North: "Analysing Scala Puzzlers: Essential and Accidental Complexit...
Scala Up North: "Analysing Scala Puzzlers: Essential and Accidental Complexit...
 
Real Time Big Data Management
Real Time Big Data ManagementReal Time Big Data Management
Real Time Big Data Management
 
Scala ntnu
Scala ntnuScala ntnu
Scala ntnu
 
Scala clojure techday_2011
Scala clojure techday_2011Scala clojure techday_2011
Scala clojure techday_2011
 
Pune Clojure Course Outline
Pune Clojure Course OutlinePune Clojure Course Outline
Pune Clojure Course Outline
 
Scala Talk at FOSDEM 2009
Scala Talk at FOSDEM 2009Scala Talk at FOSDEM 2009
Scala Talk at FOSDEM 2009
 
Static or Dynamic Typing? Why not both?
Static or Dynamic Typing? Why not both?Static or Dynamic Typing? Why not both?
Static or Dynamic Typing? Why not both?
 
Java 8
Java 8Java 8
Java 8
 
whats new in java 8
whats new in java 8 whats new in java 8
whats new in java 8
 
[Start] Scala
[Start] Scala[Start] Scala
[Start] Scala
 
Functional Programming With Scala
Functional Programming With ScalaFunctional Programming With Scala
Functional Programming With Scala
 

Dernier

"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii SoldatenkoFwdays
 
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationBeyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationSafe Software
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Patryk Bandurski
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebUiPathCommunity
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Mattias Andersson
 
Commit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyCommit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyAlfredo García Lavilla
 
Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Manik S Magar
 
Story boards and shot lists for my a level piece
Story boards and shot lists for my a level pieceStory boards and shot lists for my a level piece
Story boards and shot lists for my a level piececharlottematthew16
 
Install Stable Diffusion in windows machine
Install Stable Diffusion in windows machineInstall Stable Diffusion in windows machine
Install Stable Diffusion in windows machinePadma Pradeep
 
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticscarlostorres15106
 
Training state-of-the-art general text embedding
Training state-of-the-art general text embeddingTraining state-of-the-art general text embedding
Training state-of-the-art general text embeddingZilliz
 
CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):comworks
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Mark Simos
 
Search Engine Optimization SEO PDF for 2024.pdf
Search Engine Optimization SEO PDF for 2024.pdfSearch Engine Optimization SEO PDF for 2024.pdf
Search Engine Optimization SEO PDF for 2024.pdfRankYa
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024Stephanie Beckett
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfAlex Barbosa Coqueiro
 
Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 3652toLead Limited
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsSergiu Bodiu
 
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)Wonjun Hwang
 

Dernier (20)

"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko
 
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationBeyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio Web
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?
 
Commit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyCommit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easy
 
Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!
 
Story boards and shot lists for my a level piece
Story boards and shot lists for my a level pieceStory boards and shot lists for my a level piece
Story boards and shot lists for my a level piece
 
Install Stable Diffusion in windows machine
Install Stable Diffusion in windows machineInstall Stable Diffusion in windows machine
Install Stable Diffusion in windows machine
 
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
 
Training state-of-the-art general text embedding
Training state-of-the-art general text embeddingTraining state-of-the-art general text embedding
Training state-of-the-art general text embedding
 
CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):
 
DMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special EditionDMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special Edition
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
 
Search Engine Optimization SEO PDF for 2024.pdf
Search Engine Optimization SEO PDF for 2024.pdfSearch Engine Optimization SEO PDF for 2024.pdf
Search Engine Optimization SEO PDF for 2024.pdf
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdf
 
Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platforms
 
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
 

What You Need to Know about Lambdas

  • 1. @knight_cloud What You Need to Know About Lambdas Ryan Knight Senior Consultant | Typesafe
  • 2. Acknowledgement • Material originally created by Jamie Allen • @jamie_allen • Modified by Ryan Knight • @knight_cloud
  • 3.
  • 4. I Love Functional Programming! • Functional Programming is: • Immutability • Referential Transparency • Functions as first-class citizens • Eliminating side effects
  • 5. Why Functional Programming? • Foundation for Reactive Programming • Requires Callbacks to handle Events and Async Results • Avoid Inner Classes • Higher-Level of Abstraction • Define the What not the How
  • 6. Imperative 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); }
  • 7. We Want Declarative Code • Remove temporary lists - List<Integer> numbersPlusOne = Collections.emptyList(); • Remove looping - for (Integer number : numbers) • Focus on what - x+1
  • 8. What is a Lambda? • A function literal - fixed value in the code. • 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
  • 9. Java 8 Lambdas • Functional Interface that defines a Single Abstract Method • Target Type of the Lambda is the Functional Interface • java.util.function - Package with standard Functional Interfaces
  • 10. Java 8 Function Example @FunctionalInterface public interface Function<T, R> { ! /** * Applies this function to the given argument. * * @param t the function argument * @return the function result */ R apply(T t); Target Type of Lambda
  • 11. 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); ! final List<Integer> numbersPlusOne = numbers.stream().map(number -> number + 1). collect(Collectors.toList()); } } λ
  • 12. Scala • Have a Function Type used to represent the Lambda • map(f:Integer => Integer) • Creates a Function underneath the covers
  • 13. Scala object LambdaDemo extends App { val numbers = List(1, 2, 3) val numbersPlusOne = numbers.map(number => number + 1) } λ
  • 14. 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)); λ
  • 15. Clojure (ns LambdaDemo.core) (defn -main [& args] (println(map #(+ % 1) [1, 2, 3]))) λ
  • 16. JRuby require "java" ! array = [1, 2, 3] array.collect! do |n| n + 1 end λ
  • 17. What is the Problem?
  • 19. Not Reusable • Lambdas are limited in scope to their call site • You cannot reuse the functionality elsewhere
  • 20. 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
  • 21. 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
  • 22. 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)   } } }}} λλ λ λ λ
  • 23.
  • 24. 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
  • 25. 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
  • 27. 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
  • 28. 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
  • 29. Clojureprintln(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
  • 30. 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
  • 31. Difficult Debugging • Debuggers on the JVM are getting better - still hard to debug Lambdas final List<Integer> numbersPlusOne = numbers.stream(). map(number -> number + 1).collect(Collectors.toList()); NO!
  • 32. 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());
  • 33. 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)
  • 34. Solution We want to maintain our ability to program in a functional style, while having something maintainable and understandable in production
  • 35. 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
  • 36. Named Function final Function<Integer, Integer> addOneToValue = number -> number / 0; ! final List<Integer> numbersPlusOne = numbers.stream() .map(addOneToValue) .collect(Collectors.toList());
  • 37. Named Function Stack Trace final Function<Integer, Integer> addOneToValue = number -> number / 0; ! final List<Integer> numbersPlusOne = numbers.stream().map(addOneToValue) .collect(Collectors.toList()); ! ! Exception in thread "main" java.lang.ArithmeticException: / by zero at demoFuncs.BadExamples.lambda$main$0(BadExamples.java:15) at demoFuncs.BadExamples$$Lambda$1/1044036744.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:499) at demoFuncs.BadExamples.main(BadExamples.java:20) wat
  • 38. “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
  • 39. Stack Trace of a Method Java 8 public static Integer addOneToValue(Integer number) { return number / 0; } ! final List<Integer> numbersPlusOne = numbers.stream() .map(BadExamples::addOneToValue) .collect(Collectors.toList()); ! Exception in thread "main" java.lang.ArithmeticException: / by zero at demoFuncs.BadExamples.addOneToValue(BadExamples.java:12) at demoFuncs.BadExamples$$Lambda$1/1826771953.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:499) at demoFuncs.BadExamples.main(BadExamples.java:23) Much Better!
  • 40. Stack Trace of a Method Scala 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
  • 41. 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 def badFunction(x: Int) = x / 0 • Better to stick with simple method syntax instead
  • 42. 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!
  • 43. Benefits • You can’t close over variables • Better stack traces • More debuggable • More testable • More maintainable and descriptive • Reusable
  • 44. Rule of Thumb • Reserve lambda usage for the most basic expressions • Externalize anything more significant than that to methods
  • 45. Java 8 Futures final CompletableFuture<Object> cacheFuture = CompletableFuture .supplyAsync(() -> { return cacheRetriever.getCustomer(id); }); ! cacheFuture.thenApply(customer -> dbService.getOrders(customer)) • java.util.concurrent.CompletableFuture • Future operation specified as a Function • Callback specified as Function when the Future completes
  • 46. Java 8 vs. Scala • Scala Functions are a first-class citizens • Scala compiler can infer type of Function • Java 8 Lambdas mapped to Functional Interfaces • Weaker Type Inference - Can only infer type based on left hand side of assignment operator
  • 47. Java 8 vs. Scala • Scala still targeting Java 1.6 • Creates synthetic class to represent Lambda • Java 8 Lambdas leverage invoke dynamic • Avoids creating synthetic classes • http://www.takipiblog.com/2014/01/16/compiling-lambda- expressions-scala-vs-java-8/
  • 48. 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 - Smart stepping into Lambdas • IntelliJ - Smart Step Into