Transcript
Page 1: About Functional Programming

About Functional Programming(Robust Programming)

Aapo Kyrölä, 23.3.2011Sulake

Page 2: About Functional Programming

Contents

1. Motivation: some issues with OOP and Java2. Introduction to Functional Programming3. Functional Programming –style in Java

Page 3: About Functional Programming

Motivation: Problems with Object-Oriented Programming and Java

Page 4: About Functional Programming

Fundamental Design Problem of Java

• Not well-typed => Nullpointers

• Programmer should handle two cases explicitly: userToBan is either null or not null.– OR, compiler should not allow assigning NULL to a reference

(like in C++ &obj).• By proper typing, compiler would prevent null-pointers…

Page 5: About Functional Programming

In Standard ML

Page 6: About Functional Programming

OOP: criticism• Class/Object structure cumbersome to change.

– a class hierarchy might be natural from some point of view, but for other (future) uses cumbersome.

• Problems with Inheritance– much functionality hidden in superclasses.– Hard to manage: if behavior of superclass is changed, how does it affect

all subclasses?• Especially in UI: subclass may depend on a not-intended behavior of a

superclass.– Delegation usually better than inheritance (Spring)

• better modularity with IOP than with object hierarchies.

• API dependencies.– Makes refactoring hard.

Page 7: About Functional Programming

Object-relational mapping• Always hated…• a) Intuitively, object should have an identity– But when you have many copies of the object…

• b) Queries with criteria-objects or example objects just stink.

Select * from sale where date>? and date<? order by date limit 10;

Page 8: About Functional Programming

ORM (continues)

• c) Even bigger problem with relations– Identity of the objects in collection?– Cumbersome to control when you want the

collections loaded (all that hibernate session stuff).

• d) SQL is great, easy and powerful. Why switch away? Declarative programming is powerful.

Page 9: About Functional Programming

Side effects

• When you call a method, it can change the state, even if it is named getX().– At least previously in Habbo: effects on database

object cache.– Or : calling a collection method in hibernate

object, user.getFriends().• You need to know if users were loaded in order to

reason what happens.

Page 10: About Functional Programming

Who manages an object?

• Java does not have immutable objects– Need to “wrap” them by hand

(Collections.unmodifiableList()).– Error only on run-time. How do you handle such

error? Should be compile-time.• Concurrency issues– Who manages multi-threaded access to an object?

Read-only objects do not have this problem…– Easy to get deadlocks.

Page 11: About Functional Programming

Key to more robust code

• Compiler and type-system should do more!– Generics are even worse…

• End of rant.

Page 12: About Functional Programming

Quick introduction to Functional Programming Languages

Page 13: About Functional Programming

Contents1. Some history2. Functional vs. imperative languages

1. Declarative programming.2. Functions as values.3. High-order functions.4. Referential transparency.5. Power of the Type system in Standard ML.

All examples in Standard ML.

Next: how to program “functionally in Java”.

Page 14: About Functional Programming

History

• Lambda calculus (30s-40s): mathematical theory for computing with functions (Church).

• LISP (50s): motivated by artificial intelligence. Introduced high level data structures such as lists and trees. – Scheme, Clojure

• Meta-language: ML (70s): for writing proof checkers.– Standard ML, OCaML, F#

• Haskell (80s-90s)

Page 15: About Functional Programming

History (cont.)

• Functional programming has (so far) mostly been favored in the academia

• Mathematically consistent (no pointer-arithmetic).• Clear semantics: define functions, not manipulate state.• Focus on computation, not on memory addressing, low-level

issues.– Carnegie Mellon uses ML as teaching language on data

structures and algorithms• Many other universities use Scheme or Haskell.• Learn the data structures & algorithms, not fight with

segfaults or nullpointers.

Page 16: About Functional Programming

FP: new coming?• Functional languages compatible with mainstream languages:

– Microsoft’s F#, based on OCaML– Scala, Clojure for Java (hybrids)– Python and other script languages adopt many functional ideas, such as list.map() and

lambda-functions.• Focus on correctness, not performance

– Especially important in finance.– Compilers have improved.

• But,– Completely different way of programming: hard to change.– Performance (and memory consumption) has been a big issue.– Lack of good tools; cumbersome to program “stateful” code such as UI.– However, Scala/Clojure/F# will help bridging the gap as they are compatible with

Java/C#.

Page 17: About Functional Programming

What is Functional Programming?• Imperative program executes sequence of commands to compute a value

and modifies the state in the process:

• Functional program is declarative and uses pattern matching: fun sumlist [] = 0 | (x::xs) = x + sumlist(xs);

“sum of numbers in list is the value of head of the list plus the sum of the rest of the list. Sum of an empty list is zero.”

• Functions are usually defined recursively.

Page 18: About Functional Programming

More function declarations

> fun factorial 1 = 1# | factorial n = n * factorial(n-1);

“factorial of n is n multiplied by the factorial of n-1, if n is larger than 1.Otherwise, factorial for 1 is 1.”

fun gcd(a : int, 0) = a | gcd(a : int, b : int) = if (a < b) then gcd(a, b mod a) else gcd(b, a mod b)

Page 19: About Functional Programming

More function declarations

• More pattern matching for types:

Page 20: About Functional Programming

Functional programming (cont.)

• Imperative program executes commands, functional program evaluates expressions.– Functions have no side-effects – there is no state.– “Monads” used for input/output etc. (not part of

this talk)• Values are bound to symbols – but they

cannot be changed!– Definition of variable is different: it is not an

address in memory.

Page 21: About Functional Programming

Functional programming (cont.)

• Functions are values, and can be passed as parameters (anonymous or named):– Example :

(* Create new functions that return square of the original function *)

fun sqrfun (f : real->real) = let

fun F2 (x:real) = f(x)*f(x) in F2 end;

val dblsin = sqrfun(Math.sin);> dblsin(2.0);val it = 0.8268218104: real

Page 22: About Functional Programming

FP (cont.): Functionals• map

> val mylist = [1,2,3,4,5,6,7,8,9,10];val mylist = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]: int list> List.map (fn x=>x*x) mylist;val it = [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]: int list

• foldl / foldr> List.foldl (fn (x,n)=>x+n) 0 mylist;val it = 55: int> List.foldl op+ 0 mylist;val it = 55: int

> val listsummer = List.foldl op+ 0;val listsummer = fn: int list -> int> listsummer(mylist);val it = 55: int

• filter> val evenfilter =

List.filter (fn (x)=> if (x mod 2 = 0) then true else false);val evenfilter = fn: int list -> int list> evenfilter(mylist);val it = [2, 4, 6, 8, 10]: int list

Extremely consistent and clear code!

Page 23: About Functional Programming

Referential Transparency

= expression can be safely replaced by its values= no side-effects.

• Enables reasoning about semantics of programs. • Lazy evaluation.• Automatic parallel evaluation: order of execution does

not matter.• Imperative programs are close to machine code, hard to

read. Meaning of functional program is “as it is written”.

Page 24: About Functional Programming

Type system

• Very powerful feature of ML (and Haskell):– use it for your benefit. Compiler can detect many errors

that Java compiler could not.– (You can ignore the type system and use wildcards

extensively, but then you lose much of the power of Functional Programming).

• Parametric polymorphism and algebraic data types– instead of inheritance.

• Example…

Page 25: About Functional Programming

Type system: algebraic datatypes

• Product types (records=structs) and sum-types (union of types, such as: user|pet|furniture)

Page 26: About Functional Programming

ADT (cont.)

Page 27: About Functional Programming

ADT (cont.)

• Let’s now add a new room object type, “wallitem”.

But we forget to add a case to“blocks_coordinate”!

Page 28: About Functional Programming

ADT (cont.)

• But compiler warns us about this!

Page 29: About Functional Programming

ADT (cont.)

• Compiler also warns about redundant cases– typical error.

• Consider this in Java– perhaps you have blocksCoordinate() for each room

object class – example may not be best.– but, maybe in Catalog code we have special price for

each item for Moderators:• This will be implemented as a if/case in Catalog code, not

as a method in User object.• Easy to forget cases when new user types are added.

Page 30: About Functional Programming

Parametric Polymorphism

• Close to C++ templates– unlike Java generics, first-class types (compile-

time).• Recursive types

- definition of a tree with node type a’:

datatype ’a tree = Empty |

Node of ’a tree * ’a * ’a tree

Page 31: About Functional Programming

Miscellanious• In practice, it is easy to very also inefficient code in SML

(like it is with Java).– Garbage collection.

• Standard ML has a sophisticated module system that neatly separates API and implementation.

• Lazy ML– Haskell is lazily evaluated.– Laziness is problematic for parallelism or reasoning about costs.

• OCaML brings objects to ML.– (but no-one uses them…)

Page 32: About Functional Programming

Functional Style with Java

Some ideas

Page 33: About Functional Programming

Functional Languages for JDK

• Scala– gaining popularity.– compiles into Java bytecode, compatible with

Java.– parallel computation features.– Erlang-type concurrent messaging style

programming also supported.• Clojure– LISP dialect.

Page 34: About Functional Programming

1) Pattern: Immutable objects• If a “manager” returns an object, usually it should be immutable – and a

copy:– create special immutable classes: ImmutableUser, ImmutableRoom, etc. => Makes

ownership of the object clear.– better to make own classes that do not have methods to modify the object than

throw an exception!– Collections.unmodifiableList(…)– do not cache objects – only manager caches.– makes thread-safe programming easier.

• Favor tiny carrier objects instead of huge monstrous objects– instead of User, favor UserId, UserAppearance.– make it clear by naming, that the object does not represent the “actual object”, buti

s a “view” of it.– especially important with DAOs!! Should be evident what data has been loaded to

the data-object.

Page 35: About Functional Programming

2) Fail fast

• Java does not do much sanity checking in compilation time, so try to make incorrect code fail quickly in test time. Use runtime exceptions – and you should not prepare to handle these kind of errors.

Page 36: About Functional Programming

3) Instead of modifying an object, create new ones

• Avoids race conditions.• Java GC is really fast, and likes short-lived

objects.• Particulary: avoid recycling objects. It is very

error-prone!

Page 37: About Functional Programming

4) Assertions and Declarations• Functional: @MessageHandler(id=.., need_session=true), @Moderator

– Use conservative default values for parameters!– This is much better than expecting programmers to check all cases.

• Assertive: @NotNull, @NoSideEffect, @Slow etc.– not great, but better than nothing.

• Intuitive naming: don’t use getXX, if method has a side-effect!• Long method-names that explain what method does are good:

– user = loginUserWithPassword(user, pass);• user = loginUserWithToke(token);

– instead of user = login(user,pass); • user = login(token);

Page 38: About Functional Programming

Do not switch assertions off!

• “… it is absurd to make elaborate security checks on debugging runs, when no trust is put into results, and then remove them in production runs, when an errorenous result could be expensive or disastrous. What would we think of a sailing enthusiast who wears his life-jacket when training on dry land but takes it off as soon as he goes to sea?”

• C.A.R Hoare (1989)

Page 39: About Functional Programming

5) Poor man’s Closures• Closures = anonymous/lambda functions– example from Groovy:

• Unfortunately Java (not even 7) will support Closures.– BUT, anonymous classes can be used for the same purpose –

although with much boilerplate.

Page 40: About Functional Programming

Closure example

Page 41: About Functional Programming

6) Compute, do not store

• If computing a value is reasonably light-weight, it is better to do that than store a precomputed value.– Avoids many errors of forgetting to update all

fields of an object.– (example on next slide)

Page 42: About Functional Programming

Example

Page 43: About Functional Programming

Discussion

Page 44: About Functional Programming

Questions

1. Do you have experience on functional programming?

2. Opinion on using Hibernate vs. using explicit queries?

3. Where is Java going?1. why is it so difficult to do simple things, like a

simple web service, with Java?4. Convention vs. Configuration?

Page 45: About Functional Programming

Resources

• PolyML: http://www.polyml.org/• Google: “ocaml jane street cmu”– good video introduction to FP

• scala-lang.org


Top Related