Related
There is a lot of talk about loop-less (functional) programming languages, but I haven't heard of any modern recursive-less programming languages. I know COBOL doesn't (or didn't) support recursion and I imagine it's the same for FORTRAN (or at the very least they will have a weird behaviour), but are there any modern languages?
There are several reasons I am wondering about this...
From what I understand there is no recursive algorithm for which no iterative implementation exists that is at least as performant (as you can simply "simulate" recursion iteratively, when managing the stack within the loop). So there is a) no performance gain and b) no capability gain from using recursion.
Recursion can have worse performance than iteration for things like naiive, recursive implementations of fibonacci numbers. People like to point out that recursion can be just as fast when compilers are optimized and it comes to tail recursion, but from my understanding tail recursion algos always are trivial to convert to loops. So there is c) potential performance loss from recursion.
Academics seem to have a thing for recursion, but then again most of them can't/don't really write any productive code. C++ (or object orientation in general) is the living proof how academic ideas can make their way into the business world/companies, while beeing mostly impractical. I wonder if recursion is only another example of this. (I know this is an opinionated topic, but the majority of accomplished software engineers I heard talk agree on this at least to some extent).
I have written recursive algorithms in productive systems before, but I can't think of a time, when I really benefited from using recursion. Recursive algorithms d) may or may not provide code readability advantages in some cases. I am not sure about this...
Most (all?) modern operating systems rely on specified call stack conventions. So if you want to call any external library from within your program, your programming language/compiler has to comply with the system's call stack convention. This makes it an easy step to adopt recursion for programming languages/compilers. However if you would create a recursion-less language you wouldn't need a call stack at all, which would have interesting effects in terms of memory management...
So I am not hating on recursion... I am just wondering if the recursion-less language experiment has been done in the recent past and what the results have been, as it seems like a practical experiment to me?
I have been reading up on functional programming and I have two questions that I was hoping someone could help me with.
I've read that lazy functional programs can be inefficient if you are accessing the same data often because of the extra overhead of checking whether the expression has been evaluated. I have also read in the first answer of the following thread (Are functional programming languages suitable for graphics programming?), that functional programming can be resource demanding in the context of graphical programming because it creates a lot of temporary objects (I assume this has to do with having to create new objects to simulate state?).
Are there any other areas where functional programming might end up being resource heavy / inefficient in compairison to OOP/procedural programming?
I have read in the first answer in the following thread (Pitfalls/Disadvantages of Functional Programming), that "it is very difficult to predict the time and space costs of evaluating a lazy functional program". Could someone give a simple (if that exists) explaination of why this is the case? I assume it has to do with lazy evaluation only evaluation expressions when needed, but why is it not simple to predict kind of a worst case scenario that is similar to imperative programming where everything is evaluated?
I've read that lazy functional programs can be inefficient if you are accessing the same data often because of the extra overhead of checking whether the expression has been evaluated.
This involves checking a tag bit on a pointer. It is cheap.
functional programming can be resource demanding in the context of graphical programming because it creates a lot of temporary objects
This depends on the implementation. Allocation in pure FP languages is cheap, as immutability means you can avoid some write barriers. Object allocation is roughly similar to OO languages, though some GCs, such as GHCs, are very efficient compared to e.g. Java.
Are there any other areas where functional programming might end up being resource heavy / inefficient in compairison to OOP/procedural programming?
There are plenty of problems that require very tight resource usage. E.g. operating systems. In such environments you need libraries for direct access to hardware and the ability to mutate memory in place. Depending on the functional language implementation you're using, you may or may not have this.
it is very difficult to predict the time and space costs of evaluating a lazy functional program
It is harder to model lazy evaluation costs because the amount of work done, and when it is done, depends on the input data, which is only available at runtime.
Practically, languages let you choose whether you want to use strict or lazy evaluation, as neither are appropriate for all situations.
Here seems to be the two biggest things I can take from the How to Design Programs (simplified Racket) course I just finished, straight from the lecture notes of the course:
1) Tail call optimization, and the lack thereof in non-functional languages:
Sadly, most other languages do not support TAIL CALL
OPTIMIZATION. Put another way, they do build up a stack
even for tail calls.
Tail call optimization was invented in the mid 70s, long
after the main elements of most languages were developed.
Because they do not have tail call optimization, these
languages provide a fixed set of LOOPING CONSTRUCTS that
make it possible to traverse arbitrary sized data.
a) What are the equivalents to this type of optimization in procedural languages that don't feature it?
b) Do using those equivalents mean we avoid building up a stack in similar situations in languages that don't have it?
2) Mutation and multicore processors
This mechanism is fundamental in almost any other language you
program in. We have delayed introducing it until now for
several reasons:
despite being fundamental, it is surprisingly complex
overuse of it leads to programs that are not amenable
to parallelization (running on multiple processors).
Since multi-core computers are now common, the ability
to use mutation only when needed is becoming more and
more important
overuse of mutation can also make it difficult to
understand programs, and difficult to test them well
But mutable variables are important, and learning this mechanism
will give you more preparation to work with Java, Python and many
other languages. Even in such languages, you want to use a style
called "mostly functional programming".
I learned some Java, Python and C++ before taking this course, so came to take mutation for granted. Now that has been all thrown in the air by the above statement. My questions are:
a) where could I find more detailed information regarding what is suggested in the 2nd bullet, and what to do about it, and
b) what kind of patterns would emerge from a "mostly functional programming" style, as opposed to a more careless style I probably would have had had I continued on with those other languages instead of taking this course?
As Leppie points out, looping constructs manage to recover the space savings of proper tail calling, for the particular kinds of loops that they support. The only problem with looping constructs is that the ones you have are never enough, unless you just hurl the ball into the user's court and force them to model the stack explicitly.
To take an example, suppose you're traversing a binary tree using a loop. It works... but you need to explicitly keep track of the "ones to come back to." A recursive traversal in a tail-calling language allows you to have your cake and eat it too, by not wasting space when not required, and not forcing you to keep track of the stack yourself.
Your question on parallelism and concurrency is much more wide-open, and the best pointers are probably to areas of research, rather than existing solutions. I think that most would agree that there's a crisis going on in the computing world; how do we adapt our mutation-heavy programming skills to the new multi-core world?
Simply switching to a functional paradigm isn't a silver bullet here, either; we still don't know how to write high-level code and generate blazing fast non-mutating run-concurrently code. Lots of folks are working on this, though!
To expand on the "mutability makes parallelism hard" concept, when you have multiple cores going, you have to use synchronisation if you want to modify something from one core and have it be seen consistently by all the other cores.
Getting synchronisation right is hard. If you over-synchronise, you have deadlocks, slow (serial rather than parallel) performance, etc. If you under-synchronise, you have partially-observed changes (where another core sees only a portion of the changes you made from a different core), leaving your objects observed in an invalid "halfway changed" state.
It is for that reason that many functional programming languages encourage a message-queue concept instead of a shared state concept. In that case, the only shared state is the message queue, and managing synchronisation in a message queue is a solved problem.
a) What are the equivalents to this type of optimization in procedural languages that don't feature it? b) Do using those equivalents mean we avoid building up a stack in similar situations in languages that don't have it?
Well, the significance of a tail call is that it can evaluate another function without adding to the call stack, so anything that builds up the stack can't really be called an equivalent.
A tail call behaves essentially like a jump to the new code, using the language trappings of a function call and all the appropriate detail management. So in languages without this optimization, you'd use a jump within a single function. Loops, conditional blocks, or even arbitrary goto statements if nothing else works.
a) where could I find more detailed information regarding what is suggested in the 2nd bullet, and what to do about it
The second bullet sounds like an oversimplification. There are many ways to make parallelization more difficult than it needs to be, and overuse of mutation is just one.
However, note that parallelization (splitting a task into pieces that can be done simultaneously) is not entirely the same thing as concurrency (having multiple tasks executed simultaneously that may interact), though there's certainly overlap. Avoiding mutation is incredibly helpful in writing concurrent programs, since immutable data avoids a lot of race conditions and resource contention that would otherwise be possible.
b) what kind of patterns would emerge from a "mostly functional programming" style, as opposed to a more careless style I probably would have had had I continued on with those other languages instead of taking this course?
Have you looked at Haskell or Clojure? Both are heavily inclined to a very functional style emphasizing controlled mutation. Haskell is more rigorous about it but has a lot of tools for working with limited forms of mutability, while Clojure is a bit more informal and might be more familiar to you since it's another Lisp dialect.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 9 years ago.
Improve this question
I hear all the time that Erlang is a functional language, yet it is easy to call databases or non side-effect free code from a function, and commands are easily ordered by using "," commas between them just like Ruby or another language, so where is the "functional" part of Erlang?
The central idea is that each process is a functional program over an input stream of messages. The result from the functional program is an output stream of messages to others. From this perspective, Erlang is a rather clean functional language; there are no destructive updates to data structures (like setcar in Lisp and most Schemes).
With few exceptions, all built-in functions such as operations on ETS tables also follow this model: apart from efficiency issues, those BIFs could actually have been implemented with pure Erlang processes and message passing.
So yes, the Erlang language is functional, but a collection of interacting Erlang processes is a different thing. Each process is an ongoing computation, and as such it has a current state, which can change in relation to the other processes. Even a database is just another process in this respect.
In my mind, this is one of the most important things about Erlang: outside the process, there could be a storm raging, but inside, things are calm, letting you focus on what that process should do - and only that.
There's a meme that functional languages must have immutable values and be side-effect free, but I say that any language with first-class functions is a functional programming language.
It is useful and powerful to have strong controls over value mutability and side effects, but I believe these are peripheral to functional programming. Nice to have, but not essential. Even in languages that do have these properties, there is always a way to escape the purity of the paradigm.1
There is a grayscale continuum between truly pure FP languages that you can't actually use for anything practical and languages that are really quite impure but still have some of the FP nature to them:
Book FP: Introductory books on FP languages frequently show only a subset of the language, with all examples done within the language's REPL, so that you never get to see the purely functional paradigm get broken. A good example of this is Scheme as presented in The Little Schemer.
You can come away from reading such a book with the false impression that FP languages can't actually do anything useful.
Haskell: The creators of Haskell went to uncommon lengths to wall off impurity via the famous I/O monad. Everything on one side of the wall is purely functional, so that the compiler can reason confidently about the code.
But the important thing is, despite the existence of this wall, you have to use the I/O monad to get anything useful done in Haskell.2 In that sense, Haskell isn't as "pure" as some would like you to believe. The I/O monad allows you to build any sort of "impure" software you like in Haskell: database clients, highly stateful GUIs, etc.
Erlang: Has immutable values and first-class functions, but lacks a strong wall between the core language and the impure bits.
Erlang ships with Mnesia, a disk-backed in-memory DBMS, which is about as impure as software gets. It's scarcely different in practice from a global variable store. Erlang also has great support for communicating with external programs via ports, sockets, etc.
Erlang doesn't impose any kind of purity policy on you, the programmer, at the language level. It just gives you the tools and lets you decide how to use them.
OCaml and F#: These closely-related multiparadigm languages include both purely functional elements as well as imperative and object-oriented characteristics.
The imperative programming bits allow you to do things like write a traditional for loop with a mutable counter variable, whereas a pure FP program would probably try to recurse over a list instead to accomplish the same result.
The OO parts are pretty much useless without the mutable keyword, which turns a value definition into a variable, so that the compiler won't complain if you change the variable's value. Mutable variables in OCaml and F# have some limitations, but you can escape even those limitations with the ref keyword.
If you're using F# with .NET, you're going to be mutating values all the time, because most of .NET is mutable, in one way or another. Any .NET object with a settable property is mutable, for example, and all the GUI stuff inherently has side-effects. The only immutable part of .NET that immediately comes to mind is System.String.
Despite all this, no one would argue that OCaml and F# are not functional programming languages.
JavaScript, R, Lua, Perl...: There are many languages even less pure than OCaml which can still be considered functional in some sense. Such languages have first-class functions, but values are mutable by default.
Foototes:
Any truly pure FP language is a toy language or someone's research project.
That is, unless your idea of "useful" is to keep everything in the ghci REPL. You can use Haskell like a glorified calculator, if you like, so it's pure FP.
Yes, it's a functional language. It's not a pure functional language like Haskell, but then again, neither is LISP (and nobody really argues that LISP isn't functional).
The message-passing/process handling of Erlang is an implementation of the Actor model. You could argue that Erlang is an Actor language, with a functional language used for the individual Actors.
The functional part is that you tend to pass around functions. Most langauges can be used both as a functional language, and as an imperative language, even C (it's quite possible to make a program consisting of only function pointers and constants).
I guess the distinguishing factor is usually the lack of mutable variables in functional languages.
In my second year of University we were "taught" Haskell, I know almost nothing about it and even less about functional programming.
What is functional programming, why and/xor where would I want to use it instead of non-functional programming and am I correct in thinking that C is a non-functional programming language?
One key feature in a functional language is the concept of first-class functions. The idea is that you can pass functions as parameters to other functions and return them as values.
Functional programming involves writing code that does not change state. The primary reason for doing so is so that successive calls to a function will yield the same result. You can write functional code in any language that supports first-class functions, but there are some languages, like Haskell, which do not allow you to change state. In fact, you're not supposed to make any side effects (like printing out text) at all - which sounds like it could be completely useless.
Haskell instead employs a different approach to IO: monads. These are objects that contain the desired IO operation to be executed by your interpreter's toplevel. At any other level they are simply objects in the system.
What advantages does functional programming provide? Functional programming allows coding with fewer potentials for bugs because each component is completely isolated. Also, using recursion and first-class functions allows for simple proofs of correctness which typically mirror the structure of the code.
What is functional programming
There are two different definitions of "functional programming" in common use today:
The older definition (originating from Lisp) is that functional programming is about programming using first-class functions, i.e. where functions are treated like any other value so you can pass functions as arguments to other functions and function can return functions among their return values. This culminates in the use of higher-order functions such as map and reduce (you may have heard of mapReduce as a single operation used heavily by Google and, unsurprisingly, it is a close relative!). The .NET types System.Func and System.Action make higher-order functions available in C#. Although currying is impractical in C#, functions that accept other functions as arguments are common, e.g. the Parallel.For function.
The younger definition (popularized by Haskell) is that functional programming is also about minimizing and controlling side effects including mutation, i.e. writing programs that solve problems by composing expressions. This is more commonly called "purely functional programming". This is made possible by wildly different approaches to data structures called "purely functional data structures". One problem is that translating traditional imperative algorithms to use purely functional data structures typically makes performance 10x worse. Haskell is the only surviving purely functional programming language but the concepts have crept into mainstream programming with libraries like Linq on .NET.
where would I want to use it instead of non-functional programming
Everywhere. Lambdas in C# have now demonstrated major benefits. C++11 has lambdas. There's no excuse not to use higher-order functions now. If you can use a language like F# you'll also benefit from type inference, automatic generalization, currying and partial application (as well as lots of other language features!).
am I correct in thinking that C is a non-functional programming language?
Yes. C is a procedural language. However, you can get some of the benefit of functional programming by using function pointers and void * in C.
May be worth checking out this article on F# "101" on CoDe Mag recently posted.
Also, Dustin Campbell has a great blog where he has posted many articles on his adventures on getting up to speed with F#..
I hope you find these useful :)
EDIT:
Also, just to add, my understanding of functional programming is that everything is a function, or parameters to a function, rather than instances/stateful objects.. But I could be wrong F# is something I am dying to get in to but just dont have the time! :)
John the Statistician's example code does not show functional programming, because when you're doing functional programming, the key is that the code does NO ASSIGNMENTS ( record = thingConstructor(t) is an assignment), and it has NO SIDE EFFECTS (localMap.put(record) is a statement with a side effect). As a result of these two constraints, everything that a function does is fully captured by its arguments and its return value. Rewriting the Statistician's code the way it would have to look, if you wanted to emulate a functional language using C++:
RT getOrCreate(const T thing,
const Function<RT<T>> thingConstructor,
const Map<T,RT<T>> localMap) {
return localMap.contains(t) ?
localMap.get(t) :
localMap.put(t,thingConstructor(t));
}
As a result of the no side-effects rule, every statement is part of the return value (hence return comes first), and every statement is an expression. In languages that enforce functional programming, the return keyword is implied, and the if statement behaves like C++'s ?: operator.
Also, everything is immutable, so localMap.put has to create a new copy of localMap and return it, instead of modifying the original localMap, the way a normal C++ or Java program would. Depending on the structure of localMap, the copy could re-use pointers into the original, reducing the amount of data that has to be copied.
Some of the advantages of functional programming include the fact that functional programs are shorter, and it is easier to modify a functional program (because there are no hidden global effects to take into account), and it is easier to get the program right in the first place.
However, functional programs tend to run slowly (because of all the copying they have to do), and they don't tend to interact well with other programs, operating system processes, or operating systems, which deal in memory addresses, little-endian blocks of bytes, and other machine-specific, non-functional bits. The degree of noninteroperability tends to be inversely correlated with the degree of functional purity, and the strictness of the type system.
The more popular functional languages have really, really strict type systems. In OCAML, you can't even mix integer and floating-point math, or use the same operators (+ is for adding integers, +. is for adding floats). This can be either an advantage or a disadvantage, depending on how highly you value the ability of a type checker to catch certain kinds of bugs.
Functional languages also tend to have really big runtime environments. Haskell is an exception (GHC executables are almost as small as C programs, both at compile-time and runtime), but SML, Common Lisp, and Scheme programs always require tons of memory.
Yes you are correct in thinking that C is a non-functional language. C is a procedural language.
I prefer to use functional programming to save myself repeated work, by making a more abstract version and then using that instead. Let me give an example. In Java, I often find myself creating maps to record structures, and thus writing getOrCreate structures.
SomeKindOfRecord<T> getOrCreate(T thing) {
if(localMap.contains(thing)) { return localMap.get(thing); }
SomeKindOfRecord<T> record = new SomeKindOfRecord<T>(thing);
localMap = localMap.put(thing, record);
return record;
}
This happens very often. Now, in a functional language I could write
RT<T> getOrCreate(T thing,
Function<RT<T>> thingConstructor,
Map<T,RT<T>> localMap) {
if(localMap.contains(thing)) { return localMap.get(thing); }
RT<T> record = thingConstructor(thing);
localMap = localMap.put(thing,record);
return record;
}
and I would never have to write a new one of these again, I could inherit it. But I could do one better than inheriting, I could say in the constructor of this thing
getOrCreate = myLib.getOrCreate(*,
SomeKindOfRecord<T>.constructor(<T>),
localMap);
(where * is a kind of "leave this parameter open" notation, which is a sort of currying)
and then the local getOrCreate is exactly the same as it would have been if I wrote out the whole thing, in one line, with no inheritance dependencies.
If you are looking for a good text on F#
Expert F# is co-written by Don Syme. Creator of F#. He worked on generics in .NET specifically so he could create F#.
F# is modeled after OCaml so any OCaml text would help you learn F# as well.
I find What Is Functional Programming? to be useful
Functional programming is about writing pure functions, about removing
hidden inputs and outputs as far as we can, so that as much of our
code as possible just describes a relationship between inputs and
outputs.
Prefer explicit when param
public Program getProgramAt(TVGuide guide, int channel, Date when) {
Schedule schedule = guide.getSchedule(channel);
Program program = schedule.programAt(when);
return program;
}
over
public Program getCurrentProgram(TVGuide guide, int channel) {
Schedule schedule = guide.getSchedule(channel);
Program current = schedule.programAt(new Date());
return current;
}
A functional language is actively hostile to side-effects. Side-effects are complexity and complexity is bugs and bugs are the devil. A functional language will help you be hostile to side-effects too.