DEV Community

Nahiyan Alamgir
Nahiyan Alamgir

Posted on

Functional programming in C++, Python, etc.

Let's say I want to print to the screen. In pure functional programming languages like Haskell or Elm, you can simply leave it to the runtime engine to do it for you. Your function doesn't need to do the dirty job.

If I move on to non-functional programming languages like python, C++, etc, I cannot signal the runtime environment to print text on screen, generate a random number, talk to the DB, etc. I have to do the operations myself. This makes functions impure since they are changing the state and/or relying on external states to work.

How can I write pure functions in python, C++, JS, etc since these languages lack features like Action, Command, etc to let the function communicate with the runtime environment?

I prefer learning with simple examples. If possible, can you show me how to write a pure function which prints text on the screen using a non-functional language (preferably python or C++)?

Top comments (12)

Collapse
 
rhymes profile image
rhymes

Regarding Python...

I think you already know the answer: you can't...

Collapse
 
nahiyan profile image
Nahiyan Alamgir

You're right, we can't have have 100% pure functional code. The idea is to keep as much of the core pure functional while the rest has to remain imperative.

Collapse
 
lyfolos profile image
Muhammed H. Alkan

Actually, you can. What are the reasons to can't functional in Python?

Collapse
 
rhymes profile image
rhymes

You can do a bit of functional programming: docs.python.org/3.7/howto/function...

It's just that it's not a functional language per se. It was designed as a general purpose, multi paradigm, language.

Thread Thread
 
lyfolos profile image
Muhammed H. Alkan

So basically you're meaning all of the multi paradigm languages has no paradigm, so like Scala is not functional nor object oriented. Sorry but that's a little bit absurd. You just have to obey the rules, nothing else. Functional programming doesn't mean purely functional programming. It's not hard at all functional programming in Python.

Thread Thread
 
rhymes profile image
rhymes

No, I was saying exactly the opposite 😅

You can mix object orientation and functional programming.

Thread Thread
 
lyfolos profile image
Muhammed H. Alkan

You just said it's multi-paradigm language but a little bit functional :p

Thread Thread
 
rhymes profile image
rhymes

Yeah sorry, I should have been clearer. It's not a pure functional language, but you can do functional programming. If you are careful not to use global state you can go far. Iterators, generators, the itertools and functools modules are all useful.

A side note: functions can store state but let's not go down that path 😂

Thread Thread
 
nahiyan profile image
Nahiyan Alamgir • Edited

I figured out that you can't have a 100% "pure functional" program in languages which aren't built for that, due to lack of features I've mentioned in this post.

However, the main concept is not to have 100% pure functional program but to have a pure functional core and an imperative shell. Google "functional core, imperative shell" for details. The idea is to push the imperative code far off to the edge and keep the core pure functional.

And based on that, I've written a demo Hello World program in C++. The idea is that you build a pure functional core which returns actions (just like you do in Haskell) - same input yields same output with no side effect, while you have an imperative shell which executes the actions. Here's my code:

gist.github.com/nahiyan/4ea3181b6b...

Thread Thread
 
rhymes profile image
rhymes • Edited

What's the advantage here? I mean over the imperative way of outputting strings over stdio.

You're basically storing in memory potentially huge amount of strings and having to call execute instead of just using cout 🤔 The example is also encapsulating IO in a class, I'm not sure which part is functional 😬

Why is this better than creating a buffer and then printing it out when needed?

Thread Thread
 
nahiyan profile image
Nahiyan Alamgir

I didn't write an efficient IO monad, I just wanted it to work somehow. Even if I wrote an efficient IO monad, there is no doubt that imperative programming is likely to be more memory efficient. If you're aiming for memory efficiency, go for it. But in the modern age of cheap and fast computing, we don't really care about the efficiency if we get benefits which are worth it.

The benefit here is that the functions aren't dealing with side effects, they are only declaring side effects, keeping them pure. Declared side effects are executed by the imperative shell. Pure functions are just like the ones you see in mathematics, they lead to much less bugs, are easier to test, debug, etc. Imagine writing a unit test for pure functions vs a non-pure function (nightmare to say the least). This is pretty much how Haskell or any declarative pure functional programming language works.

The function I wrote "main_" only returns a declared side effect (IO instance), is a pure function and is super easy to test, I don't even have to mock anything here. That's the functional part of the program. The rest is the imperative shell.

P.S. I'm not storing huge amounts of data in the memory here. If I ever need to output huge text, I'd deal with them in chunks. You can argue about the same thing when using recursion in functional programming rather than a loop (which can also lead to max call stack overflow errors in some languages). Recursion uses much more memory than a simple for/while loop. But when we're doing functional programming, we're considering the benefits of having more maintainable code.

Collapse
 
epogrebnyak profile image
Evgeny Pogrebnyak

Check out docs.python.org/3/howto/functional... (as mentioned). For "pure function which prints text on the screen" I think you are stuck, unless you review what is your defintion of fucntional.

If you are to encapsulate your output into IO monad in python you can try github.com/dbrattli/OSlash, but this is just an excercise.

from oslash import put_line, get_line

main = put_line("What is your name?") | (lambda _:
    get_line() | (lambda name:
    put_line("What is your age?") | (lambda _:
    get_line() | (lambda age:
    put_line("Hello " + name + "!") | (lambda _:
    put_line("You are " + age + " years old"))))))

if __name__ == "__main__":
    main()

I thing more fruitful concepts in functional programming are curring, map/filter/reduce and function composition.

Regarding the nice code in gist.github.com/nahiyan/4ea3181b6b... - I think you are just mimicing one behaviour of bind as concat string, while binding can perform different actions on container content. Also there is a difference on class type and an OOP class, as discussed for example here stackoverflow.com/questions/270465....