SlideShare une entreprise Scribd logo
1  sur  39
Programming Picaresque
In Which Our Hero Learns Some Valuable
Life Lessons And The Importance Of Pure
Functions
Bret McGuire
A Few Definitions
Object-oriented
Programming
● Model of programming based on entities
(“objects”) which combine state with
behaviour(s)
● Objects correspond to nouns in a system
● Objects interact by invoking methods (verbs) on
objects
● Methods with side effects are quite common
○ State updates
○ Interacting with OS resources
● Objects are often mutable
○ Although immutable objects are not prohibited
● Objects must safely manage concurrent access
to mutable state when multiple objects are at
play
Functional
Programming
● “Programming that emphasizes programming
with functions” [1]
● Side effects in functions should be avoided
○ Functions should compute and return a value
based on arguments
○ No statements; everything returns a value
● Values are immutable
● State is a value for a participant in the system
(an “identity”) at some point in time
● Seriously, just watch the video
○ Rich explains it much better than I do!
The Players
Haskell ● Purely functional
○ No side effects
■ That’s what we have monads for
● Lazy evaluation
○ Values aren’t computed until needed
● Static typing
● Paragon of functional programming
Scala ● In a bit of a weird spot here
● Scala is explicitly a multi-paradigm language
○ Intent is to support OOP, FP or both
● Over time a bias has emerged
○ Something like “a gentle nudge” towards:
■ Immutability
■ FP concepts
● Not by any means required
○ Don’t have to use scalaz to use Scala
○ Could happily write imperative code all day long
● Plenty of other benefits
○ Advanced type system
○ Type inference
○ Strong pattern matching
Java ● Adamantly object-oriented
○ Everything is an object
■ Well, except primitives…
● Statically typed
● Simpler type system than Scala
● Paragon of OO programming
○ For good and for bad
● An important distinction: “Java” can mean:
○ A programming language
○ The virtual machine it runs on
○ The community and practices surrounding them
● We mostly focus on the language here
○ Although community/practices will figure in
Lambdas
Scala: Functions As First-Class Entities
$ scala
...
scala> List("one", "two", "three").map {_.toUpperCase}
res0: List[String] = List(ONE, TWO, THREE)
scala> val foo = { v:String => v.toUpperCase}
foo: String => String = <function1>
scala> List("one", "two", "three").map(foo)
res1: List[String] = List(ONE, TWO, THREE)
scala> val bar = (prefix:String) => (arg:String) => prefix.concat(arg)
bar: String => (String => String) = <function1>
scala> val baz = bar("hi ")
baz: String => String = <function1>
scala> List("one", "two", "three").map(baz)
res2: List[String] = List(hi one, hi two, hi three)
Java: Me Too, Me Too!
import java.util.function.Function;
...
public class FunctionsTest {
private Function<String, String> bar(String prefix) { return v -> prefix + v; }
@Test
public void testFunctions() {
List<String> base = ImmutableList.of("one", "two", "three");
List<String> expected = ImmutableList.of("ONE", "TWO", "THREE");
assertEquals(expected,
base.stream().map(v -> v.toUpperCase())
.collect(ImmutableList.toImmutableList()));
Function<String, String> foo = v -> v.toUpperCase();
assertEquals(expected,
base.stream().map(foo)
.collect(ImmutableList.toImmutableList()));
Function<String, String> baz = bar("hi ");
assertEquals(ImmutableList.of("hi one", "hi two", "hi three"),
base.stream().map(baz).collect(ImmutableList.toImmutableList()));
}
}
Java: Let’s Try It With Guava!
@Test
public void voidTestFunctionsSomeMore() {
ImmutableList<String> base = ImmutableList.of("one", "two", "three");
List<String> expected = ImmutableList.of("ONE", "TWO", "THREE");
assertEquals(expected, FluentIterable.from(base).transform(v ->
v.toUpperCase()).toList());
Function<String, String> foo = v -> v.toUpperCase();
assertEquals(expected, FluentIterable.from(base).transform(foo).toList());
Function<String, String> baz = bar("hi ");
assertEquals(ImmutableList.of("hi one", "hi two", "hi three"),
FluentIterable.from(base).transform(baz).toList());
}
Java: And Now We Are Sad
$ ./gradlew test
> Task :compileTestJava FAILED
/home/mersault/git/working/src/test/java/com/datastax/FunctionsTest.java:50: error: method transform in class FluentIterable<E> cannot be applied to given types;
assertEquals(expected, FluentIterable.from(base).transform(foo).toList());
^
required: com.google.common.base.Function<? super String,T>
found: java.util.function.Function<String,String>
reason: cannot infer type-variable(s) T
(argument mismatch; java.util.function.Function<String,String> cannot be converted to com.google.common.base.Function<? super String,T>)
where T,E are type-variables:
T extends Object declared in method <T>transform(com.google.common.base.Function<? super E,T>)
E extends Object declared in class FluentIterable
/home/mersault/git/working/src/test/java/com/datastax/FunctionsTest.java:54: error: method transform in class FluentIterable<E> cannot be applied to given types;
FluentIterable.from(base).transform(baz).toList());
^
required: com.google.common.base.Function<? super String,T>
found: java.util.function.Function<String,String>
reason: cannot infer type-variable(s) T
(argument mismatch; java.util.function.Function<String,String> cannot be converted to com.google.common.base.Function<? super String,T>)
where T,E are type-variables:
T extends Object declared in method <T>transform(com.google.common.base.Function<? super E,T>)
E extends Object declared in class FluentIterable
2 errors
Where We Went
Wrong
● Lambdas are implemented as a compile-time
feature
○ Think “pre-processor” if that weren’t such a dirty
notion in some quarters
● If a lambda is used in a context where a
“functional interface” is expected the lambda
will be converted to the type of that “functional
interface”
○ Over time Java has created many types which
are in essence functions (listeners, event
handlers, etc.)
○ Changing all these types to inherit from a
common type would’ve been… painful
● Upshot: once this conversion happens the
lambda is just another instance of that type
○ When we assign the lambda to a variable or
return it from a function we do just that
This Is Very Definitely An Improvement
private static class Foo implements com.google.common.base.Function<String, String> {
public String apply(String arg) { return arg.toUpperCase(); }
}
private static com.google.common.base.Function<String, String> bar(String prefix) {
return new com.google.common.base.Function<String, String>() {
public String apply(String arg) { return prefix + arg; }
};
}
@Test
public void testOldSchoolGuava() {
List<String> base = ImmutableList.of("one", "two", "three");
List<String> expected = ImmutableList.of("ONE", "TWO", "THREE");
assertEquals(expected, Lists.transform(base, new Foo()));
com.google.common.base.Function<String, String> baz = bar("hi ");
assertEquals(ImmutableList.of("hi one", "hi two", "hi three"),
Lists.transform(base, baz));
}
Immutability
Haskell: Things Don’t Change
GHCi, version 8.6.3
Prelude> let foo = [1,2,3]
Prelude> let bar = [4,5,6]
Prelude> foo ++ bar
[1,2,3,4,5,6]
Prelude> foo
[1,2,3]
Prelude> let baz = foo ++ bar
Prelude> baz
[1,2,3,4,5,6]
Prelude> foo
[1,2,3]
Prelude> bar
[4,5,6]
Haskell: ADTs Don’t Change Either
GHCi, version 8.6.3
Prelude> data OneTwo = OneTwo { one :: Int, two :: String } deriving Show
Prelude> let foo = OneTwo { one = 1, two = "one" }
Prelude> let bar = foo { two = "oops" }
Prelude> foo
OneTwo {one = 1, two = "one"}
Prelude> bar
OneTwo {one = 1, two = "oops"}
Scala: This Looks Familiar...
Welcome to Scala 2.11.8 (OpenJDK 64-Bit Server VM, Java 1.8.0_181).
scala> val foo = List(1,2,3)
foo: List[Int] = List(1, 2, 3)
scala> val bar = List(4,5,6)
bar: List[Int] = List(4, 5, 6)
scala> foo ++ bar
res0: List[Int] = List(1, 2, 3, 4, 5, 6)
scala> foo
res1: List[Int] = List(1, 2, 3)
scala> val baz = foo ++ bar
baz: List[Int] = List(1, 2, 3, 4, 5, 6)
scala> baz
res2: List[Int] = List(1, 2, 3, 4, 5, 6)
scala> foo
res3: List[Int] = List(1, 2, 3)
scala> bar
res4: List[Int] = List(4, 5, 6)
Java: In The
Beginning
● Java has certainly not ignored the notion of
immutable data
○ Collections.unmodifiable* has been around
since… Java 1.2-ish
■ Return wrapped versions of collection
types which throw exceptions on
mutation methods
○ Value object
■ No language-level support
■ Several recipes/patterns for doing so
● “Effective Java” recipe
● JCIP discusses the idea
● Discussion centers on concrete benefits of
immutable objects
○ Thread safety
○ Ease of reasoning
○ No notion of the deeper way of thinking about
values, identity
Java: The Middle
Ages
● Collections: google-collections (later folded into
Guava) comes along and offers Immutable*,
truly immutable collection classes
● These implementations address two major
problems with Collections.unmodifiable*
○ The wrapped collections are unmodifiable, not
immutable
■ Changes to the wrapped (presumably
mutable) collection would appear in the
wrapper
○ Return types are general List, Map, Set interfaces
■ No indication to the type system that
these objects have different
characteristics
● Value objects: not much change
○ Still no language-level support
○ Developers largely left to roll their own
Java: It’s A Brave New World!
public class OneTwoTest {
@Value.Immutable
public interface OneTwo {
Integer one();
String two();
}
@Test
public void testOneTwo() {
OneTwo onetwo = ImmutableOneTwo.builder().one(1).two("one").build();
assertEquals(1, onetwo.one().intValue());
assertEquals("one",onetwo.two());
}
}
Monads
Warm Fuzzy Things [2]
Some Things About
Monads
● Remind me what they are again?
○ A wrapped value and…
○ A “unit” function
■ To put a value into a monad
○ A “bind” function
■ Given (M T) and a function T -> M T’ apply
the function to the value wrapped in the
moand to generate a new monad
An example: Option ● The Option monad contains a value with one of
two variant types:
○ None (has no value)
○ Some (contains some value)
● The “bind” operation will apply it’s fn to the
wrapped value if the monad val is Some
○ Otherwise return None
● These behaviours allow Option to serve as “a
simple kind of error monad”
○ If a set of operations on a monad are successful
you get a Some containing the result
○ If any step fails you get None
Haskell: All About Option
data Maybe a = Nothing | Just a
deriving ( Eq
, Ord
)
instance Monad Maybe where
(Just x) >>= k = k x
Nothing >>= _ = Nothing
(>>) = (*>)
fail _ = Nothing
The type declaration: Maybe is an ADT with two
distinct variant types
While we’re here let’s make it a monad as well
Haskell: Option In Practice
GHCi, version 8.6.3
Prelude> (Just 1) >>= t -> Just(t + 1)
Just 2
Prelude> Nothing >>= t -> Just(t + 1)
Nothing
Scala: This Looks Familiar (Reprise)...
$ more SillyOptions.scala
def doSillyThing(opt:Option[String]):Option[Int] = {
opt filter { !_.isEmpty } map { _.length } map { _ * 10 }
}
$ scala -i SillyOptions.scala
Loading SillyOptions.scala...
doSillyThing: (opt: Option[String])Option[Int]
Welcome to Scala 2.11.8 (OpenJDK 64-Bit Server VM, Java 1.8.0_181).
scala> doSillyThing(None)
res0: Option[Int] = None
scala> doSillyThing(Some(""))
res1: Option[Int] = None
scala> doSillyThing(Some("abc"))
res2: Option[Int] = Some(30)
scala> doSillyThing(Some("abcdef"))
res3: Option[Int] = Some(60)
Java: A Pair of
Optionals
● Java has two common implementations of the
option/maybe type
○ Guava’s com.google.common.base.Optional
■ First on the scene
■ Before this everybody rolled their own
○ java.util.Optional
■ Standard as of Java8
● Overwhelming use case here is to avoid
returning null
○ Goal: minimize NullPointerExceptions (NPEs)
● This is not a small thing
○ Since null references have cost us exactly one
billion dollars [3]
Java: The Good Side of Optional
public class OptionTest {
private Integer findFirstNegativeInt(Integer...integers) {
for (Integer integer : integers) {
if (integer < 0) { return integer; }
}
return null;
}
private Optional<Integer> findFirstNegativeIntOption(Integer...integers) {
for (Integer integer : integers) {
if (integer < 0) { return Optional.<Integer>of(integer); }
}
return Optional.empty();
}
@Test
public void testOption() {
assertNotNull(findFirstNegativeInt(1,2,3,-100,4));
assertNull(findFirstNegativeInt(1,2,3,4));
assertNotNull(findFirstNegativeIntOption(1,2,3,-100,4));
assertNotNull(findFirstNegativeIntOption(1,2,3,4));
}
Java: The Other Side of Optional
public class OtherOptionTest {
private Optional<String> thisIsSafeRight(List<Integer> integers, Integer thingIWant) {
Map<Integer,Optional<String>> options = new HashMap<Integer,Optional<String>>();
for (Integer integer : integers) {
options.put(integer, Optional.<String>of(integer.toString()));
}
return options.get(Collections.binarySearch(integers, thingIWant));
}
@Test
public void testOption() {
assertNotNull(thisIsSafeRight(ImmutableList.of(1,2,3,4), 1)); // oops, this didn't pass
assertNotNull(thisIsSafeRight(ImmutableList.of(1,2,3,4), 4));
assertNotNull(thisIsSafeRight(ImmutableList.of(10,20,30,40), 10)); // hmmm, this didn't pass either
}
}
Some Other Things
About Option and
Java...
● So… Java doesn’t use monads
○ In practice, no
○ But...
Java: It’s a Monad After All!
public class OptionMonadTest {
public Optional<Integer> doTheThing(Optional<String> in) {
return in.filter(v -> !v.isEmpty()).map(v -> v.length()).map(v -> v * 10);
}
@Test
public void testOptionAsMonad() {
assertFalse(doTheThing(Optional.empty()).isPresent());
assertFalse(doTheThing(Optional.of("")).isPresent());
assertEquals(30, doTheThing(Optional.of("abc")).orElse(-1).intValue());
assertEquals(60, doTheThing(Optional.of("abcdef")).orElse(-1).intValue());
}
}
Conclusions
Conclusion The
First: Adaptation
Not Adoption
● We’ve seen Java “adapt” ideas from FP into
something that works within Java
○ Immutable types rather than persistent data
structures
○ Option type rather than use as monad
● Even these adapted uses can be terribly
powerful
○ These ideas represent significant improvements
to the OOP process
Conclusion The
Second: Perhaps
This Can Only Go So
Far
● Is it possible that adoption of these ideas
(persistent data structures and/or monads) at a
deeper level is limited because they represent
ways of managing state?
● State management in an object-oriented system
is (for better or worse) a solved problem
Conclusion The
Third: One-Way
Flow of Ideas
● We’ve seen a few examples of Java “converging
on” ideas from functional programming
● No equivalent adoption of ideas from OOP in
Haskell
● Not as if OOP is suffering for new ideas
○ Both theoretical…
■ Seriously, look at any OOPSLA program
○ … and practical
■ Proliferation of traits in object systems
■ Go’s radical approach to composition
● Closest I could get: Scala’s use of traits for
bottom-up composition of behaviours
○ More of a function of Scala implementing OOP
○ Not really FP absorbing something from OOP
● Did I miss something?
● Hypothesis: OOP’s focus on explicit entities
within the system (and their taxonomies) just
doesn’t apply to FP
References
1. Rich Hickey, “Persistent Data Structures and Managed References”
(https://www.infoq.com/presentations/Value-Identity-State-Rich-Hickey)
2. Simon Peyton-Jones, “Wearing the Hairshirt” (http://www.cs.nott.ac.uk/~pszgmh/appsem-
slides/peytonjones.ppt)
3. Tony Hoare, “Null References: The Billion Dollar Mistake” (https://www.infoq.com/presentations/Null-
References-The-Billion-Dollar-Mistake-Tony-Hoare)

Contenu connexe

Tendances

Scala In The Wild
Scala In The WildScala In The Wild
Scala In The Wild
djspiewak
 
scalaliftoff2009.pdf
scalaliftoff2009.pdfscalaliftoff2009.pdf
scalaliftoff2009.pdf
Hiroshi Ono
 

Tendances (18)

A Tour Of Scala
A Tour Of ScalaA Tour Of Scala
A Tour Of Scala
 
10 Things I Hate About Scala
10 Things I Hate About Scala10 Things I Hate About Scala
10 Things I Hate About Scala
 
Introduction To Scala
Introduction To ScalaIntroduction To Scala
Introduction To Scala
 
Scala In The Wild
Scala In The WildScala In The Wild
Scala In The Wild
 
Practically Functional
Practically FunctionalPractically Functional
Practically Functional
 
Java 8 Lambda and Streams
Java 8 Lambda and StreamsJava 8 Lambda and Streams
Java 8 Lambda and Streams
 
scalaliftoff2009.pdf
scalaliftoff2009.pdfscalaliftoff2009.pdf
scalaliftoff2009.pdf
 
A Scala Corrections Library
A Scala Corrections LibraryA Scala Corrections Library
A Scala Corrections Library
 
Scala
ScalaScala
Scala
 
Java 8 - Project Lambda
Java 8 - Project LambdaJava 8 - Project Lambda
Java 8 - Project Lambda
 
Stepping Up : A Brief Intro to Scala
Stepping Up : A Brief Intro to ScalaStepping Up : A Brief Intro to Scala
Stepping Up : A Brief Intro to Scala
 
Java 8 presentation
Java 8 presentationJava 8 presentation
Java 8 presentation
 
Starting with Scala : Frontier Developer's Meetup December 2010
Starting with Scala : Frontier Developer's Meetup December 2010Starting with Scala : Frontier Developer's Meetup December 2010
Starting with Scala : Frontier Developer's Meetup December 2010
 
Programming with Lambda Expressions in Java
Programming with Lambda Expressions in Java Programming with Lambda Expressions in Java
Programming with Lambda Expressions in Java
 
Java 8 features
Java 8 featuresJava 8 features
Java 8 features
 
Workshop Scala
Workshop ScalaWorkshop Scala
Workshop Scala
 
Scala Reflection & Runtime MetaProgramming
Scala Reflection & Runtime MetaProgrammingScala Reflection & Runtime MetaProgramming
Scala Reflection & Runtime MetaProgramming
 
Java 8 lambda
Java 8 lambdaJava 8 lambda
Java 8 lambda
 

Similaire à Programming picaresque

BCS SPA 2010 - An Introduction to Scala for Java Developers
BCS SPA 2010 - An Introduction to Scala for Java DevelopersBCS SPA 2010 - An Introduction to Scala for Java Developers
BCS SPA 2010 - An Introduction to Scala for Java Developers
Miles Sabin
 
FP in Java - Project Lambda and beyond
FP in Java - Project Lambda and beyondFP in Java - Project Lambda and beyond
FP in Java - Project Lambda and beyond
Mario Fusco
 
Intro to scala
Intro to scalaIntro to scala
Intro to scala
Joe Zulli
 
Persistent Data Structures by @aradzie
Persistent Data Structures by @aradziePersistent Data Structures by @aradzie
Persistent Data Structures by @aradzie
Vasil Remeniuk
 

Similaire à Programming picaresque (20)

A Brief Introduction to Scala for Java Developers
A Brief Introduction to Scala for Java DevelopersA Brief Introduction to Scala for Java Developers
A Brief Introduction to Scala for Java Developers
 
BCS SPA 2010 - An Introduction to Scala for Java Developers
BCS SPA 2010 - An Introduction to Scala for Java DevelopersBCS SPA 2010 - An Introduction to Scala for Java Developers
BCS SPA 2010 - An Introduction to Scala for Java Developers
 
Java
JavaJava
Java
 
FP in Java - Project Lambda and beyond
FP in Java - Project Lambda and beyondFP in Java - Project Lambda and beyond
FP in Java - Project Lambda and beyond
 
Short intro to scala and the play framework
Short intro to scala and the play frameworkShort intro to scala and the play framework
Short intro to scala and the play framework
 
Scala Talk at FOSDEM 2009
Scala Talk at FOSDEM 2009Scala Talk at FOSDEM 2009
Scala Talk at FOSDEM 2009
 
Intro to scala
Intro to scalaIntro to scala
Intro to scala
 
Java 8
Java 8Java 8
Java 8
 
Scala in a nutshell by venkat
Scala in a nutshell by venkatScala in a nutshell by venkat
Scala in a nutshell by venkat
 
Introduction to new features in java 8
Introduction to new features in java 8Introduction to new features in java 8
Introduction to new features in java 8
 
Introduction to new features in java 8
Introduction to new features in java 8Introduction to new features in java 8
Introduction to new features in java 8
 
DataWeave 2.0 Language Fundamentals
DataWeave 2.0 Language FundamentalsDataWeave 2.0 Language Fundamentals
DataWeave 2.0 Language Fundamentals
 
Java 8 Workshop
Java 8 WorkshopJava 8 Workshop
Java 8 Workshop
 
Java gets a closure
Java gets a closureJava gets a closure
Java gets a closure
 
Persistent Data Structures by @aradzie
Persistent Data Structures by @aradziePersistent Data Structures by @aradzie
Persistent Data Structures by @aradzie
 
Scala is java8.next()
Scala is java8.next()Scala is java8.next()
Scala is java8.next()
 
Programming in java basics
Programming in java  basicsProgramming in java  basics
Programming in java basics
 
Clean Code: Chapter 3 Function
Clean Code: Chapter 3 FunctionClean Code: Chapter 3 Function
Clean Code: Chapter 3 Function
 
Introduction to Client-Side Javascript
Introduction to Client-Side JavascriptIntroduction to Client-Side Javascript
Introduction to Client-Side Javascript
 
Beyond java8
Beyond java8Beyond java8
Beyond java8
 

Dernier

%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
masabamasaba
 
Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...
Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...
Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...
Medical / Health Care (+971588192166) Mifepristone and Misoprostol tablets 200mg
 
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
masabamasaba
 
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
VictoriaMetrics
 
Abortion Pill Prices Boksburg [(+27832195400*)] 🏥 Women's Abortion Clinic in ...
Abortion Pill Prices Boksburg [(+27832195400*)] 🏥 Women's Abortion Clinic in ...Abortion Pill Prices Boksburg [(+27832195400*)] 🏥 Women's Abortion Clinic in ...
Abortion Pill Prices Boksburg [(+27832195400*)] 🏥 Women's Abortion Clinic in ...
Medical / Health Care (+971588192166) Mifepristone and Misoprostol tablets 200mg
 

Dernier (20)

%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
 
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital TransformationWSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
 
%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg
%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg
%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg
 
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
Direct Style Effect Systems -The Print[A] Example- A Comprehension AidDirect Style Effect Systems -The Print[A] Example- A Comprehension Aid
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
 
Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...
Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...
Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...
 
%in kempton park+277-882-255-28 abortion pills for sale in kempton park
%in kempton park+277-882-255-28 abortion pills for sale in kempton park %in kempton park+277-882-255-28 abortion pills for sale in kempton park
%in kempton park+277-882-255-28 abortion pills for sale in kempton park
 
Artyushina_Guest lecture_YorkU CS May 2024.pptx
Artyushina_Guest lecture_YorkU CS May 2024.pptxArtyushina_Guest lecture_YorkU CS May 2024.pptx
Artyushina_Guest lecture_YorkU CS May 2024.pptx
 
VTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learnVTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learn
 
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
 
WSO2Con2024 - GitOps in Action: Navigating Application Deployment in the Plat...
WSO2Con2024 - GitOps in Action: Navigating Application Deployment in the Plat...WSO2Con2024 - GitOps in Action: Navigating Application Deployment in the Plat...
WSO2Con2024 - GitOps in Action: Navigating Application Deployment in the Plat...
 
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
 
Architecture decision records - How not to get lost in the past
Architecture decision records - How not to get lost in the pastArchitecture decision records - How not to get lost in the past
Architecture decision records - How not to get lost in the past
 
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
 
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
 
%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrand%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrand
 
WSO2Con2024 - From Blueprint to Brilliance: WSO2's Guide to API-First Enginee...
WSO2Con2024 - From Blueprint to Brilliance: WSO2's Guide to API-First Enginee...WSO2Con2024 - From Blueprint to Brilliance: WSO2's Guide to API-First Enginee...
WSO2Con2024 - From Blueprint to Brilliance: WSO2's Guide to API-First Enginee...
 
WSO2CON 2024 - Navigating API Complexity: REST, GraphQL, gRPC, Websocket, Web...
WSO2CON 2024 - Navigating API Complexity: REST, GraphQL, gRPC, Websocket, Web...WSO2CON 2024 - Navigating API Complexity: REST, GraphQL, gRPC, Websocket, Web...
WSO2CON 2024 - Navigating API Complexity: REST, GraphQL, gRPC, Websocket, Web...
 
Abortion Pill Prices Boksburg [(+27832195400*)] 🏥 Women's Abortion Clinic in ...
Abortion Pill Prices Boksburg [(+27832195400*)] 🏥 Women's Abortion Clinic in ...Abortion Pill Prices Boksburg [(+27832195400*)] 🏥 Women's Abortion Clinic in ...
Abortion Pill Prices Boksburg [(+27832195400*)] 🏥 Women's Abortion Clinic in ...
 
WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?
 
%in Soweto+277-882-255-28 abortion pills for sale in soweto
%in Soweto+277-882-255-28 abortion pills for sale in soweto%in Soweto+277-882-255-28 abortion pills for sale in soweto
%in Soweto+277-882-255-28 abortion pills for sale in soweto
 

Programming picaresque

  • 1. Programming Picaresque In Which Our Hero Learns Some Valuable Life Lessons And The Importance Of Pure Functions Bret McGuire
  • 3. Object-oriented Programming ● Model of programming based on entities (“objects”) which combine state with behaviour(s) ● Objects correspond to nouns in a system ● Objects interact by invoking methods (verbs) on objects ● Methods with side effects are quite common ○ State updates ○ Interacting with OS resources ● Objects are often mutable ○ Although immutable objects are not prohibited ● Objects must safely manage concurrent access to mutable state when multiple objects are at play
  • 4. Functional Programming ● “Programming that emphasizes programming with functions” [1] ● Side effects in functions should be avoided ○ Functions should compute and return a value based on arguments ○ No statements; everything returns a value ● Values are immutable ● State is a value for a participant in the system (an “identity”) at some point in time ● Seriously, just watch the video ○ Rich explains it much better than I do!
  • 6. Haskell ● Purely functional ○ No side effects ■ That’s what we have monads for ● Lazy evaluation ○ Values aren’t computed until needed ● Static typing ● Paragon of functional programming
  • 7. Scala ● In a bit of a weird spot here ● Scala is explicitly a multi-paradigm language ○ Intent is to support OOP, FP or both ● Over time a bias has emerged ○ Something like “a gentle nudge” towards: ■ Immutability ■ FP concepts ● Not by any means required ○ Don’t have to use scalaz to use Scala ○ Could happily write imperative code all day long ● Plenty of other benefits ○ Advanced type system ○ Type inference ○ Strong pattern matching
  • 8. Java ● Adamantly object-oriented ○ Everything is an object ■ Well, except primitives… ● Statically typed ● Simpler type system than Scala ● Paragon of OO programming ○ For good and for bad ● An important distinction: “Java” can mean: ○ A programming language ○ The virtual machine it runs on ○ The community and practices surrounding them ● We mostly focus on the language here ○ Although community/practices will figure in
  • 10. Scala: Functions As First-Class Entities $ scala ... scala> List("one", "two", "three").map {_.toUpperCase} res0: List[String] = List(ONE, TWO, THREE) scala> val foo = { v:String => v.toUpperCase} foo: String => String = <function1> scala> List("one", "two", "three").map(foo) res1: List[String] = List(ONE, TWO, THREE) scala> val bar = (prefix:String) => (arg:String) => prefix.concat(arg) bar: String => (String => String) = <function1> scala> val baz = bar("hi ") baz: String => String = <function1> scala> List("one", "two", "three").map(baz) res2: List[String] = List(hi one, hi two, hi three)
  • 11. Java: Me Too, Me Too! import java.util.function.Function; ... public class FunctionsTest { private Function<String, String> bar(String prefix) { return v -> prefix + v; } @Test public void testFunctions() { List<String> base = ImmutableList.of("one", "two", "three"); List<String> expected = ImmutableList.of("ONE", "TWO", "THREE"); assertEquals(expected, base.stream().map(v -> v.toUpperCase()) .collect(ImmutableList.toImmutableList())); Function<String, String> foo = v -> v.toUpperCase(); assertEquals(expected, base.stream().map(foo) .collect(ImmutableList.toImmutableList())); Function<String, String> baz = bar("hi "); assertEquals(ImmutableList.of("hi one", "hi two", "hi three"), base.stream().map(baz).collect(ImmutableList.toImmutableList())); } }
  • 12. Java: Let’s Try It With Guava! @Test public void voidTestFunctionsSomeMore() { ImmutableList<String> base = ImmutableList.of("one", "two", "three"); List<String> expected = ImmutableList.of("ONE", "TWO", "THREE"); assertEquals(expected, FluentIterable.from(base).transform(v -> v.toUpperCase()).toList()); Function<String, String> foo = v -> v.toUpperCase(); assertEquals(expected, FluentIterable.from(base).transform(foo).toList()); Function<String, String> baz = bar("hi "); assertEquals(ImmutableList.of("hi one", "hi two", "hi three"), FluentIterable.from(base).transform(baz).toList()); }
  • 13. Java: And Now We Are Sad $ ./gradlew test > Task :compileTestJava FAILED /home/mersault/git/working/src/test/java/com/datastax/FunctionsTest.java:50: error: method transform in class FluentIterable<E> cannot be applied to given types; assertEquals(expected, FluentIterable.from(base).transform(foo).toList()); ^ required: com.google.common.base.Function<? super String,T> found: java.util.function.Function<String,String> reason: cannot infer type-variable(s) T (argument mismatch; java.util.function.Function<String,String> cannot be converted to com.google.common.base.Function<? super String,T>) where T,E are type-variables: T extends Object declared in method <T>transform(com.google.common.base.Function<? super E,T>) E extends Object declared in class FluentIterable /home/mersault/git/working/src/test/java/com/datastax/FunctionsTest.java:54: error: method transform in class FluentIterable<E> cannot be applied to given types; FluentIterable.from(base).transform(baz).toList()); ^ required: com.google.common.base.Function<? super String,T> found: java.util.function.Function<String,String> reason: cannot infer type-variable(s) T (argument mismatch; java.util.function.Function<String,String> cannot be converted to com.google.common.base.Function<? super String,T>) where T,E are type-variables: T extends Object declared in method <T>transform(com.google.common.base.Function<? super E,T>) E extends Object declared in class FluentIterable 2 errors
  • 14. Where We Went Wrong ● Lambdas are implemented as a compile-time feature ○ Think “pre-processor” if that weren’t such a dirty notion in some quarters ● If a lambda is used in a context where a “functional interface” is expected the lambda will be converted to the type of that “functional interface” ○ Over time Java has created many types which are in essence functions (listeners, event handlers, etc.) ○ Changing all these types to inherit from a common type would’ve been… painful ● Upshot: once this conversion happens the lambda is just another instance of that type ○ When we assign the lambda to a variable or return it from a function we do just that
  • 15. This Is Very Definitely An Improvement private static class Foo implements com.google.common.base.Function<String, String> { public String apply(String arg) { return arg.toUpperCase(); } } private static com.google.common.base.Function<String, String> bar(String prefix) { return new com.google.common.base.Function<String, String>() { public String apply(String arg) { return prefix + arg; } }; } @Test public void testOldSchoolGuava() { List<String> base = ImmutableList.of("one", "two", "three"); List<String> expected = ImmutableList.of("ONE", "TWO", "THREE"); assertEquals(expected, Lists.transform(base, new Foo())); com.google.common.base.Function<String, String> baz = bar("hi "); assertEquals(ImmutableList.of("hi one", "hi two", "hi three"), Lists.transform(base, baz)); }
  • 17. Haskell: Things Don’t Change GHCi, version 8.6.3 Prelude> let foo = [1,2,3] Prelude> let bar = [4,5,6] Prelude> foo ++ bar [1,2,3,4,5,6] Prelude> foo [1,2,3] Prelude> let baz = foo ++ bar Prelude> baz [1,2,3,4,5,6] Prelude> foo [1,2,3] Prelude> bar [4,5,6]
  • 18. Haskell: ADTs Don’t Change Either GHCi, version 8.6.3 Prelude> data OneTwo = OneTwo { one :: Int, two :: String } deriving Show Prelude> let foo = OneTwo { one = 1, two = "one" } Prelude> let bar = foo { two = "oops" } Prelude> foo OneTwo {one = 1, two = "one"} Prelude> bar OneTwo {one = 1, two = "oops"}
  • 19. Scala: This Looks Familiar... Welcome to Scala 2.11.8 (OpenJDK 64-Bit Server VM, Java 1.8.0_181). scala> val foo = List(1,2,3) foo: List[Int] = List(1, 2, 3) scala> val bar = List(4,5,6) bar: List[Int] = List(4, 5, 6) scala> foo ++ bar res0: List[Int] = List(1, 2, 3, 4, 5, 6) scala> foo res1: List[Int] = List(1, 2, 3) scala> val baz = foo ++ bar baz: List[Int] = List(1, 2, 3, 4, 5, 6) scala> baz res2: List[Int] = List(1, 2, 3, 4, 5, 6) scala> foo res3: List[Int] = List(1, 2, 3) scala> bar res4: List[Int] = List(4, 5, 6)
  • 20. Java: In The Beginning ● Java has certainly not ignored the notion of immutable data ○ Collections.unmodifiable* has been around since… Java 1.2-ish ■ Return wrapped versions of collection types which throw exceptions on mutation methods ○ Value object ■ No language-level support ■ Several recipes/patterns for doing so ● “Effective Java” recipe ● JCIP discusses the idea ● Discussion centers on concrete benefits of immutable objects ○ Thread safety ○ Ease of reasoning ○ No notion of the deeper way of thinking about values, identity
  • 21. Java: The Middle Ages ● Collections: google-collections (later folded into Guava) comes along and offers Immutable*, truly immutable collection classes ● These implementations address two major problems with Collections.unmodifiable* ○ The wrapped collections are unmodifiable, not immutable ■ Changes to the wrapped (presumably mutable) collection would appear in the wrapper ○ Return types are general List, Map, Set interfaces ■ No indication to the type system that these objects have different characteristics ● Value objects: not much change ○ Still no language-level support ○ Developers largely left to roll their own
  • 22. Java: It’s A Brave New World! public class OneTwoTest { @Value.Immutable public interface OneTwo { Integer one(); String two(); } @Test public void testOneTwo() { OneTwo onetwo = ImmutableOneTwo.builder().one(1).two("one").build(); assertEquals(1, onetwo.one().intValue()); assertEquals("one",onetwo.two()); } }
  • 25. Some Things About Monads ● Remind me what they are again? ○ A wrapped value and… ○ A “unit” function ■ To put a value into a monad ○ A “bind” function ■ Given (M T) and a function T -> M T’ apply the function to the value wrapped in the moand to generate a new monad
  • 26. An example: Option ● The Option monad contains a value with one of two variant types: ○ None (has no value) ○ Some (contains some value) ● The “bind” operation will apply it’s fn to the wrapped value if the monad val is Some ○ Otherwise return None ● These behaviours allow Option to serve as “a simple kind of error monad” ○ If a set of operations on a monad are successful you get a Some containing the result ○ If any step fails you get None
  • 27. Haskell: All About Option data Maybe a = Nothing | Just a deriving ( Eq , Ord ) instance Monad Maybe where (Just x) >>= k = k x Nothing >>= _ = Nothing (>>) = (*>) fail _ = Nothing The type declaration: Maybe is an ADT with two distinct variant types While we’re here let’s make it a monad as well
  • 28. Haskell: Option In Practice GHCi, version 8.6.3 Prelude> (Just 1) >>= t -> Just(t + 1) Just 2 Prelude> Nothing >>= t -> Just(t + 1) Nothing
  • 29. Scala: This Looks Familiar (Reprise)... $ more SillyOptions.scala def doSillyThing(opt:Option[String]):Option[Int] = { opt filter { !_.isEmpty } map { _.length } map { _ * 10 } } $ scala -i SillyOptions.scala Loading SillyOptions.scala... doSillyThing: (opt: Option[String])Option[Int] Welcome to Scala 2.11.8 (OpenJDK 64-Bit Server VM, Java 1.8.0_181). scala> doSillyThing(None) res0: Option[Int] = None scala> doSillyThing(Some("")) res1: Option[Int] = None scala> doSillyThing(Some("abc")) res2: Option[Int] = Some(30) scala> doSillyThing(Some("abcdef")) res3: Option[Int] = Some(60)
  • 30. Java: A Pair of Optionals ● Java has two common implementations of the option/maybe type ○ Guava’s com.google.common.base.Optional ■ First on the scene ■ Before this everybody rolled their own ○ java.util.Optional ■ Standard as of Java8 ● Overwhelming use case here is to avoid returning null ○ Goal: minimize NullPointerExceptions (NPEs) ● This is not a small thing ○ Since null references have cost us exactly one billion dollars [3]
  • 31. Java: The Good Side of Optional public class OptionTest { private Integer findFirstNegativeInt(Integer...integers) { for (Integer integer : integers) { if (integer < 0) { return integer; } } return null; } private Optional<Integer> findFirstNegativeIntOption(Integer...integers) { for (Integer integer : integers) { if (integer < 0) { return Optional.<Integer>of(integer); } } return Optional.empty(); } @Test public void testOption() { assertNotNull(findFirstNegativeInt(1,2,3,-100,4)); assertNull(findFirstNegativeInt(1,2,3,4)); assertNotNull(findFirstNegativeIntOption(1,2,3,-100,4)); assertNotNull(findFirstNegativeIntOption(1,2,3,4)); }
  • 32. Java: The Other Side of Optional public class OtherOptionTest { private Optional<String> thisIsSafeRight(List<Integer> integers, Integer thingIWant) { Map<Integer,Optional<String>> options = new HashMap<Integer,Optional<String>>(); for (Integer integer : integers) { options.put(integer, Optional.<String>of(integer.toString())); } return options.get(Collections.binarySearch(integers, thingIWant)); } @Test public void testOption() { assertNotNull(thisIsSafeRight(ImmutableList.of(1,2,3,4), 1)); // oops, this didn't pass assertNotNull(thisIsSafeRight(ImmutableList.of(1,2,3,4), 4)); assertNotNull(thisIsSafeRight(ImmutableList.of(10,20,30,40), 10)); // hmmm, this didn't pass either } }
  • 33. Some Other Things About Option and Java... ● So… Java doesn’t use monads ○ In practice, no ○ But...
  • 34. Java: It’s a Monad After All! public class OptionMonadTest { public Optional<Integer> doTheThing(Optional<String> in) { return in.filter(v -> !v.isEmpty()).map(v -> v.length()).map(v -> v * 10); } @Test public void testOptionAsMonad() { assertFalse(doTheThing(Optional.empty()).isPresent()); assertFalse(doTheThing(Optional.of("")).isPresent()); assertEquals(30, doTheThing(Optional.of("abc")).orElse(-1).intValue()); assertEquals(60, doTheThing(Optional.of("abcdef")).orElse(-1).intValue()); } }
  • 36. Conclusion The First: Adaptation Not Adoption ● We’ve seen Java “adapt” ideas from FP into something that works within Java ○ Immutable types rather than persistent data structures ○ Option type rather than use as monad ● Even these adapted uses can be terribly powerful ○ These ideas represent significant improvements to the OOP process
  • 37. Conclusion The Second: Perhaps This Can Only Go So Far ● Is it possible that adoption of these ideas (persistent data structures and/or monads) at a deeper level is limited because they represent ways of managing state? ● State management in an object-oriented system is (for better or worse) a solved problem
  • 38. Conclusion The Third: One-Way Flow of Ideas ● We’ve seen a few examples of Java “converging on” ideas from functional programming ● No equivalent adoption of ideas from OOP in Haskell ● Not as if OOP is suffering for new ideas ○ Both theoretical… ■ Seriously, look at any OOPSLA program ○ … and practical ■ Proliferation of traits in object systems ■ Go’s radical approach to composition ● Closest I could get: Scala’s use of traits for bottom-up composition of behaviours ○ More of a function of Scala implementing OOP ○ Not really FP absorbing something from OOP ● Did I miss something? ● Hypothesis: OOP’s focus on explicit entities within the system (and their taxonomies) just doesn’t apply to FP
  • 39. References 1. Rich Hickey, “Persistent Data Structures and Managed References” (https://www.infoq.com/presentations/Value-Identity-State-Rich-Hickey) 2. Simon Peyton-Jones, “Wearing the Hairshirt” (http://www.cs.nott.ac.uk/~pszgmh/appsem- slides/peytonjones.ppt) 3. Tony Hoare, “Null References: The Billion Dollar Mistake” (https://www.infoq.com/presentations/Null- References-The-Billion-Dollar-Mistake-Tony-Hoare)

Notes de l'éditeur

  1. A few introductory comments This topic (convergence of OO and FP) is… large Third or fourth generation of these slides At one point you were gonna get a lengthy discussion of Alan Kay All you can do is find some avenue into this conversation and run with it A few quick notes about me I started out writing Perl and later Scheme as an undergrad Then went on to be a Java programmer for 20 years Early and eager embrace of Clojure and Scala Now I write Clojure at my day job Try to keep a foot in both these camps Putting slides together is always an effort for me Feel pretty good about this one The theme is called “Paradigm”
  2. Quick definitions for OO and FP Note that this is a perilous exercise There are no universally agreed upon definitions for either of these things Doing this mainly to orient some of the discussion…
  3. What does it mean to say functions are a first-class entity of your language? It means kinda what you’d expect… you can do everything with them you can do with other things (like objects, say) You can: Assign them to a variable Pass them as an arg to something else Return them from a function
  4. Note: the first test (the one with the lambda inline) actually passed Anybody wanna guess about where we went wrong?
  5. No one is dying to go back to this kind of nonsense Having lambdas is better than not having lambdas And yes, in large part this approach was taken because Java has been around for a long time and is very concerned about not breaking existing code My goal here is not to bash on Java or how it solved this problem My goal here is to make the following observations: The idea of lambdas (anonymous functions) were incorporated This idea has a long history in other languages (some of them functional, some OO) This feature was brought in in a way that doesn’t really support treating these entities as first-class functions This is still described as “functional” in many resources (and victory is declared)
  6. Not just immutable here; call out the persistent data structures at play
  7. Scala has a suite of mutable collections which parallel the immutable ones… but we get immutable behaviour by default
  8. The Java Collections framework came in with Java 1.2… and I believe the unmodifiable entities were there the beginning Value object - loose equivalent to ADT in Java (very, very loose) “Effective Java” - even included methods to return new versions of immutable structures from modification operations as programming “in a functional style”
  9. New frameworks (such as Immutables, used here) facilitate creation of immutable value objects But the conversation here is still limited to “immutable objects are thread-safe and easy to reason about” Which is true… but the next step isn’t usually taken Why does FP care so much about immutability What’s a value and how do I work with it? What are persistent collections? And, far more importantly… _why_ do I care about them? There are some Java impls of persistent collections… they’re just on the margins
  10. Simon Peyton Jones suggestion for the term that should’ve been used instead of “monad”... from the “Wearing the Hair Shirt” slides
  11. Don’t worry, we won’t be going through Yet Another Monad Tutorial We do need to highlight a couple things though… We’re simplifying a lot here to highlight the things we actually care about
  12. “Simple kind of error monad”... from Haskell’s hackage docs on Data.Maybe… look it up, I swear it’s there
  13. “Everybody rolled their own” - and that’s never been a problem ever
  14. It’s also not foolproof… So, I’m not a very good programmer and I think it’s a great idea to compute all possible return values upfront just ‘cause… well, because I read it on a blog post somewhere So I do that, and then I search for my object and return the corresponding Optional from my pre-computed map Sure, you wouldn’t actually do this… but the point is (a) Optional references can still themselves be null and (b) it’s fairly easy to write code which obscures when you’re returning nulls or not
  15. Unfortunately most of the usages (at least that I’ve come across), documentation, design patterns, etc. don’t worry about this kind of thing Very focused on returning Optional as an object to avoid NPEs
  16. Nothing from OO -> FP… outside of CLOS, that is, and that is… a stretch