You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
@@ -18,7 +21,7 @@ Currying decomposes a function that takes multiple arguments into a sequence of
18
21
19
22
Real-world example
20
23
21
-
> Consider a librarian who wants to populate their library with books. The librarian wants functions which can create books corresponding to specific genres and authors. Currying makes this possible by writing a curried book builder function and utilising partial application.
24
+
> Currying in programming can be compared to an assembly line in a factory. Imagine a car manufacturing process where each station on the assembly line performs a specific task, such as installing the engine, painting the car, and adding the wheels. Each station takes a partially completed car and performs a single operation before passing it to the next station. Similarly, in currying, a function that requires multiple arguments is broken down into a series of functions, each taking a single argument and returning another function until all arguments are provided. This step-by-step processing simplifies complex tasks by dividing them into manageable, sequential operations.
22
25
23
26
In plain words
24
27
@@ -28,7 +31,9 @@ Wikipedia says
28
31
29
32
> In mathematics and computer science, currying is the technique of translating a function that takes multiple arguments into a sequence of families of functions, each taking a single argument.
30
33
31
-
Programmatic example
34
+
**Programmatic example**
35
+
36
+
Consider a librarian who wants to populate their library with books. The librarian wants functions which can create books corresponding to specific genres and authors. Currying makes this possible by writing a curried book builder function and utilising partial application.
32
37
33
38
We have a `Book` class and `Genre` enum.
34
39
@@ -50,58 +55,78 @@ public class Book {
50
55
publicenumGenre {
51
56
FANTASY,
52
57
HORROR,
53
-
SCI_FI;
58
+
SCI_FI
54
59
}
55
60
```
56
61
57
62
We could easily create a `Book` object with the following method:
58
63
59
64
```java
60
-
Book createBook(Genre genre,String author,String title,LocalDate publicationDate){
However, what if we only wanted to create books from the `FANTASY` genre? We could pass in the `FANTASY` parameter on each method call; however, this is repetitive. We could define a new method specifically for creating `FANTASY` books; however, it is infeasible to create a new method for each book genre. The solution is to create a curried function.
70
+
However, what if we only wanted to create books from the `FANTASY` genre? Passing the `FANTASY` parameter with each method call would be repetitive. Alternatively, we could define a new method specifically for creating `FANTASY` books, but it would be impractical to create a separate method for each genre. The solution is to use a curried function.
Note that the order of the parameters is important. `genre` must come before `author`, `author` must come before `title` and so on. We must be considerate of this when writing curried functions to take full advantage of partial application. Using the above function, we can define a new function `fantasyBookFunc`, to generate `FANTASY` books as follows:
Unfortunately, the type signature of `BOOK_CREATOR` and `fantasyBookFunc` are difficult to read and understand. We can improve this by using the [builder pattern](https://java-design-patterns.com/patterns/builder/) and [functional interfaces](https://www.geeksforgeeks.org/functional-interfaces-java/#:~:text=A%20functional%20interface%20is%20an,any%20number%20of%20default%20methods).
90
+
Unfortunately, the type signature of `BOOK_CREATOR` and `fantasyBookFunc` are difficult to read and understand. We can improve this by using the [builder pattern](https://java-design-patterns.com/patterns/builder/) and functional interfaces.
83
91
84
92
```java
85
-
publicstaticAddGenre builder(){
86
-
return genre
87
-
->author
88
-
->title
89
-
->publicationDate
90
-
->newBook(genre,author,title,publicationDate);
91
-
}
92
93
94
+
/**
95
+
* Implements the builder pattern using functional interfaces to create a more readable book
96
+
* creator function. This function is equivalent to the BOOK_CREATOR function.
97
+
*/
98
+
publicstaticAddGenre builder() {
99
+
return genre
100
+
-> author
101
+
-> title
102
+
-> publicationDate
103
+
->newBook(genre, author, title, publicationDate);
104
+
}
105
+
106
+
/**
107
+
* Functional interface which adds the genre to a book.
108
+
*/
93
109
publicinterfaceAddGenre {
94
110
Book.AddAuthorwithGenre(Genregenre);
95
111
}
96
112
113
+
/**
114
+
* Functional interface which adds the author to a book.
115
+
*/
97
116
publicinterfaceAddAuthor {
98
117
Book.AddTitlewithAuthor(Stringauthor);
99
118
}
100
119
120
+
/**
121
+
* Functional interface which adds the title to a book.
122
+
*/
101
123
publicinterfaceAddTitle {
102
124
Book.AddPublicationDatewithTitle(Stringtitle);
103
125
}
104
126
127
+
/**
128
+
* Functional interface which adds the publication date to a book.
@@ -110,83 +135,89 @@ public interface AddPublicationDate {
110
135
The semantics of the `builder` function can easily be understood. The `builder` function returns a function `AddGenre`, which adds the genre to the book. Similarity, the `AddGenre` function returns another function `AddTitle`, which adds the title to the book and so on, until the `AddPublicationDate` function returns a `Book`. For example, we could create a `Book` as follows:
111
136
112
137
```java
113
-
Book book=Book.builder().withGenre(Genre.FANTASY)
114
-
.withAuthor("Author")
115
-
.withTitle("Title")
116
-
.withPublicationDate(LocalDate.of(2000,7,2));
138
+
Book book=Book.builder().withGenre(Genre.FANTASY)
139
+
.withAuthor("Author")
140
+
.withTitle("Title")
141
+
.withPublicationDate(LocalDate.of(2000,7, 2));
117
142
```
118
143
119
144
The below example demonstrates how partial application can be used with the `builder` function to create specialised book builder functions.
09:04:52.506 [main] INFO com.iluwatar.currying.App -- Book{genre=FANTASY, author='Stephen King', title='The Dark Tower: Gunslinger', publicationDate=1982-06-10}
198
+
09:04:52.506 [main] INFO com.iluwatar.currying.App -- J.K. Rowling Books:
199
+
09:04:52.506 [main] INFO com.iluwatar.currying.App -- Book{genre=FANTASY, author='J.K. Rowling', title='Harry Potter and the Chamber of Secrets', publicationDate=1998-07-02}
200
+
09:04:52.506 [main] INFO com.iluwatar.currying.App -- Sci-fi Books:
201
+
09:04:52.506 [main] INFO com.iluwatar.currying.App -- Book{genre=SCIFI, author='Frank Herbert', title='Dune', publicationDate=1965-08-01}
202
+
09:04:52.506 [main] INFO com.iluwatar.currying.App -- Book{genre=SCIFI, author='Isaac Asimov', title='Foundation', publicationDate=1942-05-01}
178
203
```
179
204
180
205
## Class diagram
181
206
182
-

207
+

183
208
184
209
## Applicability
185
210
186
211
* When functions need to be called with some arguments preset.
187
212
* In functional programming languages or paradigms to simplify functions that take multiple arguments.
188
213
* To improve code reusability and composability by breaking down functions into simpler, unary functions.
189
214
215
+
## Tutorials
216
+
217
+
*[Currying in Java (Baeldung)](https://www.baeldung.com/java-currying)
218
+
*[What Is Currying in Programming (Towards Data Science)](https://towardsdatascience.com/what-is-currying-in-programming-56fd57103431#:~:text=Currying%20is%20helpful%20when%20you,concise%2C%20and%20more%20readable%20solution.)
219
+
*[Why the fudge should I use currying? (DailyJS)](https://medium.com/dailyjs/why-the-fudge-should-i-use-currying-84e4000c8743)
220
+
190
221
## Known uses
191
222
192
223
* Functional programming languages like Haskell, Scala, and JavaScript.
@@ -216,9 +247,6 @@ Trade-offs:
216
247
217
248
## Credits
218
249
250
+
*[Functional Programming in Java: Harnessing the Power Of Java 8 Lambda Expressions](https://amzn.to/3TKeZPD)
219
251
*[Java 8 in Action: Lambdas, Streams, and functional-style programming](https://amzn.to/3J6vEaW)
220
252
*[Modern Java in Action: Lambdas, streams, functional and reactive programming](https://amzn.to/3J6vJLM)
221
-
*[Functional Programming in Java: Harnessing the Power Of Java 8 Lambda Expressions](https://amzn.to/3TKeZPD)
222
-
*[Currying in Java](https://www.baeldung.com/java-currying)
223
-
*[What Is Currying in Programming](https://towardsdatascience.com/what-is-currying-in-programming-56fd57103431#:~:text=Currying%20is%20helpful%20when%20you,concise%2C%20and%20more%20readable%20solution.)
224
-
*[Why the fudge should I use currying?](https://medium.com/dailyjs/why-the-fudge-should-i-use-currying-84e4000c8743)
0 commit comments