Found in 14 comments on Hacker News
charlysl · 2017-07-28 · Original thread
I am currently studying the excellent https://www.amazon.com/Concepts-Techniques-Models-Computer-P..., and I believe that this book answers the questions in the OP very clearly, and although maybe you find it too theoretical, it does in fact provide loads of practical advice, and is very readable; not for the faint of heart though ;)

Anyway, just to practice what I've learned so far I will try to answer some of your questions from the top of my head; apologies in advance for my verbosity:

First of all, let's define functional (in fact, to be strict, declarative; more on this below):

An operation (i.e. a code fragment with a clearly defined input and output) is functional if for a given input it always gives the same output, regardless of all other execution state. It behaves just like a mathematical function, hence the name.

This gives a declarative operation the following properties:

1) Independence: nothing going on in the rest of the world will ever affect it.

2) Statelessness (same as immutability): there is no observable internal state; the output is the same every single time it is invoked with the same input.

3) Determinism: the output depends exclusively on the input and is always the same for a given input.

So what is the difference between functional and declarative? Functional is just a subset of declarative = declarative - dataflow variables

These properties give a functional program the following key benefits:

1) It is easier to design, implement and test. This is because of the above properties. For instance, because the output will never vary between different invocations, each input only needs to be tested once.

2) Easier to reason about (to prove correct). Algebraic reasoning (applying referential transparency for instance: if f(a)=a^2 then all occurences of f(a) can be replaced with a^2) and logical reasoning can be applied.

To further explore the practical implications of all this lets say that, given that all functional programs consist of a hierarchy of components (clearly defined program fragments connected exclusively to other components through their inputs and outputs) to understand a functional program it suffices to understand each of its components in isolation.

Basically, despite other programming models having more mindshare (but, as far as I can tell, aren't really better known, and this includes me ;), because of the above properties functional programming is fundamentally simpler than more expressive models, like OO and other models with explicit state.

Another very important point is that it is perfectly acceptable and feasible to write functional programs in non strictly functional languages like Java of C++ (although not in C, I won't explain why, it's complicated but basically the core reason has to do with how memory management is done in C).

This is because functional programming is not restricted to functional languages (where the program will be functional by definition no matter how much you mess up).

A program is functional if it is observably functional, if it behaves in the way specified above.

This can be achieved in, say, Java, with some discipline and if you know what you are doing; the Interpreter and Visitor design patterns are exactly for this, and one of the key operations to implement higher order programming, procedural abstraction, can easily be done using objects (see the excellent MIT OCW course https://ocw.mit.edu/courses/electrical-engineering-and-compu... for more on this).

Because of its limitations, it is often impossible to write a purely functional program. This is because the real world is statefull and concurrent. For instance, it is impossible to write a purely functional client-server application. How about IO or a GUI? Nope. I don't know Haskell yet, it seems they somehow pull it off with monads, but this approach, although impressive, is certainly not natural.

Garbage collection is a good thing. It's main benefit to functional languages is that it totally avoids dangling references by design. This is key to making determinism possible. Of course, automatically managing inactive memory to avoid most leaks is nice too (but not all leaks, like, say, references to unused variables inside a data structure, or any external resources).

However, functional programs can indeed result in higher memory consumption (bytes allocated per second, as opposed to memory usage, which is the minimum amount of memory for the program to run), which can be an issue in simulators, in which case a good garbage collector is required.

Certain specialised domains, like hard real time where lives are at stake, require specialised hardware and software anyway, never mind whether the language is functional or not.

So, for me, for the reasons above, the take home lesson so far is:

Program in the functional style wherever possible, it is in fact easier to get right due to its higher simplicity, and restrict and encapsulate statefulness (and concurrency) in an abstraction wherever possible (this common technique is called impedance matching).

Each programming problem, or component, etc, involves some degree of design first, or modelling, or a description, whichever word you prefer, it is all the same. There are some decisions you must make before coding, TDD or no TDD.

What paradigm you choose should depend first on the nature of the problem, not on the language. Certain problems are more easily (same as naturally) described in a functional way, as recursive functions on data structures. That part of the program should be implemented in a functional way if your language of choice allows that .

Other programs are more easily modelled as an object graph, or as a state diagram (awesome for IO among other things), and this is the way they should be designed and implemented if possible. But even in this case, some components can be designed in a functional way, and they should be wherever possible.

There is no one superior way, no silver bullet, it all depends on the context. It is better to know multiple programming paradigms without preferring one over the other, and apply the right one to the right problem.

pierre_d528 · 2016-11-06 · Original thread
There's no easy answer to this, but books like CTM [1] give an overview of the programming languages landscape. They can come in handy when evaluating language designs.
kzhahou · 2015-07-06 · Original thread
CTM, since it's not in the referenced article:

http://www.amazon.com/Concepts-Techniques-Models-Computer-Pr...

I feel like many of us are searching and probing around the same space. It definitely seems to be the case that existing programming languages are way too rigid, but that the current popular example of "just make the language whatever you desire" (Lisp) is not quite right, either. It's close, but just far enough away that it seems alien.

I'll definitely be paying closer attention to this as it agrees with a lot of hunches that I have about what's wrong with programming as we currently practice it.

Thanks so much for the link. I'm taking notes :)

EDIT: Anyone who likes Avail, and particularly the points made in the History section, should probably read CTM. [1]

You might be interested in Concepts, Techniques and Models of Computer Programming by Peter Van Roy and Seif Haridi (http://www.amazon.com/Concepts-Techniques-Models-Computer-Pr...). It presents an overview of different programming models, and expounds on the right way to approach problems with these different models. I found the chapters on concurrency useful myself.

While not a book, an alternative strategy that might be helpful would be to explore some projects like TorqueBox (Ruby) or Immutant (Clojure) that pull together a lot of different solutions (web server, application server, messaging, caching, transactions and scheduling) into a suite.

bjz_ · 2014-01-10 · Original thread
This is by fellow who wrote the awesome book Concepts, Techniques, and Models of Computer Programming. It'll probably teach different models of computation via the Oz programming language, but I doubt it will go into the kind of theory you'd find in Types and Programming Languages.

http://www.amazon.com/Concepts-Techniques-Models-Computer-Pr...

I'm injecting my own language bias here, and I must admit that this is not an opinion that everyone agrees with, but I think you're better with Scala or Clojure than with Java. (Both run on the JVM, so you end up learning the Java ecosystem.)

Scala is a "better Java" and you can learn both the JVM and functional programming (take Odersky's course on Coursera). Clojure is a great Lisp but the Java stuff will be very confusing if you haven't seen it before (the JVM-interop functions like proxy, gen-class, and reify don't have the easiest APIs).

This (Structure and Interpretation of Computer Programs) is a great book to get started on the deeper aspects of CS: http://mitpress.mit.edu/sicp/full-text/book/book.html

Also, I like this one: http://www.amazon.com/Concepts-Techniques-Models-Computer-Pr...

Yes, functional programming does give you more options, and that's the point. Each style of programming -- functional, object-oriented, relational, imperative, etc. -- has its strengths and weaknesses. It's up to the programmer to choose which one best fits the problem at hand.

In some languages, like Java, you're stuck in the OO style of programming because its syntax and features make anything else too cumbersome. Clojure actually works the other way around: though the most common style is functional, it's easy to work in terms of objects. It might not look the same as Java OO, but that's for the better.

Here's a good book about switching between programming styles within a single program: http://www.amazon.com/Concepts-Techniques-Models-Computer-Pr...

stiff · 2012-06-03 · Original thread
SICP is not really a book for programming beginners, there are plenty of other books for that, like "How to Design Programs". I detest the idea of using "more appropriate" examples, to me illustrating deep concepts from interesting fields like electronics and mathematics via computer programs was the gist of the book. Also, all the ideas used in the programs are very high-level, explained in the text, and you don't have to have any in-depth knowledge from any field outside of CS, you just have to have some basic maturity with respect to dealing with abstract concepts. I know because I for example solved all the exercises related to mathematics (differentiation, power series etc.) in SICP before I actually learnt any calculus, which I later did largely being inspired by SICP. Anyone aspiring to become a good programmer has to be able to learn basics of a new domain quickly, just knowing how to program is useless in itself. Besides, the more interesting the domain, the more interesting the programs, I think SICP gets this as right as possible.

SICP in general is a damn good book, there were already quite a few attempts to "improve" it, but I am not convinced any of those have really superseded it. There is for example "Concepts, Techniques and Models of Computer Programming", which is basically what you wish, SICP without digging into any particular domain:

http://www.amazon.com/Concepts-Techniques-Models-Computer-Pr...

There are certainly lots of valuable programming concepts explained in this book, and I would certainly recommend it to anyone with a deep interest in programming languages, but by using "dummy" examples, I think it simply became much more boring and less intellectually stimulating.

tim_sw · 2007-05-20 · Original thread
Read COncepts, Techniques, and models of computer programming.

You will get a taste of all these languages/paradigms, and in addition, others like concurrent programming etc.

Fresh book recommendations delivered straight to your inbox every Thursday.