SlideShare a Scribd company logo
1 of 30
Download to read offline
Making Your Program Spicy
Currying
and
Partial Function Application (PFA)
Dhaval Dalal
@softwareartisan
https://dhavaldalal.wordpress.com
14th Nov 2019
• Refers to the phenomena of rewriting a N-arg function
to a nest of functions, each taking only 1-arg at a time
Currying
// (String, Integer) -> String

String merge(String x, Integer y) {

return x + y.toString();

}

// String -> (Integer -> String)

Function<Integer, String> merge(String x) {

return y -> x + y.toString();

}

// () -> (String -> (Integer -> String))

Function<String, Function<Integer, String>> merge() {

return x -> y -> x + y.toString();

}
// (String -> (Integer -> String))

Function<String, Function<Integer, String>> merge = x -> y -> x + y.toString();

System.out.println(merge("Test#", 1)); // Test#1

System.out.println(merge("Test#").apply(2)); // Test#2

System.out.println(merge().apply("Test#").apply(3)); // Test#3
System.out.println(merge.apply("Test#").apply(4)); // Test#4
Currying
For each arg, there is
another nested function,
that takes a arg and
returns a function taking
the subsequent arg, until
all the args are exhausted.
f : (T, U, V) ↦ R
f′ : T ↦ U ↦ V ↦ R
f = f′
• Curried function is a nested structure, just like Russian
dolls, takes one arg at a time, instead of all the args at once.
Currying
• Function type associates towards right.
• In other words, arrow groups towards right.
Function<String, Function<Integer, String>> merge = 

x ->
y ->
x + y.toString();
x -> y -> x + y.toString();
// is same as
x -> (y -> x + y.toString());
• Function application associates towards left. In
other words, apply() groups towards left.
merge.apply("Test#").apply(1);
// is same as
(merge.apply("Test#")).apply(1);
Why Currying?
• Facilitates arguments to be applied from different
scopes.
Function<Integer, Function<Integer, Integer>> add =
x ->
y ->
x + y;
Function<Integer, Integer> increment = add.apply(1);
increment.apply(2); // 3
Function<Integer, Integer> decrement = add.apply(-1);
decrement.apply(2); // 1
• Helps us reshape and re-purpose the original function
by creating a partially applied function from it
Function<Integer, Function<Integer, Integer>> add =
x ->
y ->
x + y; Scope 1
Scope 2
But, how does that
make programming
spicier?
• Let’s say we have a Customer repository.
• Now, we want to allow authorised calls to repo. So,
Let’s write an authorise function.
class CustomerRepository {

Optional<Customer> findById(Integer id) {

return (id > 0) ? Optional.of(new Customer(id)) 

: Optional.empty();

} 

}
class Authoriser {

public Optional<Customer> authorise(CustomerRepository repo, Request
request) {

System.out.println("Authorizing Request#" + request.id);

// Some auth code here which guards the request.

// On success, the line below is executed.

return repo.findById(Integer.parseInt(request.get("customer_id")));

}

}
• We also have a Request.
• Lets see them in action…
class Request {

public final int id;

private Map<String, String> params = new HashMap<>();



Request(int id) { this.id = id; }

String set(String key, String value) { return params.put(key, value); } 

String get(String key) { return params.get(key); }

}
var authoriser = new Authoriser();

var repo = new CustomerRepository();



var request1 = new Request(1) {{ set("customer_id", "10"); }};



var customer1 = authoriser.authorise(repo, request1);

System.out.println(customer1);



var request2 = new Request(2) {{ set("customer_id", "30"); }};

var customer2 = authoriser.authorise(repo, request2);

System.out.println(customer2);
• Requests vary, however the CustomerRepository is
same.

• Can we avoid repeated injection of the repo?
Solution 1
Optional<Customer> authorise(Request req) {
CustomerRepository repo = new CustomerRepository();
return repo.findById(req.get());
}
Authoriser authoriser = new Authoriser();
Request req1 = new Request();
var customer1 = authoriser.authorise(req1);
Request req2 = new Request();
var customer2 = authoriser.authorise(req2);
• Wrap the authorise function in another function (also
called authorise)
• Requests vary, however the CustomerRepository is
same.

• Can we avoid repeated injection of the repo?
Solution 1
Optional<Customer> authorise(Request req) {
CustomerRepository repo = new CustomerRepository();
return repo.findById(req.get());
}
Authoriser authoriser = new Authoriser();
Request req1 = new Request();
var customer1 = authoriser.authorise(req1);
Request req2 = new Request();
var customer2 = authoriser.authorise(req2);
But
newification
locally like
this is
untestable!
• Wrap the authorise function in another function (also
called authorise)
Solution 2
class Authoriser {
public
Function<Request, Optional<Customer>> authorise(CustomerRepository repo) {
return req -> {
//Some auth code here which guards the request.
repo.findById(req.get());
}
}
}
var repo = new CustomerRepository();
Function<Request, Optional<Customer>> curriedAuthorise = authorise(repo);
Request req1 = new Request();
var customer1 = curriedAuthorise.apply(req1);
Request req2 = new Request();
var customer2 = curriedAuthorise.apply(req2);
• Re-shape authorise to accept only one fixed
parameter - CustomerRepository
Need some more
spice?
interface Transaction { }
interface ApprovalStrategy {
boolean approve(List<Transaction> ts);
//…
}
class Clearing {
private final ApprovalStrategy as;
Clearing(ApprovalStrategy as) {
this.as = as;
}
public boolean approve(List<Transaction> ts) {
return as.approve(ts);
}
}
//main
ApprovalStrategy singleMakerChecker = new SingleMakerChecker();
Clearing clearing = new Clearing(singleMakerChecker);
clearing.approve(ts);
Regular DI
Curried DI
interface Transaction { }
interface ApprovalStrategy {
boolean approve(List<Transaction> ts);
//…
}
class Clearing {
public
Function<List<Transaction>, Boolean> approve(ApprovalStrategy as) {
return ts -> as.approve(ts);
}
}
//main
Clearing clearing = new Clearing();
// ApprovalStrategy can now be injected from different contexts,
// one for production and a different one - say mock for testing,
// Just like in case of Regular DI.
clearing.approve(new SingleMakerChecker()).apply(ts);
Making Our Own Curry
<T, U, R>
Function<T, Function<U, R>> curry(BiFunction<T, U, R> fn) {
return t -> u -> fn.apply(t, u);
}
// Function with all args applied at the same time.
BiFunction<Integer, Integer, Integer> add = (x, y) -> x + y;
// Curried Function - one arg at a time.
Function<Integer, Function<Integer, Integer>> cAdd = curry(add);
Function<Integer, Integer> increment = cAdd.apply(1);
increment.apply(2); // 3
Function<Integer, Integer> decrement = cAdd.apply(-1);
decrement.apply(2); // 1
It would be nice if
Java8 provided this
out-of-box on
BiFunction
Scala calls
this curried
Uncurry or Tuple it!
<T, U, R>
BiFunction<T, U, R> uncurry(Function<T, Function<U, R>> fn) {
return (t, u) -> fn.apply(t).apply(u);
}
// Curried Function - one arg at a time.
Function<Integer, Function<Integer, Integer>> add = x -> y -> x + y;
// Function with all args applied at the same time.
BiFunction<Integer, Integer, Integer> ucAdd = uncurry(add);
ucAdd.apply(2, 3); // 5
It would be nice if
Java8 provided this
out-of-box on
Function
Scala calls
this uncurried
Currying in Scala
scala> def merge1(x: String, y: Int) = x + y.toString
merge1: (x: String, y: Int)String
scala> val merge1F = merge1 _
merge1F: (String, Int) => String
scala> def merge2(x: String)(y: Int) = x + y.toString

scala> val merge2F = merge2 _
merge2F: String => (Int => String)
scala> val mergeTest = merge2F("Test#")
mergeTest: Int => String
scala> mergeTest(1)
res1: Test#1
scala> mergeTest(2)
res2: Test#2
• Scala uses special syntax for currying - It does not use
tupled arguments, instead uses multiple function call
syntax in the definition to denote a curried function.
Curry Uncurry
scala> def merge1(x: String, y: Int) = x + y.toString
merge1: (x: String, y: Int)String
scala> val merge1F = merge1 _
merge1F: (String, Int) => String
scala> val merge1FCurried = merge1F.curried
merge1FCurried: String => (Int => String)
scala> def merge2(x: String)(y: Int) = x + y.toString

scala> val merge2F = merge2 _
merge2F: String => (Int => String)
scala> val merge2FUncurried = Function.uncurried(merge2F)
merge2FUncurried: (String, Int) => String
Scala
PFA in Scala
// Partially Applied Function or Partial Function Application (PFA)

def greet(salutation: String, fname: String, lname: String)
= s"$salutation. $fname $lname"

println(greet("Mr", "Dhaval", "Dalal")) // Mr Dhaval Dalal
def new_ms = greet("Ms", _: String, _: String)
// (String, String) => String

println(new_ms("Ada", "Lovelace")) // Ms Ada Lovelace



def new_drew = greet(_: String, _: String, "Drew")

(String, String) => String
println(new_drew("Ms", "Nancy")) // Ms Nancy Drew
• Supply a value to partially apply the function and to
leave out the arguments unapplied, use underscore “_”

• Note: PFA is different from Partial Function
Re-shaping Third Party
Library Functions
• In third-party libraries we may never be able to
modify the code. 

• Use Currying/PFA to simplify the callers interface.
def power(n: Double) = Math.pow(_: Double, n)

val square = power(2)

println(square(2)) // 4.0



val cube = power(3)

println(cube(2)) // 8.0
Currying in Haskell
greet :: String -> String -> String -> String

greet salutation fname lname = salutation ++ ". " ++ fname ++ " " ++ lname



main :: IO ()

main = do

print $ greet "Mr" "Dhaval" "Dalal" -- Mr Dhaval Dalal

let greet_mr = greet "Mr"

print (greet_mr "Joe" "Shmo") -- Mr Joe Shmo

let greet_mr_joe = greet "Mr" "Joe"

print (greet_mr_joe "Sober") -- Mr Joe Sober

print "Done!"
• In Haskell, all the functions are curried by default,
you don’t need special syntax for that.

• It does not have Partially Applied Functions.
Currying in Haskell
Prelude> :type (*)
(*) :: Num a => a -> a -> a
Prelude> multiply2 = (*2)
Prelude> :type multiply2
multiplyBy2 :: Num a => a -> a
Prelude> multiply2 3
6
• Even operators are
curried by default.
Prelude> :type filter
filter :: (a -> Bool) -> [a] -> [a]
Prelude> even = x -> x `mod` 2 == 0
Prelude> filterEvens = filter even
Prelude> :type filterEvens
filterEvens :: Integral a => [a] -> [a]
Prelude> filterEvens [0..10]
[2,4,6,8,10]
Prelude> filterOdds = filter (not . even)
Prelude> filterOdds [0..10]
[1,3,5,7,9]
• Yet another
example…
PFA in Clojure
(defn new-person [salutation f-name l-name]

(println salutation f-name l-name))



(new-person "Mr." "Dhaval" "Dalal") ; Mr Dhaval Dalal
(def new-ms (partial new-person "Ms"))

(new-ms "Ada" "Lovelace") ; Ms Ada Lovelace
• Lets partially apply title to this function…
• Lets now partially apply title and first-name
(def new-ms-ada (partial new-person "Ms" "Ada"))

(new-ms-ada "Lovelace") ; Ms Ada Lovelace
PFA in Clojure
• What if we want to fix the third arg - last name
instead of the 1st?
(def new-dalal (partial new-person salutation f-name "Dalal"))

(new-dalal "Mr" “Dhaval")
; The above code won't compile
• This is because we need placeholder for 1st and 2nd
args, which we don’t want to apply., we can’t directly
apply the 3rd argument. 

• In Clojure, with partial function application the order of
arguments matters. Its from left to right. This is just
like currying.

• So, what do we do?
Lambda to the rescue
• We wrap this in a lambda!
(def new-dalal (fn [sal fname]

(new-person sal fname "Dalal")))
(new-dalal "Mr." "Dhaval") ; Mr. Dhaval Dalal
• Doing this by hand every time is tedious!

• Fortunately, Clojure has a macro to synthesise this
kind of "ad-hoc" partial function application
(def new-dalal #(new-person %1 %2 "Dalal")) ; Mr. Dhaval Dalal

(new-dalal "Mr." "Dhaval") ; Mr. Dhaval Dalal
(def new-ada #(new-person %1 "Ada" %2))

(new-ada "Ms." "Lovelace") ; Ms Ada Lovelace

(new-ada "Mrs." "???") ; Mrs. Ada ???
Currying in Groovy
def filterList = { filter, list -> list.findAll(filter) }

def even = { it % 2 == 0 }

def evens = filterList.curry(even)

println evens(0..10) // [0, 2, 4, 6, 8, 10]



def not = { !it }

def odds = filterList.curry(even >> not) // even andThen not

println odds(0..10) // [1, 3, 5, 7, 9]
• In Groovy, we need to explicitly call the curry
method on closure!
• It curries from left to right
def merge = { x, y, z ->

println "arg0: x = $x"

println "arg1: y = $y"

println "arg2: z = $z"

"$x$y$z"

}

println merge.curry(10)('Hello', new Date()) // 10Hello<Date>

println merge.curry(10, 'Hello')(new Date()) // 10Hello<Date>
Currying in Groovy
• And if you need to curry from right-to-left, use rcurry()
def merge = { x, y, z ->

println "arg0: x = $x"

println "arg1: y = $y"

println "arg2: z = $z"

"$x$y$z"

}

println merge.rcurry(10)('Hello', new Date()) // Hello<Date>10

println merge.rcurry(10, 'Hello')(new Date()) // <Date>10Hello
• And for currying at a index, use ncurry()
println merge.ncurry(1, new Date())(10, 'Hello') //10<Date>Hello

println merge.ncurry(0, new Date(), 'Hello')(10) //<Date>Hello10
Reflections
• You curry strictly from left-to-right.

• We don’t have to provide all the arguments to the
function at one go! This is partially applying the function. 

• In other words, Currying enables Partial Function
Application, a.k.a - Partially Applied Function (PFA).

• "ad-hoc PFA" is practically more powerful than currying
in some ways. With currying, you have to curry strictly from
left to right, with PFA you can do ad-hoc application of args

• In a language that deals well with PFA, you won’t really
miss currying, because you’ll use PFA where you would
have used currying.
References
• Code Jugalbandi (http://codejugalbandi.org)

• Exploring Functional Programming - Ryan Lemmer and
Dhaval Dalal

• https://github.com/CodeJugalbandi/FunctionalProgramming/
tree/master/melodies/currying

• Healthy Code Magazine Code Jugalbandi Article 

• https://www.slideshare.net/DhavalDalal/3-code-
jugalbandicurryingpfahealthycodemagazinemar2015
Thank - You!
https://github.com/DhavalDalal/FunctionalConference-2019-Currying-PFA-Demo

More Related Content

What's hot

JavaScript Functions
JavaScript FunctionsJavaScript Functions
JavaScript FunctionsColin DeCarlo
 
Laziness, trampolines, monoids and other functional amenities: this is not yo...
Laziness, trampolines, monoids and other functional amenities: this is not yo...Laziness, trampolines, monoids and other functional amenities: this is not yo...
Laziness, trampolines, monoids and other functional amenities: this is not yo...Mario Fusco
 
Lambdas and Streams Master Class Part 2
Lambdas and Streams Master Class Part 2Lambdas and Streams Master Class Part 2
Lambdas and Streams Master Class Part 2José Paumard
 
Booting into functional programming
Booting into functional programmingBooting into functional programming
Booting into functional programmingDhaval Dalal
 
Swiss army knife Spring
Swiss army knife SpringSwiss army knife Spring
Swiss army knife SpringMario Fusco
 
LinkedIn TBC JavaScript 100: Functions
 LinkedIn TBC JavaScript 100: Functions LinkedIn TBC JavaScript 100: Functions
LinkedIn TBC JavaScript 100: FunctionsAdam Crabtree
 
If You Think You Can Stay Away from Functional Programming, You Are Wrong
If You Think You Can Stay Away from Functional Programming, You Are WrongIf You Think You Can Stay Away from Functional Programming, You Are Wrong
If You Think You Can Stay Away from Functional Programming, You Are WrongMario Fusco
 
Functional Javascript
Functional JavascriptFunctional Javascript
Functional Javascriptguest4d57e6
 
Pragmatic functional refactoring with java 8
Pragmatic functional refactoring with java 8Pragmatic functional refactoring with java 8
Pragmatic functional refactoring with java 8RichardWarburton
 
Lambda and Stream Master class - part 1
Lambda and Stream Master class - part 1Lambda and Stream Master class - part 1
Lambda and Stream Master class - part 1José Paumard
 
Java 7, 8 & 9 - Moving the language forward
Java 7, 8 & 9 - Moving the language forwardJava 7, 8 & 9 - Moving the language forward
Java 7, 8 & 9 - Moving the language forwardMario Fusco
 
Refactoring to Java 8 (Devoxx BE)
Refactoring to Java 8 (Devoxx BE)Refactoring to Java 8 (Devoxx BE)
Refactoring to Java 8 (Devoxx BE)Trisha Gee
 
Object Design - Part 1
Object Design - Part 1Object Design - Part 1
Object Design - Part 1Dhaval Dalal
 
JavaScript Functions
JavaScript FunctionsJavaScript Functions
JavaScript FunctionsBrian Moschel
 
Reactive Programming for a demanding world: building event-driven and respons...
Reactive Programming for a demanding world: building event-driven and respons...Reactive Programming for a demanding world: building event-driven and respons...
Reactive Programming for a demanding world: building event-driven and respons...Mario Fusco
 
Leveraging Completable Futures to handle your query results Asynchrhonously
Leveraging Completable Futures to handle your query results AsynchrhonouslyLeveraging Completable Futures to handle your query results Asynchrhonously
Leveraging Completable Futures to handle your query results AsynchrhonouslyDavid Gómez García
 
Java script advance-auroskills (2)
Java script advance-auroskills (2)Java script advance-auroskills (2)
Java script advance-auroskills (2)BoneyGawande
 

What's hot (20)

JavaScript Functions
JavaScript FunctionsJavaScript Functions
JavaScript Functions
 
Laziness, trampolines, monoids and other functional amenities: this is not yo...
Laziness, trampolines, monoids and other functional amenities: this is not yo...Laziness, trampolines, monoids and other functional amenities: this is not yo...
Laziness, trampolines, monoids and other functional amenities: this is not yo...
 
Lambdas and Streams Master Class Part 2
Lambdas and Streams Master Class Part 2Lambdas and Streams Master Class Part 2
Lambdas and Streams Master Class Part 2
 
Booting into functional programming
Booting into functional programmingBooting into functional programming
Booting into functional programming
 
Swiss army knife Spring
Swiss army knife SpringSwiss army knife Spring
Swiss army knife Spring
 
LinkedIn TBC JavaScript 100: Functions
 LinkedIn TBC JavaScript 100: Functions LinkedIn TBC JavaScript 100: Functions
LinkedIn TBC JavaScript 100: Functions
 
If You Think You Can Stay Away from Functional Programming, You Are Wrong
If You Think You Can Stay Away from Functional Programming, You Are WrongIf You Think You Can Stay Away from Functional Programming, You Are Wrong
If You Think You Can Stay Away from Functional Programming, You Are Wrong
 
Functional Javascript
Functional JavascriptFunctional Javascript
Functional Javascript
 
Pragmatic functional refactoring with java 8
Pragmatic functional refactoring with java 8Pragmatic functional refactoring with java 8
Pragmatic functional refactoring with java 8
 
Lambda and Stream Master class - part 1
Lambda and Stream Master class - part 1Lambda and Stream Master class - part 1
Lambda and Stream Master class - part 1
 
Java 7, 8 & 9 - Moving the language forward
Java 7, 8 & 9 - Moving the language forwardJava 7, 8 & 9 - Moving the language forward
Java 7, 8 & 9 - Moving the language forward
 
Refactoring to Java 8 (Devoxx BE)
Refactoring to Java 8 (Devoxx BE)Refactoring to Java 8 (Devoxx BE)
Refactoring to Java 8 (Devoxx BE)
 
Object Design - Part 1
Object Design - Part 1Object Design - Part 1
Object Design - Part 1
 
JavaScript Functions
JavaScript FunctionsJavaScript Functions
JavaScript Functions
 
Reactive Programming for a demanding world: building event-driven and respons...
Reactive Programming for a demanding world: building event-driven and respons...Reactive Programming for a demanding world: building event-driven and respons...
Reactive Programming for a demanding world: building event-driven and respons...
 
Leveraging Completable Futures to handle your query results Asynchrhonously
Leveraging Completable Futures to handle your query results AsynchrhonouslyLeveraging Completable Futures to handle your query results Asynchrhonously
Leveraging Completable Futures to handle your query results Asynchrhonously
 
Java script advance-auroskills (2)
Java script advance-auroskills (2)Java script advance-auroskills (2)
Java script advance-auroskills (2)
 
Clean code slide
Clean code slideClean code slide
Clean code slide
 
Sneaking inside Kotlin features
Sneaking inside Kotlin featuresSneaking inside Kotlin features
Sneaking inside Kotlin features
 
Pragmatic sbt
Pragmatic sbtPragmatic sbt
Pragmatic sbt
 

Similar to Currying and Partial Function Application (PFA)

Introduction to nsubstitute
Introduction to nsubstituteIntroduction to nsubstitute
Introduction to nsubstituteSuresh Loganatha
 
Finagle and Java Service Framework at Pinterest
Finagle and Java Service Framework at PinterestFinagle and Java Service Framework at Pinterest
Finagle and Java Service Framework at PinterestPavan Chitumalla
 
What is new in java 8 concurrency
What is new in java 8 concurrencyWhat is new in java 8 concurrency
What is new in java 8 concurrencykshanth2101
 
Part 3-functions1-120315220356-phpapp01
Part 3-functions1-120315220356-phpapp01Part 3-functions1-120315220356-phpapp01
Part 3-functions1-120315220356-phpapp01Abdul Samee
 
Столпы функционального программирования для адептов ООП, Николай Мозговой
Столпы функционального программирования для адептов ООП, Николай МозговойСтолпы функционального программирования для адептов ООП, Николай Мозговой
Столпы функционального программирования для адептов ООП, Николай МозговойSigma Software
 
Php Reusing Code And Writing Functions
Php Reusing Code And Writing FunctionsPhp Reusing Code And Writing Functions
Php Reusing Code And Writing Functionsmussawir20
 
php user defined functions
php user defined functionsphp user defined functions
php user defined functionsvishnupriyapm4
 
From object oriented to functional domain modeling
From object oriented to functional domain modelingFrom object oriented to functional domain modeling
From object oriented to functional domain modelingCodemotion
 
Thinking Functionally with JavaScript
Thinking Functionally with JavaScriptThinking Functionally with JavaScript
Thinking Functionally with JavaScriptLuis Atencio
 
Classes function overloading
Classes function overloadingClasses function overloading
Classes function overloadingankush_kumar
 
Tools for Making Machine Learning more Reactive
Tools for Making Machine Learning more ReactiveTools for Making Machine Learning more Reactive
Tools for Making Machine Learning more ReactiveJeff Smith
 

Similar to Currying and Partial Function Application (PFA) (20)

Introduction to nsubstitute
Introduction to nsubstituteIntroduction to nsubstitute
Introduction to nsubstitute
 
Finagle and Java Service Framework at Pinterest
Finagle and Java Service Framework at PinterestFinagle and Java Service Framework at Pinterest
Finagle and Java Service Framework at Pinterest
 
25-functions.ppt
25-functions.ppt25-functions.ppt
25-functions.ppt
 
Cocoa heads 09112017
Cocoa heads 09112017Cocoa heads 09112017
Cocoa heads 09112017
 
What is new in java 8 concurrency
What is new in java 8 concurrencyWhat is new in java 8 concurrency
What is new in java 8 concurrency
 
Celery with python
Celery with pythonCelery with python
Celery with python
 
Part 3-functions1-120315220356-phpapp01
Part 3-functions1-120315220356-phpapp01Part 3-functions1-120315220356-phpapp01
Part 3-functions1-120315220356-phpapp01
 
Столпы функционального программирования для адептов ООП, Николай Мозговой
Столпы функционального программирования для адептов ООП, Николай МозговойСтолпы функционального программирования для адептов ООП, Николай Мозговой
Столпы функционального программирования для адептов ООП, Николай Мозговой
 
Php Reusing Code And Writing Functions
Php Reusing Code And Writing FunctionsPhp Reusing Code And Writing Functions
Php Reusing Code And Writing Functions
 
php user defined functions
php user defined functionsphp user defined functions
php user defined functions
 
Functional programming 101
Functional programming 101Functional programming 101
Functional programming 101
 
From object oriented to functional domain modeling
From object oriented to functional domain modelingFrom object oriented to functional domain modeling
From object oriented to functional domain modeling
 
Function & Recursion
Function & RecursionFunction & Recursion
Function & Recursion
 
Licão 13 functions
Licão 13 functionsLicão 13 functions
Licão 13 functions
 
Thinking Functionally with JavaScript
Thinking Functionally with JavaScriptThinking Functionally with JavaScript
Thinking Functionally with JavaScript
 
Test driven development_for_php
Test driven development_for_phpTest driven development_for_php
Test driven development_for_php
 
Classes function overloading
Classes function overloadingClasses function overloading
Classes function overloading
 
Fp201 unit5 1
Fp201 unit5 1Fp201 unit5 1
Fp201 unit5 1
 
Tools for Making Machine Learning more Reactive
Tools for Making Machine Learning more ReactiveTools for Making Machine Learning more Reactive
Tools for Making Machine Learning more Reactive
 
Function C++
Function C++ Function C++
Function C++
 

More from Dhaval Dalal

Test Pyramid in Microservices Context
Test Pyramid in Microservices ContextTest Pyramid in Microservices Context
Test Pyramid in Microservices ContextDhaval Dalal
 
Json Viewer Stories
Json Viewer StoriesJson Viewer Stories
Json Viewer StoriesDhaval Dalal
 
Mars rover-extension
Mars rover-extensionMars rover-extension
Mars rover-extensionDhaval Dalal
 
How Is Homeopathy Near To Yoga?
How Is Homeopathy Near To Yoga?How Is Homeopathy Near To Yoga?
How Is Homeopathy Near To Yoga?Dhaval Dalal
 
Approaching ATDD/BDD
Approaching ATDD/BDDApproaching ATDD/BDD
Approaching ATDD/BDDDhaval Dalal
 
Paradigms Code jugalbandi
Paradigms Code jugalbandiParadigms Code jugalbandi
Paradigms Code jugalbandiDhaval Dalal
 
Data Reconciliation
Data ReconciliationData Reconciliation
Data ReconciliationDhaval Dalal
 
4-Code-Jugalbandi-destructuring-patternmatching-healthycode#apr2015
4-Code-Jugalbandi-destructuring-patternmatching-healthycode#apr20154-Code-Jugalbandi-destructuring-patternmatching-healthycode#apr2015
4-Code-Jugalbandi-destructuring-patternmatching-healthycode#apr2015Dhaval Dalal
 
3-CodeJugalbandi-currying-pfa-healthycodemagazine#mar2015
3-CodeJugalbandi-currying-pfa-healthycodemagazine#mar20153-CodeJugalbandi-currying-pfa-healthycodemagazine#mar2015
3-CodeJugalbandi-currying-pfa-healthycodemagazine#mar2015Dhaval Dalal
 
CodeJugalbandi-Sequencing-HealthyCode-Magazine-Feb-2015
CodeJugalbandi-Sequencing-HealthyCode-Magazine-Feb-2015CodeJugalbandi-Sequencing-HealthyCode-Magazine-Feb-2015
CodeJugalbandi-Sequencing-HealthyCode-Magazine-Feb-2015Dhaval Dalal
 
CodeJugalbandi-Expression-Problem-HealthyCode-Magazine#Jan-2015-Issue
CodeJugalbandi-Expression-Problem-HealthyCode-Magazine#Jan-2015-IssueCodeJugalbandi-Expression-Problem-HealthyCode-Magazine#Jan-2015-Issue
CodeJugalbandi-Expression-Problem-HealthyCode-Magazine#Jan-2015-IssueDhaval Dalal
 
The tao-of-transformation-workshop
The tao-of-transformation-workshopThe tao-of-transformation-workshop
The tao-of-transformation-workshopDhaval Dalal
 
Grooming with Groovy
Grooming with GroovyGrooming with Groovy
Grooming with GroovyDhaval Dalal
 
Language portfolio
Language portfolioLanguage portfolio
Language portfolioDhaval Dalal
 
A case-for-graph-db
A case-for-graph-dbA case-for-graph-db
A case-for-graph-dbDhaval Dalal
 
Transition contours
Transition contoursTransition contours
Transition contoursDhaval Dalal
 

More from Dhaval Dalal (20)

Test Pyramid in Microservices Context
Test Pyramid in Microservices ContextTest Pyramid in Microservices Context
Test Pyramid in Microservices Context
 
Code Retreat
Code RetreatCode Retreat
Code Retreat
 
Json Viewer Stories
Json Viewer StoriesJson Viewer Stories
Json Viewer Stories
 
Value Objects
Value ObjectsValue Objects
Value Objects
 
Mars rover-extension
Mars rover-extensionMars rover-extension
Mars rover-extension
 
How Is Homeopathy Near To Yoga?
How Is Homeopathy Near To Yoga?How Is Homeopathy Near To Yoga?
How Is Homeopathy Near To Yoga?
 
Approaching ATDD/BDD
Approaching ATDD/BDDApproaching ATDD/BDD
Approaching ATDD/BDD
 
Paradigms Code jugalbandi
Paradigms Code jugalbandiParadigms Code jugalbandi
Paradigms Code jugalbandi
 
Data Reconciliation
Data ReconciliationData Reconciliation
Data Reconciliation
 
CodeRetreat
CodeRetreatCodeRetreat
CodeRetreat
 
4-Code-Jugalbandi-destructuring-patternmatching-healthycode#apr2015
4-Code-Jugalbandi-destructuring-patternmatching-healthycode#apr20154-Code-Jugalbandi-destructuring-patternmatching-healthycode#apr2015
4-Code-Jugalbandi-destructuring-patternmatching-healthycode#apr2015
 
3-CodeJugalbandi-currying-pfa-healthycodemagazine#mar2015
3-CodeJugalbandi-currying-pfa-healthycodemagazine#mar20153-CodeJugalbandi-currying-pfa-healthycodemagazine#mar2015
3-CodeJugalbandi-currying-pfa-healthycodemagazine#mar2015
 
CodeJugalbandi-Sequencing-HealthyCode-Magazine-Feb-2015
CodeJugalbandi-Sequencing-HealthyCode-Magazine-Feb-2015CodeJugalbandi-Sequencing-HealthyCode-Magazine-Feb-2015
CodeJugalbandi-Sequencing-HealthyCode-Magazine-Feb-2015
 
CodeJugalbandi-Expression-Problem-HealthyCode-Magazine#Jan-2015-Issue
CodeJugalbandi-Expression-Problem-HealthyCode-Magazine#Jan-2015-IssueCodeJugalbandi-Expression-Problem-HealthyCode-Magazine#Jan-2015-Issue
CodeJugalbandi-Expression-Problem-HealthyCode-Magazine#Jan-2015-Issue
 
The tao-of-transformation-workshop
The tao-of-transformation-workshopThe tao-of-transformation-workshop
The tao-of-transformation-workshop
 
Grooming with Groovy
Grooming with GroovyGrooming with Groovy
Grooming with Groovy
 
Language portfolio
Language portfolioLanguage portfolio
Language portfolio
 
Code jugalbandi
Code jugalbandiCode jugalbandi
Code jugalbandi
 
A case-for-graph-db
A case-for-graph-dbA case-for-graph-db
A case-for-graph-db
 
Transition contours
Transition contoursTransition contours
Transition contours
 

Recently uploaded

WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...WSO2
 
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 2024VictoriaMetrics
 
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...WSO2
 
WSO2Con2024 - Hello Choreo Presentation - Kanchana
WSO2Con2024 - Hello Choreo Presentation - KanchanaWSO2Con2024 - Hello Choreo Presentation - Kanchana
WSO2Con2024 - Hello Choreo Presentation - KanchanaWSO2
 
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...WSO2
 
WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...
WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...
WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...WSO2
 
WSO2Con204 - Hard Rock Presentation - Keynote
WSO2Con204 - Hard Rock Presentation - KeynoteWSO2Con204 - Hard Rock Presentation - Keynote
WSO2Con204 - Hard Rock Presentation - KeynoteWSO2
 
%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 midrandmasabamasaba
 
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...Bert Jan Schrijver
 
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.pptxAnnaArtyushina1
 
%+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
 
%in Benoni+277-882-255-28 abortion pills for sale in Benoni
%in Benoni+277-882-255-28 abortion pills for sale in Benoni%in Benoni+277-882-255-28 abortion pills for sale in Benoni
%in Benoni+277-882-255-28 abortion pills for sale in Benonimasabamasaba
 
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...Shane Coughlan
 
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...WSO2
 
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...masabamasaba
 
Announcing Codolex 2.0 from GDK Software
Announcing Codolex 2.0 from GDK SoftwareAnnouncing Codolex 2.0 from GDK Software
Announcing Codolex 2.0 from GDK SoftwareJim McKeeth
 
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-learnAmarnathKambale
 
AI & Machine Learning Presentation Template
AI & Machine Learning Presentation TemplateAI & Machine Learning Presentation Template
AI & Machine Learning Presentation TemplatePresentation.STUDIO
 
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...WSO2
 

Recently uploaded (20)

WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
 
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
 
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...
 
WSO2Con2024 - Hello Choreo Presentation - Kanchana
WSO2Con2024 - Hello Choreo Presentation - KanchanaWSO2Con2024 - Hello Choreo Presentation - Kanchana
WSO2Con2024 - Hello Choreo Presentation - Kanchana
 
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...
 
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...
 
WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...
WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...
WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...
 
WSO2Con204 - Hard Rock Presentation - Keynote
WSO2Con204 - Hard Rock Presentation - KeynoteWSO2Con204 - Hard Rock Presentation - Keynote
WSO2Con204 - Hard Rock Presentation - Keynote
 
%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
 
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...
 
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
 
%+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...
 
%in Benoni+277-882-255-28 abortion pills for sale in Benoni
%in Benoni+277-882-255-28 abortion pills for sale in Benoni%in Benoni+277-882-255-28 abortion pills for sale in Benoni
%in Benoni+277-882-255-28 abortion pills for sale in Benoni
 
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
 
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
 
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
 
Announcing Codolex 2.0 from GDK Software
Announcing Codolex 2.0 from GDK SoftwareAnnouncing Codolex 2.0 from GDK Software
Announcing Codolex 2.0 from GDK Software
 
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
 
AI & Machine Learning Presentation Template
AI & Machine Learning Presentation TemplateAI & Machine Learning Presentation Template
AI & Machine Learning Presentation Template
 
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...
 

Currying and Partial Function Application (PFA)

  • 1. Making Your Program Spicy Currying and Partial Function Application (PFA) Dhaval Dalal @softwareartisan https://dhavaldalal.wordpress.com 14th Nov 2019
  • 2. • Refers to the phenomena of rewriting a N-arg function to a nest of functions, each taking only 1-arg at a time Currying // (String, Integer) -> String
 String merge(String x, Integer y) {
 return x + y.toString();
 }
 // String -> (Integer -> String)
 Function<Integer, String> merge(String x) {
 return y -> x + y.toString();
 }
 // () -> (String -> (Integer -> String))
 Function<String, Function<Integer, String>> merge() {
 return x -> y -> x + y.toString();
 } // (String -> (Integer -> String))
 Function<String, Function<Integer, String>> merge = x -> y -> x + y.toString();
 System.out.println(merge("Test#", 1)); // Test#1
 System.out.println(merge("Test#").apply(2)); // Test#2
 System.out.println(merge().apply("Test#").apply(3)); // Test#3 System.out.println(merge.apply("Test#").apply(4)); // Test#4
  • 3. Currying For each arg, there is another nested function, that takes a arg and returns a function taking the subsequent arg, until all the args are exhausted. f : (T, U, V) ↦ R f′ : T ↦ U ↦ V ↦ R f = f′ • Curried function is a nested structure, just like Russian dolls, takes one arg at a time, instead of all the args at once.
  • 4. Currying • Function type associates towards right. • In other words, arrow groups towards right. Function<String, Function<Integer, String>> merge = 
 x -> y -> x + y.toString(); x -> y -> x + y.toString(); // is same as x -> (y -> x + y.toString()); • Function application associates towards left. In other words, apply() groups towards left. merge.apply("Test#").apply(1); // is same as (merge.apply("Test#")).apply(1);
  • 5. Why Currying? • Facilitates arguments to be applied from different scopes. Function<Integer, Function<Integer, Integer>> add = x -> y -> x + y; Function<Integer, Integer> increment = add.apply(1); increment.apply(2); // 3 Function<Integer, Integer> decrement = add.apply(-1); decrement.apply(2); // 1 • Helps us reshape and re-purpose the original function by creating a partially applied function from it Function<Integer, Function<Integer, Integer>> add = x -> y -> x + y; Scope 1 Scope 2
  • 6. But, how does that make programming spicier?
  • 7. • Let’s say we have a Customer repository. • Now, we want to allow authorised calls to repo. So, Let’s write an authorise function. class CustomerRepository {
 Optional<Customer> findById(Integer id) {
 return (id > 0) ? Optional.of(new Customer(id)) 
 : Optional.empty();
 } 
 } class Authoriser {
 public Optional<Customer> authorise(CustomerRepository repo, Request request) {
 System.out.println("Authorizing Request#" + request.id);
 // Some auth code here which guards the request.
 // On success, the line below is executed.
 return repo.findById(Integer.parseInt(request.get("customer_id")));
 }
 }
  • 8. • We also have a Request. • Lets see them in action… class Request {
 public final int id;
 private Map<String, String> params = new HashMap<>();
 
 Request(int id) { this.id = id; }
 String set(String key, String value) { return params.put(key, value); } 
 String get(String key) { return params.get(key); }
 } var authoriser = new Authoriser();
 var repo = new CustomerRepository();
 
 var request1 = new Request(1) {{ set("customer_id", "10"); }};
 
 var customer1 = authoriser.authorise(repo, request1);
 System.out.println(customer1);
 
 var request2 = new Request(2) {{ set("customer_id", "30"); }};
 var customer2 = authoriser.authorise(repo, request2);
 System.out.println(customer2);
  • 9. • Requests vary, however the CustomerRepository is same. • Can we avoid repeated injection of the repo? Solution 1 Optional<Customer> authorise(Request req) { CustomerRepository repo = new CustomerRepository(); return repo.findById(req.get()); } Authoriser authoriser = new Authoriser(); Request req1 = new Request(); var customer1 = authoriser.authorise(req1); Request req2 = new Request(); var customer2 = authoriser.authorise(req2); • Wrap the authorise function in another function (also called authorise)
  • 10. • Requests vary, however the CustomerRepository is same. • Can we avoid repeated injection of the repo? Solution 1 Optional<Customer> authorise(Request req) { CustomerRepository repo = new CustomerRepository(); return repo.findById(req.get()); } Authoriser authoriser = new Authoriser(); Request req1 = new Request(); var customer1 = authoriser.authorise(req1); Request req2 = new Request(); var customer2 = authoriser.authorise(req2); But newification locally like this is untestable! • Wrap the authorise function in another function (also called authorise)
  • 11. Solution 2 class Authoriser { public Function<Request, Optional<Customer>> authorise(CustomerRepository repo) { return req -> { //Some auth code here which guards the request. repo.findById(req.get()); } } } var repo = new CustomerRepository(); Function<Request, Optional<Customer>> curriedAuthorise = authorise(repo); Request req1 = new Request(); var customer1 = curriedAuthorise.apply(req1); Request req2 = new Request(); var customer2 = curriedAuthorise.apply(req2); • Re-shape authorise to accept only one fixed parameter - CustomerRepository
  • 13. interface Transaction { } interface ApprovalStrategy { boolean approve(List<Transaction> ts); //… } class Clearing { private final ApprovalStrategy as; Clearing(ApprovalStrategy as) { this.as = as; } public boolean approve(List<Transaction> ts) { return as.approve(ts); } } //main ApprovalStrategy singleMakerChecker = new SingleMakerChecker(); Clearing clearing = new Clearing(singleMakerChecker); clearing.approve(ts); Regular DI
  • 14. Curried DI interface Transaction { } interface ApprovalStrategy { boolean approve(List<Transaction> ts); //… } class Clearing { public Function<List<Transaction>, Boolean> approve(ApprovalStrategy as) { return ts -> as.approve(ts); } } //main Clearing clearing = new Clearing(); // ApprovalStrategy can now be injected from different contexts, // one for production and a different one - say mock for testing, // Just like in case of Regular DI. clearing.approve(new SingleMakerChecker()).apply(ts);
  • 15. Making Our Own Curry <T, U, R> Function<T, Function<U, R>> curry(BiFunction<T, U, R> fn) { return t -> u -> fn.apply(t, u); } // Function with all args applied at the same time. BiFunction<Integer, Integer, Integer> add = (x, y) -> x + y; // Curried Function - one arg at a time. Function<Integer, Function<Integer, Integer>> cAdd = curry(add); Function<Integer, Integer> increment = cAdd.apply(1); increment.apply(2); // 3 Function<Integer, Integer> decrement = cAdd.apply(-1); decrement.apply(2); // 1 It would be nice if Java8 provided this out-of-box on BiFunction Scala calls this curried
  • 16. Uncurry or Tuple it! <T, U, R> BiFunction<T, U, R> uncurry(Function<T, Function<U, R>> fn) { return (t, u) -> fn.apply(t).apply(u); } // Curried Function - one arg at a time. Function<Integer, Function<Integer, Integer>> add = x -> y -> x + y; // Function with all args applied at the same time. BiFunction<Integer, Integer, Integer> ucAdd = uncurry(add); ucAdd.apply(2, 3); // 5 It would be nice if Java8 provided this out-of-box on Function Scala calls this uncurried
  • 17. Currying in Scala scala> def merge1(x: String, y: Int) = x + y.toString merge1: (x: String, y: Int)String scala> val merge1F = merge1 _ merge1F: (String, Int) => String scala> def merge2(x: String)(y: Int) = x + y.toString
 scala> val merge2F = merge2 _ merge2F: String => (Int => String) scala> val mergeTest = merge2F("Test#") mergeTest: Int => String scala> mergeTest(1) res1: Test#1 scala> mergeTest(2) res2: Test#2 • Scala uses special syntax for currying - It does not use tupled arguments, instead uses multiple function call syntax in the definition to denote a curried function.
  • 18. Curry Uncurry scala> def merge1(x: String, y: Int) = x + y.toString merge1: (x: String, y: Int)String scala> val merge1F = merge1 _ merge1F: (String, Int) => String scala> val merge1FCurried = merge1F.curried merge1FCurried: String => (Int => String) scala> def merge2(x: String)(y: Int) = x + y.toString
 scala> val merge2F = merge2 _ merge2F: String => (Int => String) scala> val merge2FUncurried = Function.uncurried(merge2F) merge2FUncurried: (String, Int) => String Scala
  • 19. PFA in Scala // Partially Applied Function or Partial Function Application (PFA)
 def greet(salutation: String, fname: String, lname: String) = s"$salutation. $fname $lname"
 println(greet("Mr", "Dhaval", "Dalal")) // Mr Dhaval Dalal def new_ms = greet("Ms", _: String, _: String) // (String, String) => String
 println(new_ms("Ada", "Lovelace")) // Ms Ada Lovelace
 
 def new_drew = greet(_: String, _: String, "Drew")
 (String, String) => String println(new_drew("Ms", "Nancy")) // Ms Nancy Drew • Supply a value to partially apply the function and to leave out the arguments unapplied, use underscore “_” • Note: PFA is different from Partial Function
  • 20. Re-shaping Third Party Library Functions • In third-party libraries we may never be able to modify the code. • Use Currying/PFA to simplify the callers interface. def power(n: Double) = Math.pow(_: Double, n)
 val square = power(2)
 println(square(2)) // 4.0
 
 val cube = power(3)
 println(cube(2)) // 8.0
  • 21. Currying in Haskell greet :: String -> String -> String -> String
 greet salutation fname lname = salutation ++ ". " ++ fname ++ " " ++ lname
 
 main :: IO ()
 main = do
 print $ greet "Mr" "Dhaval" "Dalal" -- Mr Dhaval Dalal
 let greet_mr = greet "Mr"
 print (greet_mr "Joe" "Shmo") -- Mr Joe Shmo
 let greet_mr_joe = greet "Mr" "Joe"
 print (greet_mr_joe "Sober") -- Mr Joe Sober
 print "Done!" • In Haskell, all the functions are curried by default, you don’t need special syntax for that. • It does not have Partially Applied Functions.
  • 22. Currying in Haskell Prelude> :type (*) (*) :: Num a => a -> a -> a Prelude> multiply2 = (*2) Prelude> :type multiply2 multiplyBy2 :: Num a => a -> a Prelude> multiply2 3 6 • Even operators are curried by default. Prelude> :type filter filter :: (a -> Bool) -> [a] -> [a] Prelude> even = x -> x `mod` 2 == 0 Prelude> filterEvens = filter even Prelude> :type filterEvens filterEvens :: Integral a => [a] -> [a] Prelude> filterEvens [0..10] [2,4,6,8,10] Prelude> filterOdds = filter (not . even) Prelude> filterOdds [0..10] [1,3,5,7,9] • Yet another example…
  • 23. PFA in Clojure (defn new-person [salutation f-name l-name]
 (println salutation f-name l-name))
 
 (new-person "Mr." "Dhaval" "Dalal") ; Mr Dhaval Dalal (def new-ms (partial new-person "Ms"))
 (new-ms "Ada" "Lovelace") ; Ms Ada Lovelace • Lets partially apply title to this function… • Lets now partially apply title and first-name (def new-ms-ada (partial new-person "Ms" "Ada"))
 (new-ms-ada "Lovelace") ; Ms Ada Lovelace
  • 24. PFA in Clojure • What if we want to fix the third arg - last name instead of the 1st? (def new-dalal (partial new-person salutation f-name "Dalal"))
 (new-dalal "Mr" “Dhaval") ; The above code won't compile • This is because we need placeholder for 1st and 2nd args, which we don’t want to apply., we can’t directly apply the 3rd argument. • In Clojure, with partial function application the order of arguments matters. Its from left to right. This is just like currying. • So, what do we do?
  • 25. Lambda to the rescue • We wrap this in a lambda! (def new-dalal (fn [sal fname]
 (new-person sal fname "Dalal"))) (new-dalal "Mr." "Dhaval") ; Mr. Dhaval Dalal • Doing this by hand every time is tedious! • Fortunately, Clojure has a macro to synthesise this kind of "ad-hoc" partial function application (def new-dalal #(new-person %1 %2 "Dalal")) ; Mr. Dhaval Dalal
 (new-dalal "Mr." "Dhaval") ; Mr. Dhaval Dalal (def new-ada #(new-person %1 "Ada" %2))
 (new-ada "Ms." "Lovelace") ; Ms Ada Lovelace
 (new-ada "Mrs." "???") ; Mrs. Ada ???
  • 26. Currying in Groovy def filterList = { filter, list -> list.findAll(filter) }
 def even = { it % 2 == 0 }
 def evens = filterList.curry(even)
 println evens(0..10) // [0, 2, 4, 6, 8, 10]
 
 def not = { !it }
 def odds = filterList.curry(even >> not) // even andThen not
 println odds(0..10) // [1, 3, 5, 7, 9] • In Groovy, we need to explicitly call the curry method on closure! • It curries from left to right def merge = { x, y, z ->
 println "arg0: x = $x"
 println "arg1: y = $y"
 println "arg2: z = $z"
 "$x$y$z"
 }
 println merge.curry(10)('Hello', new Date()) // 10Hello<Date>
 println merge.curry(10, 'Hello')(new Date()) // 10Hello<Date>
  • 27. Currying in Groovy • And if you need to curry from right-to-left, use rcurry() def merge = { x, y, z ->
 println "arg0: x = $x"
 println "arg1: y = $y"
 println "arg2: z = $z"
 "$x$y$z"
 }
 println merge.rcurry(10)('Hello', new Date()) // Hello<Date>10
 println merge.rcurry(10, 'Hello')(new Date()) // <Date>10Hello • And for currying at a index, use ncurry() println merge.ncurry(1, new Date())(10, 'Hello') //10<Date>Hello
 println merge.ncurry(0, new Date(), 'Hello')(10) //<Date>Hello10
  • 28. Reflections • You curry strictly from left-to-right. • We don’t have to provide all the arguments to the function at one go! This is partially applying the function. • In other words, Currying enables Partial Function Application, a.k.a - Partially Applied Function (PFA). • "ad-hoc PFA" is practically more powerful than currying in some ways. With currying, you have to curry strictly from left to right, with PFA you can do ad-hoc application of args • In a language that deals well with PFA, you won’t really miss currying, because you’ll use PFA where you would have used currying.
  • 29. References • Code Jugalbandi (http://codejugalbandi.org) • Exploring Functional Programming - Ryan Lemmer and Dhaval Dalal • https://github.com/CodeJugalbandi/FunctionalProgramming/ tree/master/melodies/currying • Healthy Code Magazine Code Jugalbandi Article • https://www.slideshare.net/DhavalDalal/3-code- jugalbandicurryingpfahealthycodemagazinemar2015