Is there any Mathematical Model or Theory behind Programming Languages? [closed] - oop

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 7 years ago.
Improve this question
RDBMS are based on Relational Algebra as well as Codd's Model. Do we have something similar to that for Programming languages or OOP?

Do we have [an underlying model] for programming languages?
Heavens, yes. And because there are so many programming languages, there are multiple models to choose from. Most important first:
Church's untyped lambda calculus is a model of computation that is as powerful as a Turing machine (no more and no less). The famous "Church-Turing hypothesis" is that these two equivalent models represent the most general model of computation that we know how to implement. The lambda calculus is extremely simple; in its entirety the language is
e ::= x | e1 e2 | \x.e
which constitute variables, function applications, and function definitions. The lambda calculus also comes with a fairly large collection of "reduction rules" for simplifying expressions. If you find an expression that can't be reduced, that is called a "normal form" and represents a value.
The lambda calculus is so general that you can take it in several directions.
If you want to use all the available rules, you can write specialized tools like partial evaluators and parts of compilers.
If you avoid reducing any subexpression under a lambda, but otherwise use all the rules available, you wind up with a model of a lazy functional language like Haskell or Clean. In this model, if a reduction can terminate, it is guaranteed to, and it is easy to represent infinite data structures. Very powerful.
If you avoid reducing any subexpression under a lambda, and if you also insist on reducing each argument to a normal form before a function is applied, then you have a model of an eager functional language like F#, Lisp, Objective Caml, Scheme, or Standard ML.
There are also several flavors of typed lambda calculi, of which the most famous are grouped under the name System F, which were discovered independently by Girard (in logic) and by Reynolds (in computer science). System F is an excellent model for languages like CLU, Haskell, and ML, which are polymorphic but have compile-time type checking. Hindley (in logic) and Milner (in computer science) discovered a restricted form of System F (now called the Hindley-Milner type system) which makes it possible to infer System F expressions from some expressions of the untyped lambda calculus. Damas and Milner developed an algorithm do this inference, which is used in Standard ML and has been generalized in other languages.
Lambda calculus is just pushing symbols around. Dana Scott's pioneering work in denotational semantics showed that expressions in the lambda calculus actually correspond to mathematical functions—and he identified which ones. Scott's work is especially important in making sense of "recursive definitions", which are commonplace in computer science but are nonsensical from a mathematical point of view. Scott and Christopher Strachey showed that a recursive definition is equivalent to the least defined solution to a recursion equation, and furthermore showed how that solution could be constructed. Any language that allows recursion, and especially languages that allow recursion at arbitrary type (like Haskell and Clean) owes something to Scott's model.
There is a whole family of models based on abstract machines. Here there is not so much an individual model as a technique. You can define a language by using a state machine and defining transitions on the machine. This definition encompasses everything from Turing machines to Von Neumann machines to term-rewriting systems, but generally the abstract machine is designed to be "as close to the language as possible." The design of such machines, and the business of proving theorems about them, comes under the heading of operational semantics.
What about object-oriented programming?
I'm not as well educated as I should be about abstract models used for OOP. The models I'm most familiar with are very closely connected to implementation strategies. If I wanted to investigate this area further I would start with William Cook's denotational semantics for Smalltalk. (Smalltalk as a language is very simple, almost as simple as the lambda calculus, so it makes a good case study for modeling more complicated object-oriented languages.)
Wei Hu reminds me that Martin Abadi and Luca Cardelli have put together an ambitious body of work on foundational calculi (analogous to the lambda calculus) for object-oriented languages. I don't understand the work well enough to summarize it, but here is a passage from the Prologue of their book, which I feel is worth quoting:
Procedural languages are generally well understood; their constructs are by now standard, and their formal underpinnings are solid. The fundamental features of these languages have been distilled into formalisms that prove useful in identifying and explaining issues of implementation, static analysis, semantics, and verification.
An analogous understanding has not yet emerged for object-oriented languages. There is no widespread agreement on a collection of basic constructs and on their properties... This situation might improve if we had a better understanding of the foundations of object-oriented languages.
... we take objects as primitive and concentrate on the intrinsic rules that objects should obey. We introduce object calculi and develop a theory of objects around them. These object calculi are as simple as function calculi, but represent objects directly.
I hope this quotation gives you an idea of the flavor of the work.

Lisp is based on Lambda Calculus, and is the inspiration for much of what we see in modern languages today.
Von-Neumann machines are the foundation of modern computers, which were first programmed in assembler language, then in FORmula TRANslator. Then the formal linguistic theory of context-free-grammars was applied, and underlies the syntax of all modern languages.
Computability theory (formal automata) has a hierachy of machine-types that parallels the hierarchy of formal grammars, for example, regular-grammar = finite-state-machine, context-free-grammar = pushdown-automaton, context-sensitive-grammar = turing-machine.
There also is information theory, of two types, Shannon and Kolmogorov, that can be applied to computing.
There are lesser-known models of computing, such as recursive-function-theory, register-machines, and Post-machines.
And don't forget predicate-logic in its various forms.
Added: I forgot to mention discrete math - group theory and lattice theory. Lattices in particular are (IMHO) a particularly nifty concept underlying all boolean logic, and some models of computation, such as denotational semantics.

Functional languages like lisp inherit their basic concepts from Church's "lambda calculs" (wikipedia article here).
Regards

One concept may be Turing Machine.

If you study programming languages (eg: at a University), there is quite a lot of theory, and not a little math involved.
Examples are:
Finite State Machines
Formal Lanugages (and Context Free Grammars like BNF used to describe them)
The construction of LRish parser tables

The closest analogy I can think of is Gurevich Evolving Algebras that, nowadays, are more known under the name of "Gurevich Abstract State Machines" (GASM).
I've long hoped to see more real applications of the theory when Gurevich joined Microsoft, but it seems that very few is coming out. You can check the ASML page on the Microsoft site.
The good point about GASM is that they closely resemble pseudo-code even if their semantic is formally specified. This means that practitioners can easily grasp them.
After all, I think that part of the success of Relational Algebra is that it is the formal foundation of concepts that can be easily grasped, namely tables, foreign keys, joins, etc.
I think we need something similar for the dynamic components of a software system.

There are many dimensions to address your question, scattering in the answers.
First of all, to describe the syntax of a language and specify how a parser would work, we use context-free grammars.
Then you need to assign meanings to the syntax. Formal semantics come in handy; the main players are operational semantics, denotational semantics, and axiomatic semantics.
To rule out bad programs you have the type system.
In the end, all computer programs can reduce to (or compile to, if you will) very simple computation models. Imperative programs are more easily mapped to Turing machines, and functional programs are mapped to lambda calculus.
If you're learning all this stuff by yourself, I highly recommend http://www.uni-koblenz.de/~laemmel/paradigms0910/, because the lectures are videotaped and put online.

The history section of Wikipedia's Object-oriented programming could be enlightening.

Plenty has been mentioned of the application of math to computational theory and semantics. I like the mention of type theory and I'm glad someone mentioned lattice theory. Here are just a few more.
No one has explicitly mentioned category theory, which shows up more in functional languages than elsewhere, such as through the concepts of monads and functors. Then there's model theory and the various incarnations of logic that actually show up in theorem provers or the logic language Prolog. There are also mathematical applications to foundations of and problems in concurrent languages.

There is no mathematical model for OOP.
Relational algebra in the mathemaical model for SQL. It was created bt E.F. Codd. C.J. Date was also a reknown cientist who helped with this theory. The whole idea is that you can do every operation as a set operation, affecting a lot of values at the same time. This of course means that the database engine has to be told WHAT to get out, and the database is able to optimize your query.
Both Codd and Date criticized SQL because they were involved in the theory, but they were not involved in the creation of SQL.
See this video: http://player.oreilly.com/videos/9781491908853?toc_id=182164
There is a lot of information from Chris Date. I remember that Date criticized the SQL programming language as being a terrible language, but I cannot find the paper.
Teh critique was basically that most languages allow to write expressions and assign variables to those expressions, but SQL does not.
Since SQL is a kind of logical language, I guess you could write relational algebra in Prolog. At least you would have a real language. So you could write queries in Prolog. And since in prolog you have a lot of programs to interpret natural language, you could query your database using natural language.
According to Uncle Bob, databases are not going to be needed when everyone has SSD, because the architecture of SSDs means that access is so fast as RAM. So you can have all your objects in RAM.
https://www.youtube.com/watch?feature=player_detailpage&v=t86v3N4OshQ#t=3287
The only problem with ditching SQL is that you would end up without a query language for the database.
So yes and no, relational algebra was used as inspiration for SQL, but SQL is not really an implementation of relational algebra.
In the case of the Lisp, things are different. The main idea was that implementing the eval function in Lisp you could have the whole language implemented. That's whe the first Lisp implementation is only half a page of code.
http://www.michaelnielsen.org/ddi/lisp-as-the-maxwells-equations-of-software/
To laugh a little bit: https://www.youtube.com/watch?v=hzf3hTUKk8U
The importance of functional programming all comes down to curried functions and lazy calls. And never forget environments and closures. And map-reduce. This all means we will be coding in functional languages in 20 years.
Now back to OOP, there is no formalization of OOP.
Interestingly, the second OO language ever created, Smalltalk, only has objects, it doesn't have primitives or anything like that. And the creator, Alan Kay, explicitly created blocks to work exactly as Lisp functions.
Some people claim OOP could maybe be formalized using category theory, which is kind of set theory but with morphisms. A morphism is a structure preserving map between objects. So in general you could have map( f, collection ) and get back a collection with all elements being f applied.
I'm pretty sure Lisp has that, but Lisp also has functions that return one element in a collection, that destroys the structure, so a morphism is a especial kind of function and because of that, you would need to reduce and limit the functions in Lisp so that they are all morphisms.
https://www.youtube.com/watch?feature=player_detailpage&v=o6L6XeNdd_k#t=250
The main problem with this is that functions don't exist independently of objects in OOP, but in category theory they do. They are therefore incompatible. You could develop a new language in which to express category theory.
An experimental theoretical language created explicitly to try to formalize OOP is Z. Z is derived from requirements formalism.
Another attempt is Luca Cardelli's formalism:
Javahttp://lucacardelli.name/Papers/PrimObjImp.pdf
Javahttp://lucacardelli.name/Papers/PrimObj1stOrder.A4.pdf
Javahttp://lucacardelli.name/Papers/PrimObjSemLICS.A4.pdf
I'm unable to read and understand that notation. It seems like a useless excercise, since as far as I know, no one has ever implemented this the way lamba calculus was implemented in Lisp.

As I know, Formal grammars is used for description of syntax.

Related

What do different programming paradigms offer?

There are lots of different programming languages in 4 different paradigms:
Object-Oriented
Functional
Logical
Procedural
I could write a program in all programming paradigms e.g a fraction that I could write it using classes in OOP and also I could write it using functions in a functional programming language. So why do we need diferent proglangs and paradigms?
According the the master Hal Abelson almost every programming language is built upon three things:
Primitive elements
Means of combination
Means of abstraction
I write almost since some esoteric languages, like BrainFuck, doesn't have means of abstraction.
So what do one paradigm offer that another doesn't? Well a different solution to these 3 and perhaps that has a more suitable expressiveness for the certain tasks. I won't go into specifics since it becomes very opinion based so I suggest you try learning to program in the different paradigms and find out for yourself.
Now procedural is usually what you have at the hardware level no matter what language you are programming in so it is the real thing while all the others are more abstract.
Programming paradigms exists for the benefit of programmers themselves. They all represent different attempts at creating a common platform of abstraction that are as beneficial as possible when starting to solve arbitrary problems. Turing completeness clearly states that any program can basically be written in any programming language that satisfies a certain basic set of rules. Therefore it makes little difference once the program is running what paradigm it is written in. The important part is that there is a person or a group behind it that can maintain or enhance it well (and then again we are back at the persons writing the program).

What's the difference between object-oriented and dynamic programming

I know that dynamic programming refers to an approach where we tend to break down a complex problem into smaller parts. In other words, it's a divide-and-conquer paradigm. Object-oriented programming also uses the concept of classes and modules, and therefore follows the separation of concerns (SoC) principle. Can we therefore say that OO is an example of dynamic programming?
Note: Dynamic here doesn't mean dynamic typing or dynamic scripting language. It refers to the general approach.
Dynamic programming is an algorithm designing approach.
Object Oriented programming is more like a code organising methodology.
Comparing them is like comparing kilometre with kilogram.
(And Linear programming is also a totally different thing. It is for optimizing complex linear equations. It is more mathematics than programming. And Integer programming is a special case of it.)
As far as I can infer from the first few paragraphs of the Wikipedia article, dynamic programming is about identifying subproblems that were already solved to reduce the run time, which of course requires splitting a problem into smaller ones, but the point is that this "happens at runtime": you're not looking for problems that can be solved by the same approach, you're looking for equivalent problems that have the same solution.
OOP, or other programming paradigms are about recognizing problems that can be solved in the same manner, with the same algorithms. Dynamic programming is not a paradigm, it does not tell you how to structure your program. It tells you how an algorithm can be specified so that it can take advantage of solutions of subproblems.

As OOAD is to OOP what is the equivalent for functional programming?

I've recently forayed into the world of functional programming (FP) and am wondering how to "think functionally" for even moderately sized applications? Especially w.r.t. the analysis and design of FPs.
With OOP we're trained to think in terms of objects, their attributes and relations. We model our analyses/designs using class and sequence diagrams. However, the same models seem to be a bad fit when designing for FPs. What are the equivalent modeling paradigms for functional programming? It seems DFDs maybe a good fit but I maybe wrong.
For example: I was thinking of designing a simulation of Monopoly, the board game using Haskell, just to learn the language. When doing OOAD you come up with classes like board contains items that have attributes/methods attached to it. You have player and various other objects and their associated relations that can be captured in a class diagram. And their interactions in a sequence diagram. However, these modeling paradigms doesn't seem to transfer well for functional programs. So just "how" do you model functionally?
Note: I'm looking for concrete references/examples that can explain how to analyze and design functional programs given that I'm coming from a heavily object-oriented way of thinking/modeling.
According to Simon Peyton Jones:
The language in which you write profoundly affects the design of
programs written in that language. For example, in the OO world, many
people use UML to sketch a design. In Haskell or ML, one writes type
signatures instead. Much of the initial design phase of a functional
program consists of writing type definitions. Unlike UML, though, all
this design is incorporated in the final product, and is
machine-checked throughout.
Source: Masterminds of Programming
So instead of drawing all the fancy UML diagrams, you actually write type definitions coupled with undefined in the design phase.
All of my programming these days consists of single-person projects. If I were collaborating on a project with other programmers, I think that writing type definitions and using undefined would be a good approach.
But I gather what you're really looking for is some advice about how you can learn to think functionally. So here are some thoughts.
When programming in Haskell, there are two ways I think about the program I'm writing.
If the program is mathematical, I think of the program as a set of equations.
Otherwise, I tend to think of the program as one or more chains of of data transformations. (So perhaps DFDs would be useful.)
So in your Monopoly example, my first thought would be to figure out how I'm going to represent the state of the board (e.g., which properties have houses, who owns them). Then I might have a function that transforms the board when someone buys a property, and other functions for other things players might do. (There's also monads for representing state, State and StateT. I might use them, if and when I feel they will make the code clearer, but I usually keep things basic to start.)
One of the mistakes I made most often as a beginner was to create a lot of unnecessary classes and data types.
Short answer: composition of smaller programs.
You first study the problem before you, then you develop a set of small operations (often in the form of combinators) that you reckon make sense in that problem's context, and finally you build the solution around those operations. I'm under the impression that all packages found on Hackage follow this approach.
In this way the final solution is (more often than not) simple, clear and elegant. As you can appreciate the aforementioned set of small operations you choose for your solution is critical; with practice, you'll develop the sensibility to pick it wisely.
My book suggestion is Pearls of Functional Algorithm Design, by Richard Bird, Google Books (preview). In this book you'll learn about the calculational approach to functional programming, which I think is most valuable.
Two books you might be interested in:
Structure and Interpretation of Computer Programs - a classic intro to CS textbook in Scheme. I think it's a must for programmers interested in FP.
How to Design Programs - similar to SICP, slightly more modern and focuses on design. The language of choice here is Racket.
If you want a hands-on project in Haskell, I'd recommend Write Yourself a Scheme in 48 Hours, a wonderful tutorial for implementing an interpreter for Scheme. AST manipulation is where FP (and especially Haskell) shines, so I think writing an interpreter is a good experience for new FP programmers.
My perspective regarding the FP vs OO analysis and design debate is the following:
OOAD and DDD (Domain-Driven Design) are very useful tools for software systems decomposition;
FP has types, OO has classes and interfaces: they are dual in different worlds;
FP has type instances, OO has class instances (aka, objects in OO);
Use composition in FP, where in OO you would use inheritance;
Both FP and OO languages come with polymorphic constructs;
Both FP and OO use collections (sets, lists and maps) to make connections between instances (of types in FP, and of classes in OO);
Associations in FP are typically implemented as collections of instance IDs, whereas absensein OO they are implemented as collections of references to the memory locations of objects. This comes from the immutability property of data structures in FP.
Most books in FP, like those referred in the other answers before mine, do not show you how to design (aka, decompose) complex real-world problems. They generally demonstrate FP's features with very short examples (e.g., compare them with the examples in Craig Larman's Applying UML and Patterns excelent book, and judge yourself).
For something more close to what could be called Functional-Oriented Analysis and Design (FOAD), I recommend these:
Elixir in Action
Domain Modeling Made Functional: Tackle Software Complexity with Domain-Driven Design and F#
Functional and Reactive Domain Modeling
Functional Programming in Scala
DDD, OOAD, and FOAD, can be implemented in any programming language, however some programming languages offer constructs that make these approaches easier or harder to implement, but they are perfectly practical. This is evident by the many sources you can find discussing DDD in the context of FP.
Dr. Alan Kay said this regarding the essence of OOP (here):
OOP to me means only messaging, local retention and protection and
hiding of state-process, and extreme late-binding of all things. It
can be done in Smalltalk and in LISP. There are possibly other systems
in which this is possible, but I'm not aware of them.
Following this statement, Joe Armstrong, one of Erlang's creator, an FP language with important uses in the industry (e.g., WhatsApp), argues that Erlang is perhaps the most OO language around (see this interview also featuring Ralph Johnson).
Also, some say that Erlang is the best language that captured the essence of OO programming: the passing of messages between objects.
Hope this was helpful.
I can only speak from the perspective of Erlang OTP. We think in terms of processes, which have a state and functions. So in the state the process will have all the "variables" and handler functions react to data the process receives in its message queue. They act on the received data, possibly alter their own state, possibly return some data and/or have some side effects. The state can be stored in a map or a record or any other valid data type. Usually we define a record called state() or loopData().

Does functional programming replace GoF design patterns?

Since I started learning F# and OCaml last year, I've read a huge number of articles which insist that design patterns (especially in Java) are workarounds for the missing features in imperative languages. One article I found makes a fairly strong claim:
Most people I've met have read
the Design Patterns book by the Gang of
Four (GoF). Any self respecting programmer
will tell you that the book is
language agnostic and the patterns
apply to software engineering in
general, regardless of which language
you use. This is a noble claim.
Unfortunately it is far removed from
the truth.
Functional languages are extremely
expressive. In a functional language
one does not need design patterns
because the language is likely so high
level, you end up programming in
concepts that eliminate design
patterns all together.
The main features of functional programming (FP) include functions as first-class values, currying, immutable values, etc. It doesn't seem obvious to me that OO design patterns are approximating any of those features.
Additionally, in functional languages which support OOP (such as F# and OCaml), it seems obvious to me that programmers using these languages would use the same design patterns found available to every other OOP language. In fact, right now I use F# and OCaml every day, and there are no striking differences between the patterns I use in these languages vs. the patterns I use when I write in Java.
Is there any truth to the claim that functional programming eliminates the need for OOP design patterns? If so, could you post or link to an example of a typical OOP design pattern and its functional equivalent?
The blog post you quoted overstates its claim a bit. FP doesn't eliminate the need for design patterns. The term "design patterns" just isn't widely used to describe the same thing in FP languages. But they exist. Functional languages have plenty of best practice rules of the form "when you encounter problem X, use code that looks like Y", which is basically what a design pattern is.
However, it's correct that most OOP-specific design patterns are pretty much irrelevant in functional languages.
I don't think it should be particularly controversial to say that design patterns in general only exist to patch up shortcomings in the language.
And if another language can solve the same problem trivially, that other language won't have need of a design pattern for it. Users of that language may not even be aware that the problem exists, because, well, it's not a problem in that language.
Here is what the Gang of Four has to say about this issue:
The choice of programming language is important because it influences one's point of view. Our patterns assume Smalltalk/C++-level language features, and that choice determines what can and cannot be implemented easily. If we assumed procedural languages, we might have included design patterns called "Inheritance", "Encapsulation," and "Polymorphism". Similarly, some of our patterns are supported directly by the less common object-oriented languages. CLOS has multi-methods, for example, which lessen the need for a pattern such as Visitor. In fact, there are enough differences between Smalltalk and C++ to mean that some patterns can be expressed more easily in one language than the other. (See Iterator for example.)
(The above is a quote from the Introduction to the Design Patterns book, page 4, paragraph 3)
The main features of functional
programming include functions as
first-class values, currying,
immutable values, etc. It doesn't seem
obvious to me that OO design patterns
are approximating any of those
features.
What is the command pattern, if not an approximation of first-class functions? :)
In an FP language, you'd simply pass a function as the argument to another function.
In an OOP language, you have to wrap up the function in a class, which you can instantiate and then pass that object to the other function. The effect is the same, but in OOP it's called a design pattern, and it takes a whole lot more code.
And what is the abstract factory pattern, if not currying? Pass parameters to a function a bit at a time, to configure what kind of value it spits out when you finally call it.
So yes, several GoF design patterns are rendered redundant in FP languages, because more powerful and easier to use alternatives exist.
But of course there are still design patterns which are not solved by FP languages. What is the FP equivalent of a singleton? (Disregarding for a moment that singletons are generally a terrible pattern to use.)
And it works both ways too. As I said, FP has its design patterns too; people just don't usually think of them as such.
But you may have run across monads. What are they, if not a design pattern for "dealing with global state"? That's a problem that's so simple in OOP languages that no equivalent design pattern exists there.
We don't need a design pattern for "increment a static variable", or "read from that socket", because it's just what you do.
Saying a monad is a design pattern is as absurd as saying the Integers with their usual operations and zero element is a design pattern. No, a monad is a mathematical pattern, not a design pattern.
In (pure) functional languages, side effects and mutable state are impossible, unless you work around it with the monad "design pattern", or any of the other methods for allowing the same thing.
Additionally, in functional languages
which support OOP (such as F# and
OCaml), it seems obvious to me that
programmers using these languages
would use the same design patterns
found available to every other OOP
language. In fact, right now I use F#
and OCaml everyday, and there are no
striking differences between the
patterns I use in these languages vs
the patterns I use when I write in
Java.
Perhaps because you're still thinking imperatively? A lot of people, after dealing with imperative languages all their lives, have a hard time giving up on that habit when they try a functional language. (I've seen some pretty funny attempts at F#, where literally every function was just a string of 'let' statements, basically as if you'd taken a C program, and replaced all semicolons with 'let'. :))
But another possibility might be that you just haven't realized that you're solving problems trivially which would require design patterns in an OOP language.
When you use currying, or pass a function as an argument to another, stop and think about how you'd do that in an OOP language.
Is there any truth to the claim that
functional programming eliminates the
need for OOP design patterns?
Yep. :)
When you work in a FP language, you no longer need the OOP-specific design patterns. But you still need some general design patterns, like MVC or other non-OOP specific stuff, and you need a couple of new FP-specific "design patterns" instead. All languages have their shortcomings, and design patterns are usually how we work around them.
Anyway, you may find it interesting to try your hand at "cleaner" FP languages, like ML (my personal favorite, at least for learning purposes), or Haskell, where you don't have the OOP crutch to fall back on when you're faced with something new.
As expected, a few people objected to my definition of design patterns as "patching up shortcomings in a language", so here's my justification:
As already said, most design patterns are specific to one programming paradigm, or sometimes even one specific language. Often, they solve problems that only exist in that paradigm (see monads for FP, or abstract factories for OOP).
Why doesn't the abstract factory pattern exist in FP? Because the problem it tries to solve does not exist there.
So, if a problem exists in OOP languages, which does not exist in FP languages, then clearly that is a shortcoming of OOP languages. The problem can be solved, but your language does not do so, but requires a bunch of boilerplate code from you to work around it. Ideally, we'd like our programming language to magically make all problems go away. Any problem that is still there is in principle a shortcoming of the language. ;)
Is there any truth to the claim that functional programming eliminates the need for OOP design patterns?
Functional programming is not the same as object-oriented programming. Object-oriented design patterns don't apply to functional programming. Instead, you have functional programming design patterns.
For functional programming, you won't read the OO design pattern books; you'll read other books on FP design patterns.
language agnostic
Not totally. Only language-agnostic with respect to OO languages. The design patterns don't apply to procedural languages at all. They barely make sense in a relational database design context. They don't apply when designing a spreadsheet.
a typical OOP design pattern and its functional equivalent?
The above shouldn't exist. That's like asking for a piece of procedural code rewritten as OO code. Ummm... If I translate the original Fortran (or C) into Java, I haven't done anything more than translate it. If I totally rewrite it into an OO paradigm, it will no longer look anything like the original Fortran or C -- it will be unrecognizable.
There's no simple mapping from OO design to functional design. They're very different ways of looking at the problem.
Functional programming (like all styles of programming) has design patterns. Relational databases have design patterns, OO has design patterns, and procedural programming has design patterns. Everything has design patterns, even the architecture of buildings.
Design patterns -- as a concept -- are a timeless way of building, irrespective of technology or problem domain. However, specific design patterns apply to specific problem domains and technologies.
Everyone who thinks about what they're doing will uncover design patterns.
Brian's comments on the tight linkage between language and pattern is to the point,
The missing part of this discussion is the concept of idiom. James O. Coplien's book, "Advanced C++" was a huge influence here. Long before he discovered Christopher Alexander and the Column Without a Name (and you can't talk sensibly about patterns without reading Alexander either), he talked about the importance of mastering idioms in truly learning a language. He used string copy in C as an example, while(*from++ = *to++); You can see this as a bandaid for a missing language feature (or library feature), but what really matters about it is that it's a larger unit of thought, or of expression, than any of its parts.
That is what patterns, and languages, are trying to do, to allow us to express our intentions more succinctly. The richer the units of thought the more complex the thoughts you can express. Having a rich, shared vocabulary at a range of scales - from system architecture down to bit twiddling - allows us to have more intelligent conversations, and thoughts about what we should be doing.
We can also, as individuals, learn. Which is the entire point of the exercise. We each can understand and use things we would never be able to think of ourselves. Languages, frameworks, libraries, patterns, idioms and so on all have their place in sharing the intellectual wealth.
The GoF book explicitly ties itself to OOP - the title is Design Patterns - Elements of Reusable Object-Oriented Software (emphasis mine).
Design Patterns in Dynamic Programming by Peter Norvig has thoughtful coverage of this general theme, though about 'dynamic' languages instead of 'functional' (there's overlap).
Here's another link, discussing this topic: http://blog.ezyang.com/2010/05/design-patterns-in-haskel/
In his blog post Edward describes all 23 original GoF patterns in terms of Haskell.
When you try to look at this at the level of "design patterns" (in general) and "FP versus OOP", the answers you'll find will be murky at best.
Go a level deeper on both axes, though, and consider specific design patterns and specific language features and things become clearer.
So, for example, some specific patterns, like Visitor, Strategy, Command, and Observer definitely change or disappear when using a language with algebraic data types and pattern matching, closures, first class functions, etc. Some other patterns from the GoF book still 'stick around', though.
In general, I would say that, over time, specific patterns are being eliminated by new (or just rising-in-popularity) language features. This is the natural course of language design; as languages become more high-level, abstractions that could previously only be called out in a book using examples now become applications of a particular language feature or library.
(Aside: here's a recent blog I wrote, which has other links to more discussion on FP and design patterns.)
I would say that when you have a language like Lisp with its support for macros, then you can build you own domain-specific abstractions, abstractions which often are much better than the general idiom solutions.
Norvig's presentation alludes to an analysis they did of all the GoF patterns, and they say that 16 of the 23 patterns had simpler implementations in functional languages, or were simply part of the language. So presumably at least seven of them either were a) equally complicated or b) not present in the language. Unfortunately for us, they are not enumerated!
I think it's clear that most of the "creational" or "structural" patterns in GoF are merely tricks to get the primitive type systems in Java or C++ to do what you want. But the rest are worthy of consideration no matter what language you program in.
One might be Prototype; while it is a fundamental notion of JavaScript, it has to be implemented from scratch in other languages.
One of my favorite patterns is the Null Object pattern: represent the absence of something as an object that does an appropriate kind of nothing. This may be easier to model in a functional language. However, the real achievement is the shift in perspective.
And even the OO design pattern solutions are language specific.
Design patterns are solutions to common problems that your programming language doesn't solve for you. In Java, the Singleton pattern solves the one-of-something (simplified) problem.
In Scala, you have a top level construct called Object in addition to Class. It's lazily instantiated and there is only one.You don't have to use the Singleton pattern to get a Singleton. It's part of the language.
Patterns are ways of solving similar problems that get seen again and again, and then get described and documented. So no, FP is not going to replace patterns; however, FP might create new patterns, and make some current "best practices" patterns "obsolete".
As others have said, there are patterns specific to functional programming. I think the issue of getting rid of design patterns is not so much a matter of switching to functional, but a matter of language features.
Take a look at how Scala does away with the "singleton pattern": you simply declare an object instead of a class.
Another feature, pattern matching, helps avoiding the clunkiness of the visitor pattern. See the comparison here:
Scala's Pattern Matching = Visitor Pattern on Steroids
And Scala, like F#, is a fusion of OO-functional. I don't know about F#, but it probably has these kind of features.
Closures are present in functional language, but they need not be restricted to them. They help with the delegator pattern.
One more observation. This piece of code implements a pattern: it's such a classic and it's so elemental that we don't usually think of it as a "pattern", but it sure is:
for(int i = 0; i < myList.size(); i++) { doWhatever(myList.get(i)); }
Imperative languages like Java and C# have adopted what is essentially a functional construct to deal with this: "foreach".
The GoF Design Patterns is coding workaround recipes for OO languages that are descendants of Simula 67, like Java and C++.
Most of the "ills" treated by the design patterns are caused by:
statically typed classes, which specify objects, but are not themselves objects;
restriction to single dispatch (only the leftmost argument is used to select a method, the remaining arguments are considered as static types only: if they have dynamic types, it's up to the method to sort that out with ad-hoc approaches);
distinction between regular function calls and object-oriented function calls, meaning that object-oriented functions cannot be passed as functional arguments where regular functions are expected and vice versa; and
distinction between "base types" and "class types".
There isn't a single one of these design patterns that doesn't disappear in the Common Lisp Object System, even though the solution is structured in essentially the same way as in the corresponding design pattern. (Moreover, that object system precedes the GoF book by well over a decade. Common Lisp became an ANSI standard the same year that that book was first published.)
As far as functional programming is concerned, whether or not the patterns apply to it depends on whether the given functional programming language has some kind of object system, and whether it is modeled after the object systems which benefit from the patterns. That type of object-orientation does not mix well with functional programming, because the mutation of state is at the front and centre.
Construction and non-mutating access are compatible with functional programming, and so patterns which have to do with abstracting access or construction could be applicable: patterns like Factory, Facade, Proxy, Decorator, and Visitor.
On the other hand, the behavioral patterns like State and Strategy probably do not directly apply in functional OOP because mutation of state is at their core. This doesn't mean they don't apply; perhaps they somehow apply in combination with whatever tricks are available for simulating mutable state.
I'd like to plug a couple of excellent but somewhat dense papers by Jeremy Gibbons: "Design patterns as higher-order datatype-generic programs" and "The essence of the Iterator pattern" (both available here: http://www.comlab.ox.ac.uk/jeremy.gibbons/publications/).
These both describe how idiomatic functional constructs cover the terrain that is covered by specific design patterns in other (object-oriented) settings.
You can't have this discussion without bringing up type systems.
The main features of functional programming include functions as first-class values, currying, immutable values, etc. It doesn't seem obvious to me that OO design patterns are approximating any of those features.
That's because these features don't address the same issues that OOP does... they are alternatives to imperative programming. The FP answer to OOP lies in the type systems of ML and Haskell... specifically sum types, abstract data types, ML modules, and Haskell typeclasses.
But of course there are still design patterns which are not solved by FP languages. What is the FP equivalent of a singleton? (Disregarding for a moment that singletons are generally a terrible pattern to use)
The first thing typeclasses do is eliminate the need for singletons.
You could go through the list of 23 and eliminate more, but I don't have time to right now.
I think only two GoF Design Patterns are designed to introduce the functional programming logic into natural OO language. I think about Strategy and Command.
Some of the other GoF design patterns can be modified by functional programming to simplify the design and keep the purpose.
Essentially, yes!
When a pattern circumvents the missing features (high order functions, stream handling...) that ultimalty facilitate composition.
The need to re-write patterns' implementation again and again can itself be seen as a language smell.
Besides, this page (AreDesignPatternsMissingLanguageFeatures) provides a "pattern/feature" translation table and some nice discussions, if you are willing to dig.
Functional programming does not replace design patterns. Design patterns can not be replaced.
Patterns simply exist; they emerged over time. The GoF book formalized some of them. If new patterns are coming to light as developers use functional programming languages that is exciting stuff, and perhaps there will be books written about them as well.
In the new 2013 book named "Functional Programming Patterns- in Scala and Clojure" the author Michael.B. Linn does a decent job comparing and providing replacements in many cases for the GoF patterns and also discusses the newer functional patterns like 'tail recursion', 'memoization', 'lazy sequence', etc.
This book is available on Amazon. I found it very informative and encouraging when coming from an OO background of a couple of decades.
OOP and the GoF patterns deal with states. OOP models reality to keep the code base as near as possible to the given requirements of reality. GoF design patterns are patterns that were identified to solve atomic real world problems. They handle the problem of state in a semantic way.
As in real functional programming no state exists, it does not make sense to apply the GoF patterns. There are not functional design patterns in the same way there are GoF design patterns. Every functional design pattern is artifical in contrast to reality as functions are constructs of math and not reality.
Functions lack the concept of time as they are always return the same value whatever the current time is unless time is part of the function parameters what makes it really hard to prrocess "future requests". Hybrid languages mix those concepts make the languages not real functional programming languages.
Functional languages are rising only because of one thing: the current natural restrictions of physics. Todays processors are limited in their speed of processing instructions due to physical laws. You see a stagnation in clock frequency but an expansion in processing cores. That's why parallelism of instructions becomes more and more important to increase speed of modern applications. As functional programming by definition has no state and therefore has no side effects it is safe to process functions safely in parallel.
GoF patterns are not obsolete. They are at least necessary to model the real world requirements. But if you use a functional programming language you have to transform them into their hybrid equivalents. Finally you have no chance to make only functional programs if you use persistence. For the hybrid elements of your program there remains the necessity to use GoF patterns. For any other element that is purely functional there is no necessity to use GoF patterns because there is no state.
Because the GoF patterns are not necessary for real functional programming, it doesn't mean that the SOLID principles should not be applied. The SOLID principles are beyond any language paradigm.
As the accepted answer said, OOP and FP all have their specific patterns.
However, there are some patterns which are so common that all programming platforms I can think of should have. Here is an (incomplete) list:
Adapter. I can hardly think of a useful programming platform which is so comprehensive (and self-fulfilled) that it does not need to talk to the world. If it is going to do so, an adapter is definitely needed.
Façade. Any programming platforms that can handle big source code should be able to modularise. If you were to create a module for other parts of the program, you will want to hide the "dirty" parts of the code and give it a nice interface.
Interpreter. In general, any program is just doing two things: parse input and print output. Mouse inputs need to be parsed, and window widgets need to be printed out. Therefore, having an embedded interpreter gives the program additional power to customise things.
Also, I noticed in a typical FP language, Haskell, there is something similar to GoF patterns, but with different names. In my opinion this suggest they were there because there are some common problems to solve in both FP and OOP languages.
Monad transformer and decorator. The former used to add additional ability into an existing monad, the latter add additional ability to an existing object.
I think that each paradigm serves a different purpose and as such cannot be compared in this way.
I have not heard that the GoF design patterns are applicable to every language. I have heard that they are applicable to all OOP languages. If you use functional programming then the domain of problems that you solve is different from OO languages.
I wouldn't use functional language to write a user interface, but one of the OO languages like C# or Java would make this job easier. If I were writing a functional language then I wouldn't consider using OO design patterns.
OOP and FP have different goals. OOP aims to encapsulate the complexities/moving parts of software components and FP aims to minimize the complexity and dependencies of software components.
However these two paradigms are not necessarily 100% contradicting and could be applied together to get the benefit from both worlds.
Even with a language that does not natively support functional programming like C#, you could write functional code if you understand the FP principles. Likewise you could apply OOP principles using F# if you understand OOP principles, patterns, and best practices. You would make the right choice based on the situation and problem that you try to solve, regardless of the programming language you use.
Some patterns are easier to implement in a language supporting FP. For example, Strategy can be implemented using nicely using closures. However depending on context, you may prefer to implement Strategy using a class-based approach, say where the strategies themselves are quite complicated and/or share structure that you want to model using Template Method.
In my experience developing in a multi-paradigm language (Ruby), the FP implementation works well in simple cases, but where the context is more complicated the GoF OOP based approach is a better fit.
The FP approach does not replace the OOP approach, it complements it.
It does, in that a high-level functional PL (like OCaml, with classes, modules, etc.) certainly supersedes OOP imperative languages in type versatility and power of expression. The abstractions do not leak, you can express most of your ideas directly in the program. Therefore, yes, it does replace design patterns, most of which are ridiculously simplistic compared to functional patterns anyhow.
In functional programming, design patterns have a different meaning. In fact, most of OOP design patterns are unnecessary in functional programming because of the higher level of abstraction and HOFs used as building blocks.
The principle of an HOF means that functions can be passed as
arguments to other functions. and functions can return values.
The paramount characteristic of functional programming, IMHO, is that you are programming with nothing but expressions -- expressions within expressions within expressions that all evaluate to the last, final expression that "warms the machine when evaluated".
The paramount characteristic of object-oriented programming, IMHO is that you are programming with objects that have internal state. You cannot have internal state in pure functions -- object-oriented programming languages need statements to make things happen. (There are no statements in functional programming.)
You are comparing apples to oranges. The patterns of object-oriented programming do not apply to function programming, because functional programming is programming with expressions, and object-oriented programming is programming with internal state.
Brace yourselves.
It will aggravate many to hear me claim to have replaced design patterns and debunked SOLID and DRY. I'm nobody. Nevertheless, I correctly modeled collaborative (manufacturing) architecture and published the rules for building processes online along with the code and science behind it at my website http://www.powersemantics.com/.
My argument is that design patterns attempt to achieve what manufacturing calls "mass customization", a process form in which every step can be reshaped, recomposed and extended. You might think of such processes as uncompiled scripts. I'm not going to repeat my (online) argument here. In short, my mass customization architecture replaces design patterns by achieving that flexibility without any of the messy semantics. I was surprised my model worked so well, but the way programmers write code simply doesn't hold a candle to how manufacturing organizes collaborative work.
Manufacturing = each step interacts with one product
OOP = each step interacts with itself and other modules, passing the product around from point to point like useless office workers
This architecture never needs refactoring. There are also rules concerning centralization and distribution which affect complexity. But to answer your question, functional programming is another set of processing semantics, not an architecture for mass custom processes where 1) the source routing exists as a (script) document which the wielder can rewrite before firing and 2) modules can be easily and dynamically added or removed.
We could say OOP is the "hardcoded process" paradigm and that design patterns are ways to avoid that paradigm. But that's what mass customization is all about. Design patterns embody dynamic processes as messy hardcode. There's just no point. The fact that F# allows passing functions as a parameter means functional and OOP languages alike attempt to accomplish mass customization itself.
How confusing is that to the reader, hardcode which represents script? Not at all if you think your compiler's consumers pay for such features, but to me such features are semantic waste. They are pointless, because the point of mass customization is to make processes themselves dynamic, not just dynamic to the programmer wielding Visual Studio.
Let give an example of the wrong premise you state.
The adapter pattern we have in OOP as usecase adapter such as in cleanarch and ddd can be implemented in Functional via the monad variation of Option.
You are not replacing them but transforming them.

OOP vs Functional Programming vs Procedural [closed]

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 5 years ago.
Improve this question
What are the differences between these programming paradigms, and are they better suited to particular problems or do any use-cases favour one over the others?
Architecture examples appreciated!
All of them are good in their own ways - They're simply different approaches to the same problems.
In a purely procedural style, data tends to be highly decoupled from the functions that operate on it.
In an object oriented style, data tends to carry with it a collection of functions.
In a functional style, data and functions tend toward having more in common with each other (as in Lisp and Scheme) while offering more flexibility in terms of how functions are actually used. Algorithms tend also to be defined in terms of recursion and composition rather than loops and iteration.
Of course, the language itself only influences which style is preferred. Even in a pure-functional language like Haskell, you can write in a procedural style (though that is highly discouraged), and even in a procedural language like C, you can program in an object-oriented style (such as in the GTK+ and EFL APIs).
To be clear, the "advantage" of each paradigm is simply in the modeling of your algorithms and data structures. If, for example, your algorithm involves lists and trees, a functional algorithm may be the most sensible. Or, if, for example, your data is highly structured, it may make more sense to compose it as objects if that is the native paradigm of your language - or, it could just as easily be written as a functional abstraction of monads, which is the native paradigm of languages like Haskell or ML.
The choice of which you use is simply what makes more sense for your project and the abstractions your language supports.
I think the available libraries, tools, examples, and communities completely trumps the paradigm these days. For example, ML (or whatever) might be the ultimate all-purpose programming language but if you can't get any good libraries for what you are doing you're screwed.
For example, if you're making a video game, there are more good code examples and SDKs in C++, so you're probably better off with that. For a small web application, there are some great Python, PHP, and Ruby frameworks that'll get you off and running very quickly. Java is a great choice for larger projects because of the compile-time checking and enterprise libraries and platforms.
It used to be the case that the standard libraries for different languages were pretty small and easily replicated - C, C++, Assembler, ML, LISP, etc.. came with the basics, but tended to chicken out when it came to standardizing on things like network communications, encryption, graphics, data file formats (including XML), even basic data structures like balanced trees and hashtables were left out!
Modern languages like Python, PHP, Ruby, and Java now come with a far more decent standard library and have many good third party libraries you can easily use, thanks in great part to their adoption of namespaces to keep libraries from colliding with one another, and garbage collection to standardize the memory management schemes of the libraries.
These paradigms don't have to be mutually exclusive. If you look at python, it supports functions and classes, but at the same time, everything is an object, including functions. You can mix and match functional/oop/procedural style all in one piece of code.
What I mean is, in functional languages (at least in Haskell, the only one I studied) there are no statements! functions are only allowed one expression inside them!! BUT, functions are first-class citizens, you can pass them around as parameters, along with a bunch of other abilities. They can do powerful things with few lines of code.
While in a procedural language like C, the only way you can pass functions around is by using function pointers, and that alone doesn't enable many powerful tasks.
In python, a function is a first-class citizen, but it can contain arbitrary number of statements. So you can have a function that contains procedural code, but you can pass it around just like functional languages.
Same goes for OOP. A language like Java doesn't allow you to write procedures/functions outside of a class. The only way to pass a function around is to wrap it in an object that implements that function, and then pass that object around.
In Python, you don't have this restriction.
For GUI I'd say that the Object-Oriented Paradigma is very well suited. The Window is an Object, the Textboxes are Objects, and the Okay-Button is one too. On the other Hand stuff like String Processing can be done with much less overhead and therefore more straightforward with simple procedural paradigma.
I don't think it is a question of the language neither. You can write functional, procedural or object-oriented in almost any popular language, although it might be some additional effort in some.
In order to answer your question, we need two elements:
Understanding of the characteristics of different architecture styles/patterns.
Understanding of the characteristics of different programming paradigms.
A list of software architecture styles/pattern is shown on the software architecture article on Wikipeida. And you can research on them easily on the web.
In short and general, Procedural is good for a model that follows a procedure, OOP is good for design, and Functional is good for high level programming.
I think you should try reading the history on each paradigm and see why people create it and you can understand them easily.
After understanding them both, you can link the items of architecture styles/patterns to programming paradigms.
I think that they are often not "versus", but you can combine them. I also think that oftentimes, the words you mention are just buzzwords. There are few people who actually know what "object-oriented" means, even if they are the fiercest evangelists of it.
One of my friends is writing a graphics app using NVIDIA CUDA. Application fits in very nicely with OOP paradigm and the problem can be decomposed into modules neatly. However, to use CUDA you need to use C, which doesn't support inheritance. Therefore, you need to be clever.
a) You devise a clever system which will emulate inheritance to a certain extent. It can be done!
i) You can use a hook system, which expects every child C of parent P to have a certain override for function F. You can make children register their overrides, which will be stored and called when required.
ii) You can use struct memory alignment feature to cast children into parents.
This can be neat but it's not easy to come up with future-proof, reliable solution. You will spend lots of time designing the system and there is no guarantee that you won't run into problems half-way through the project. Implementing multiple inheritance is even harder, if not almost impossible.
b) You can use consistent naming policy and use divide and conquer approach to create a program. It won't have any inheritance but because your functions are small, easy-to-understand and consistently formatted you don't need it. The amount of code you need to write goes up, it's very hard to stay focused and not succumb to easy solutions (hacks). However, this ninja way of coding is the C way of coding. Staying in balance between low-level freedom and writing good code. Good way to achieve this is to write prototypes using a functional language. For example, Haskell is extremely good for prototyping algorithms.
I tend towards approach b. I wrote a possible solution using approach a, and I will be honest, it felt very unnatural using that code.