Imperative vs. Functional programming

Programming, for all ages and all languages.
Seasoft
Posts: 20
Joined: Wed Sep 02, 2020 3:09 am

Imperative vs. Functional programming

Post by Seasoft »

Even though the theory of programming paradigms is still abstract for me right now, I wonder about this. I dipped into a Haskell tutorial, a functional programming language, and I don't know how to completely describe it but so far Haskell looks like a beautiful language. Even though it looks like it's more designed for problems working with lists and other "raw" datum and number-oriented tasks rather than games or 3D graphics objects. And the process to install the platform was a bit painful.
User avatar
bloodline
Member
Member
Posts: 264
Joined: Tue Sep 15, 2020 8:07 am
Location: London, UK

Re: Imperative vs. Functional programming

Post by bloodline »

Beauty is in the eye of the beholder. Probably to die to my age, and how long I’ve been programming for, I find functional languages to be clumsy, awkward, and without question very ugly.

Very few languages will ever be as beautiful as C. :)
CuriOS: A single address space GUI based operating system built upon a fairly pure Microkernel/Nanokernel. Download latest bootable x86 Disk Image: https://github.com/h5n1xp/CuriOS/blob/main/disk.img.zip
Discord:https://discord.gg/zn2vV2Su
nullplan
Member
Member
Posts: 1769
Joined: Wed Aug 30, 2017 8:24 am

Re: Imperative vs. Functional programming

Post by nullplan »

bloodline wrote:Very few languages will ever be as beautiful as C. :)
I wonder if I should just link to the IOCCC and leave it at that. Personally, I know that good programmers can write FORTRAN in any language. The language is but the canvas, it is the painting created on it that can be beautiful. Although an empty canvas is also beautiful, in a minimalist sort of way, it is not terribly high-effort. And won't really blow your socks off if you hang the Mona Lisa next to it.

Back to the topic. As in any language, you can write awesome code in Haskell, and you can write terrible code in it. I lack the experience to distinguish the two at this point, which is why I stick to C. But I must say, functional style of programming is certainly nice for some things. How many "any" and "all" loops has each of you written in your life? Too many to count, I would wager.

It's just that functional programming is not for me, because I am a very top-down thinker: Give me a problem, and I will deconstruct it into smaller ones, then figure out the smaller problems. Functional programming is more about creating small building blocks and building bigger and better things out of those, and that is just not how I work.
Carpe diem!
User avatar
eekee
Member
Member
Posts: 872
Joined: Mon May 22, 2017 5:56 am
Location: Kerbin
Discord: eekee
Contact:

Re: Imperative vs. Functional programming

Post by eekee »

I had a friend who said Haskell was good for some things, but there were some tasks which would be a dozen lines of code in Haskell but only a small one-liner in C. I took that as a reason to appreciate impure functional languages.
Kaph — a modular OS intended to be easy and fun to administer and code for.
"May wisdom, fun, and the greater good shine forth in all your work." — Leo Brodie
User avatar
AndrewAPrice
Member
Member
Posts: 2299
Joined: Mon Jun 05, 2006 11:00 pm
Location: USA (and Australia)

Re: Imperative vs. Functional programming

Post by AndrewAPrice »

The right tool for the task. For example:

Functional programming is great for calculation tasks that produce an answer. Think spreadsheets.

Imperative programming is great for tasks that have a sequence of steps to go through. Think the network code in web browsers.

It's more so a programming style, although languages catering to a particular style make it easier. Haskell has monards. You could adopt a functional style in C++. No global state, mutate no input parameters, pass around functions, etc. But, it can be awkward compared to a language that makes this more natural.

Use the right tool for the task, which might mean mixing them.

e.g. You could build a video game with the main mechanics in an imperative language, but then use a functional language for specific tasks such as determining the damage level if one character attacks another. If you do the latter in a scripting language, it makes it easier to support modding (fans can create new characters or weapons and customize their damage level.)
My OS is Perception.
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Re: Imperative vs. Functional programming

Post by Solar »

bloodline wrote:Very few languages will ever be as beautiful as C. :)
Well, virtually every non-trivial C program will come with a Makefile to build it.

And Makefile syntax is functional. ;-)

I never could wrap my head around functional-only languages, so the pandora's box that is LISP and its derivatives remains closed to me. But I sure liked those places where functional concepts made my life easier in C++ -- another reason why I like that language so much, being a hodgepodge of whatever-works-best-right-now without shoving some paradigm down your throat. ;-)
Every good solution is obvious once you've found it.
User avatar
eekee
Member
Member
Posts: 872
Joined: Mon May 22, 2017 5:56 am
Location: Kerbin
Discord: eekee
Contact:

Re: Imperative vs. Functional programming

Post by eekee »

Solar wrote:But I sure liked those places where functional concepts made my life easier in C++ -- another reason why I like that language so much, being a hodgepodge of whatever-works-best-right-now without shoving some paradigm down your throat. ;-)
When you put it that way, I think I'd really like C++. :D But Forth is a similar kind of hodgepodge, so I'm all right there.

Can you make domain-specific languages (DSLs) in C++ using operator overloading? Or rather, I guess you can, but is it practical? I guess "cout << ..." might count as a DSL. I ask because that's the nearest thing I can think of to the fairly common Forth practice of defining DSLs as temporary language extensions. For instance, I once saw a printf-like system where <% added definitions like %s or %d , and %> restored the dictionary to its previous state.

On another note, I sometimes think I'd like an imperative Lisp.
Kaph — a modular OS intended to be easy and fun to administer and code for.
"May wisdom, fun, and the greater good shine forth in all your work." — Leo Brodie
nullplan
Member
Member
Posts: 1769
Joined: Wed Aug 30, 2017 8:24 am

Re: Imperative vs. Functional programming

Post by nullplan »

eekee wrote:Can you make domain-specific languages (DSLs) in C++ using operator overloading? Or rather, I guess you can, but is it practical? I guess "cout << ..." might count as a DSL. I ask because that's the nearest thing I can think of to the fairly common Forth practice of defining DSLs as temporary language extensions. For instance, I once saw a printf-like system where <% added definitions like %s or %d , and %> restored the dictionary to its previous state.
You can, but operator overloading with different meanings comes at the drawback that you still get the old operator in its intended meaning, even if it does something else now. For example, you correctly point out that the shift operator was overloaded so it can be used with an iostream and whatever other data you want. The drawback is that it is still the shift operator, so it gets parsed as the shift operator. If you look at a precedence chart for C (C++ has basically the same one), you will see that shift is pretty much in the middle. If you want to use expressions that utilize lower precedence operators, you must employ parentheses, or else suffer through very obtuse error messages from the compiler.

That is not to say that this style of overloading is totally without merit, else it wouldn't have stuck around for so long. Operator overloading allows you to define overloads as member functions or as free functions and invoke them with the same syntax. For example, a common way iostreams gets extended with the capacity to print a new type is just by defining a new free function

Code: Select all

std::iostream &operator<<(std::iostream &str, const MyType &foo);
And then you can output a MyType into a stream just like you would anything else. It is not possible in C++ to just add a member function in this way, so if they had used a member function for formatted output, it would not have been possible to extend iostreams in this way.

Code: Select all

cout.write(some_int).write(my_foo).write(std::endl); /* error: no overload for write(MyType&) in std::ostream */
And free functions would just have gotten annoying:

Code: Select all

write(write(write(cout, some_int), my_foo), std::endl);
It is also not possible in C++ to add new operators into the language. If you want that, use Haskell.
Carpe diem!
Seasoft
Posts: 20
Joined: Wed Sep 02, 2020 3:09 am

Re: Imperative vs. Functional programming

Post by Seasoft »

I heard that functional is suggested as one tool to improve one's programming skill.
User avatar
BigBuda
Member
Member
Posts: 104
Joined: Fri Sep 03, 2021 5:20 pm

Re: Imperative vs. Functional programming

Post by BigBuda »

nullplan wrote:It is also not possible in C++ to add new operators into the language. If you want that, use Haskell.
That (adding new operators), custom attributes (like in C#) and syntactic sugar for properties in classes (instead of get_*/set_*) are the three things that I really think C++ is missing... (but that's just me, others will have different requirements). Instead, they've been adding a lot of stuff for niche cases... sad life.
Writing a bootloader in under 15 minutes: https://www.youtube.com/watch?v=0E0FKjvTA0M
User avatar
Schol-R-LEA
Member
Member
Posts: 1925
Joined: Fri Oct 27, 2006 9:42 am
Location: Athens, GA, USA

Re: Imperative vs. Functional programming

Post by Schol-R-LEA »

Solar wrote: I never could wrap my head around functional-only languages, so the pandora's box that is LISP and its derivatives remains closed to me.
One thing to note about Lisp - at least most major Lisps such as Common Lisp and Scheme - is that they aren't purely functional. Older classic LISPs predate the formulation of FP as a discipline, and in fact FP (and logic programming, constraint programming, and dataflow programming) was largely developed as a paradigm through DSLs which were developed in LISP 1.5 and it's immediate descendants.

Both Common Lisp and Scheme are multi-paradigm, having assignment forms such as SETF/set!, and are fundamentally more procedural than functional per se; functional programming in those two languages is a style rather than a language feature (though Scheme in particular strongly favors FP). Both also encourage developing DSLs as a means of extending the language in various ways.

By contrast, Clojure is mostly functional, but is designed to easily work with the underlying Java class libraries and can define its own classes as well.

CL in particular having a significant OOP subset called CLOS - though CLOS works very differently from most OO languages. Much of the focus in CLOS is more along the lines of generic programming than OO in the conventional sense, and the class definition approach is both flexible and esoteric. There's an entire textbook on how CLOS is implemented, titled The Art of the Metaobject Protocol, and that title alone will give you some sense of the attitudes of the implementors.

Note that the majority of CLOS is implemented in Common Lisp itself, using macros and read-macros, rather than as part of the underlying compiler (CL is always compiled; even the REPL is compile-and-go, rather than interpreted). It is a library and set of conventions, rather than a part of the language as such.

There are equally complete libraries/DSLs for logic programming, relational programming (both using SQL and using a more Lispy DSL), aspect-oriented programming, constraint programming, dataflow programming, finite automata and regexes in various flavors, pretty much whatever paradigm you can name. While most of these do use the s-expression syntax of the underlying Lisp, the use of macros and/or mini-interpreters mean that pretty much any syntax can be implemented in Lisp, as well.

Scheme doesn't have any official OO support in the language or the standard library, but since much of the language is built around both closures and macros it is trivial to develop an OOP library for it, and many, many different ones exist. These can have very different styles and flavors to them, with some following CLOS's model and other using a model closer to a conventional OO model. This diversity is deliberate, since Scheme is mostly meant for both teaching and research - developing (or at least studying the implementation of) a rump OOP library is a common mid-level project for courses using Scheme as a way of showing off the language's flexibility. A simple one doesn't even need macros, just closures, though most use macros to make the syntax more accessible.

That having been said, if Lisp isn't your thing, that's no problem. It looks and feels very different from other languages and not everyone will like it.
Rev. First Speaker Schol-R-LEA;2 LCF ELF JAM POEE KoR KCO PPWMTF
Ordo OS Project
Lisp programmers tend to seem very odd to outsiders, just like anyone else who has had a religious experience they can't quite explain to others.
h0bby1
Member
Member
Posts: 240
Joined: Wed Aug 21, 2013 7:08 am

Re: Imperative vs. Functional programming

Post by h0bby1 »

From my understanding, functional langage are more derived from lambda calculus, aka stateless, as you dont have to really mannage states, only constants and chains of operations that lead to new value. Which has a side to be easier to mannage for the mind, can parrallelize for free ( no mutable state no problem ). No side effects, no needs for pointers etc and remove lot of hardware architecture details from the algorithm.

It has more a grounding in classic mathematics it can have type system more based on mathematic type theory like abstract algebra etc that is cleaner than things like c++ generics.

If your mind is confortable with mathematics notation, set theories etc you might find yourself more confortable using functional languages, and find OOP is more messy.

For an OS i think you are screwed if you want to stick to functional purity because hardware has states and you have to mannage them, as well as pointers to address those hardware states. But maybe there are techniques to do this using pure functional style.

They are supposed to more oriented towards computation/mathematics/algebra etc

Even pointers dont have a clear algebra.

The bad side is it tend to use more memory and more cpu ressources.
Ethin
Member
Member
Posts: 625
Joined: Sun Jun 23, 2019 5:36 pm
Location: North Dakota, United States

Re: Imperative vs. Functional programming

Post by Ethin »

I really like how Rust does it. Not only is its macro system awesome (you can get pretty wild with the macro syntax, and people have even written parser grammar languages using the macro system, but you can use functional and imperative styles when you like. Both will compile to the same code. For instance, this:

Code: Select all

    let region_range: MiniVec<Range<u64>> = MMAP
        .get()
        .unwrap()
        .iter()
        .filter(|r| r.kind == MemoryRegionKind::Usable)
        .map(|r| r.start..r.end)
        .collect();
is identical to this (more verbose) equivalent:

Code: Select all

    let region_range: MiniVec<Range<u64>> = MiniVec::new();
    for r in MMAP.get().unwrap().iter() {
        if r.kind == MemoryRegionKind::Usable {
            region_range.push(r.start .. r.end);
        } else {
            continue;
        }
    }
Granted, using a purely functional style you lose break/continue, and so there are some places in my code where I've used pure loops because I needed them. But the idea behind FP is that you don't need break/continue, and if you do then one of your predicates is wrong, if I understand it right.

Personally, I've never understood haskell. It just doesn't click for me. The syntax looks like it was deliberately designed to confuse people as much as possible so that only mathematical geniuses could actually understand what it is that your actually doing or wanting to do. Plus the fact that *all* functions have to be pure, and if you want to do something impure, you have to do all this extra stuff just so you can. I like how Rust/C++ do it where they give you the tools to go as functional as you want, but they don't go "Oh by the way you have to completely rethink how logic works, and you have to completely redesign your program to fit the way the designers of the language want your program to work. Oh and you need this special type (and possibly even this special syntax) just so you can do anything other than mathematics". Sorry, but I like to be productive, and Haskell would have me constantly overthinking the design of my program, and I'd end up never getting anything done.
h0bby1
Member
Member
Posts: 240
Joined: Wed Aug 21, 2013 7:08 am

Re: Imperative vs. Functional programming

Post by h0bby1 »

Ethin wrote: Granted, using a purely functional style you lose break/continue, and so there are some places in my code where I've used pure loops because I needed them. But the idea behind FP is that you don't need break/continue, and if you do then one of your predicates is wrong, if I understand it right.
.
The equivalent of loops in FP is recursion , so break is return, continue is deeper recursion , with generally something like "when" clause to have flow control, and tail call to avoid eating the stack.

Or normally you can do away with loops with map/fold/filter kind of construct that are more mathematically sound.
h0bby1
Member
Member
Posts: 240
Joined: Wed Aug 21, 2013 7:08 am

Re: Imperative vs. Functional programming

Post by h0bby1 »

Ethin wrote:
Personally, I've never understood haskell. It just doesn't click for me. The syntax looks like it was deliberately designed to confuse people as much as possible so that only mathematical geniuses could actually understand what it is that your actually doing or wanting to do. Plus the fact that *all* functions have to be pure, and if you want to do something impure, you have to do all this extra stuff just so you can. I like how Rust/C++ do it where they give you the tools to go as functional as you want, but they don't go "Oh by the way you have to completely rethink how logic works, and you have to completely redesign your program to fit the way the designers of the language want your program to work. Oh and you need this special type (and possibly even this special syntax) just so you can do anything other than mathematics". Sorry, but I like to be productive, and Haskell would have me constantly overthinking the design of my program, and I'd end up never getting anything done.
Well it's the problem with FP is that its all good if you stick to purely computation. So you will rarely find a language that really stick to FP to a T because all you can do is making computation from input constant.

If you want streams , you cant because they have states.

The good approach is maybe functional reactive programming and coroutine, because they allow to have the minimum in imperative style to mannage state, and then functional style to mannage side effects from those state changes.

The good thing with FP and asynchronous code is that it leave no room for race conditions, can easily be lockless etc.

So it still make life easier for asynchronous code, it favorise referential transparency etc which is always a good thing to have callback mechanism, event handlers and all this kind of things.

But any functional language who want to be somehow competetive in the industry has to add some quirks because sometime you cant do away with states ( UI, streams etc ). Or it would lead to massive performance loss and memory use if you need to create a new copy of everything each time something affect a state.

But states and side effects is always a pita especially in asynchronous/concurent/parralell kind of programming because they lead to race conditions, so all together its never a bad thing to avoid them.

Its make program more predictible with referential transparency etc
Post Reply