• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Liutauras Vilda
  • Jeanne Boyarsky
  • Devaka Cooray
  • Paul Clapham
Sheriffs:
  • Tim Cooke
  • Knute Snortum
  • Bear Bibeault
Saloon Keepers:
  • Ron McLeod
  • Tim Moores
  • Stephan van Hulst
  • Piet Souris
  • Ganesh Patekar
Bartenders:
  • Frits Walraven
  • Carey Brown
  • Tim Holloway

Functional Programming in Java: why do I had to change toward functional programming?

 
Ranch Hand
Posts: 38
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hello,

Can you tell me, why do I had to change toward functional programming?

I don't know about this topic.

Maybe a functional vs imprative?

Thak you.
 
Author
Posts: 160
31
  • Likes 2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Carlos,

First of all, you don't HAVE to switch to functional programming. My book is about what you can do. not about what you should do.

The most important benefit of functional programming is  building safer programs. How can you be sure an imperative program is correct? Generally, imperative programmers rely upon testing. This implies several questions:

- Testing is not proving a program correct. It is only proving that we, as programmers, have been unable to prove it incorrect.

- To make testing efficient, we should be smarter at testing than at programming. This means we should spend more time trying to make programs fail that writing them in the first place.

- Tests are programs. Who test the tests?

- Testing does not improve code quality. Not more that taking our temperature will cure fever.

Functional programing makes program safer and minimizes the need for testing, which is good because tests are so inefficient at proving an implementation correct. (Tests are still a very important way to test whether we have solve the right problem. As such, they should probably be part of the specification.)

One way to achieve this safety is referential transparency. Functional programs are referentially transparent, meaning a program can always be replaced by its result without changing the overall outcome. As a result, such a program cannot change anything in the surrounding environment. It can only return a result, and this result will always be the same given the same input.

Another benefit of functional programming is modularity. Imperative programing relies upon control structures like loops and conditionals. These are powerful tools, but they do not compose easily. 5If they did, programming would be easy!) In functional programming, these control structures do not exist. They are replaced with functions. As we only have to compose functions, writing programs is much easier. At least, writing correct programs is easier because writing wrong programs is much more difficult.

These are concrete benefits. There may be others, depending upon how you consider programming. Programming is about using computers to solve real life problems, it involves modelling these problems, finding the solution for the given model, and then applying this solution to the "real world" problem.

Imperative programming is about modelling real world problems in terms of objects having state and mutating this state over time. More exactly transitioning from one state to another, making conditional decision about the state, and then applying another transition depending upon the result of the condition tested.

Why does it work like this? Some will say that it is because the real world works like this. Others, more careful, will say that it is because computers work like this. The second is true. (I don't know about the first one, but this would make a very interesting debate). Computer are state machines.

Should we model our problems following how our tools are working? Or should we make our tools work in a way corresponding to our problems? Some problems are easier to solve using functional programming. This might not be true for all problems, but functional programming is definitely a powerful tool to add to your toolbox.
 
Ranch Hand
Posts: 112
3
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Your response here makes a lot of sense. It feels like lightbulbs coming on when you say imperative programming is modeling computers and functional programming is modeling reality.

I would like to know what referential transparency is. What are some good sources for me to experience and create referential transparency myself?
 
Pierre-Yves Saumont
Author
Posts: 160
31
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Kent,

Referential transparency means that you may replace a referentially transparent expression by the result of evaluating it without changing the outcome of the program in any way. So a call to a method returning a value may be referentially transparent if it does not do anything else: no writing to the console or a file, a socket, a database, or anything else, no mutation of any variable in the outer scope, no mutation of its argument.

Methods having the void return type are obviously not referentially transparent (unless they do nothing). They are not functions, but effects. (Methods returning a value and having an effect are said to have a "side effect").  Functional programs solve this problem by returning effects as data in non evaluated form.

Functional effects may be used in Java although some consider this technique to be a bit too extreme for Java. In any case, if you prefer to use traditional effects, what you can do is to clearly separate effects from functions.

For example, if you want to print a list of the 100 first integers to the console, you can do it imperatively using a loop inside which you increment a value an print it to the console. A more functional implementation is to produce a list as the result of a function, and then print the list as a separate effect.

The problem with this approach is that the list might be too big to be held in memory. In such case, you have to use a lazy list. Lazy lists as implemented as Stream in Java.
 
Marshal
Posts: 64623
225
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Pierre-Yves Saumont wrote:. . . Lazy lists as implemented as Stream in Java.

Now, that looks like a sweeping statement if ever I saw one

I think I can understand what you are saying, but please explain a bit more.
 
Kent O. Johnson
Ranch Hand
Posts: 112
3
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I see, so if my program is a series of referentially transparent expressions that eventually makes some state change in a data store then hypothetically I could, for one service call, replace my program with the value it would create and store that to the database and my data would be in a valid consistent state.

So the next question is what are good practices for reorganizing the effects to the ends of my referentially transparent expression (RTE) pipeline? I gather that the only side-effects should occur at the end of a pipeline of RTEs. I posted my next question here: https://coderanch.com/t/685451/Functional-Programming-Java-put-Side
 
Pierre-Yves Saumont
Author
Posts: 160
31
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
@Campbell Ritchie

What I mean is that streams are essentially generators for series of data, and generators may be seen an implementation of lazy collections in the same way as a generator for a single value may be used to implement laziness. Consider the following code:



This is a generator for a the collection of integers from 0 to max (excluded). So it can be used to represent the list of integers from 0 to max, although these integers have not been computed yet. So it might be seen as a lazy collection of integers.

On the other hand, consider the following code:



This is also a generator for a collection of integers. The difference is that it does not compute each integer from the previous one. Instead, it looks for the next value in an already evaluated collection. If this collection contains integers from 0 to max, the results are equivalent.

Both constructs have their equivalent using Java 9 streams (not considering IntStream);



The main difference is in the way they compose. Loops may be composed with functions and effects by adding code inside and around them. Stream may be composed by calling methods on them, and passing them function and effect as arguments. But both may be used as ways to represent lazy collections of data, meaning collections that can be composed with functions and effects without evaluating them.

So streams are not lazy collections (they are mostly generators), but they can be used to handle collections of data in a lazy way.

 
Campbell Ritchie
Marshal
Posts: 64623
225
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
That is what I thought it meant: thank you
 
Pierre-Yves Saumont
Author
Posts: 160
31
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
@Kent O. Johnson

You're right. Your program should compute a result in a referentially transparent way. In the end, it could send the result to some external component (console, database, file, socket, other program...) as an effect. This is the simplest way to do it in Java because Java is not very functional friendly. Another way is to produce as the result a program that will have to be executed to apply ("evaluate") the effect. Here is a simple example of a program doing a computation and applying an effect:  



Here is a version separating the computation (in a referentially transparent way) and the effect:



Now this is a version returning the non evaluated effect:



Of course, this example is stupid. But it becomes more interesting if you consider the possibility to compose such unevaluated effects. For example, if a two methods return two effects, you can compose them:



All type of composition may be applied. The overall result is that you program have not effect at all. It simply returns a new program in which all decisions have been made, all computations have been settled. The only thing left to do is running that program. In purely functional languages, this happens out of the language itself.

Whether this is something one should do in Java is of course highly arguable. But it is interesting to learn about it and see how it could be done. There is a whole chapter about functional handling of effects in my book.
 
Kent O. Johnson
Ranch Hand
Posts: 112
3
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
This really helped:


Another way is to produce as the result a program that will have to be executed to apply ("evaluate") the effect.



I hadn't thought of that before! That is awesome, building an effect function or a list of effect functions to run at the edge of the pipeline. It made sense to build data structures as the pipeline goes on though I hadn't considered functions in the same light, maybe because I haven't been programming in homoionic languages (had to check my Clojure book again for that word). Javascript can be, I just haven't been using it that way yet.

Thanks for your detailed reply!
 
Creator of Enthuware JWS+ V6
Posts: 3285
296
Android Eclipse IDE Chrome
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Congratulations Carlos Solano,

Your question has made it to our Journal !

Have a Cow!
 
It is sorta covered in the JavaRanch Style Guide.
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!