See InformalHistoryOfProgrammingIdeas, EarlyHistoryOfSmalltalk, GroundBreakingLanguages, WorseIsBetter.
Functional languages have already had quite a strong impact on mainstream languages, but only indirectly. [It takes ages] for programming ideas to hit the mainstream. JavaLanguage is the first example of a mainstream language which allows some of what SmalltalkLanguage enabled back around 1972.
However, Java focuses almost exclusively on manifestly-typed object-orientation as its primary concept. It completely ignores two related features which make Smalltalk powerful: code blocks and closures. These Smalltalk features were actually derived from LispLanguage, which at the time (1972) could only be called a proto-functional language. The first truly functional language was probably SchemeLanguage, in 1975.
Because the functional ideas inherent in Lisp were not fully developed at the time Smalltalk was created, the conceptual emphasis in Smalltalk was on object-orientation, derived from SimulaLanguage. If Smalltalk had been able to draw from Scheme instead of Lisp, there's a strong chance that it would have had a more functional bent, which might have affected the languages which were influenced by Smalltalk.
Instead, Scheme came along just a little too late to directly influence the mainstream. Only recently have we started to see functional features appearing in mainstream languages. Perl and JavaScript both support lambda-calculus-compliant closures, and first-class procedures, which are fully realized incarnations of the original concepts on which Smalltalk's somewhat limited code blocks and closures were based. PythonLanguage has also recently moved in this direction.
I predict that functional features will slowly be adopted by most mainstream languages over the next decade or two. Java will be the last new mainstream language that's completely non-functional (PunIntended). The power of these functional capabilities is too great for language designers to ignore.
Note that I'm not saying that current functional languages will become mainstream languages. Rather, just as mainstream languages have absorbed object-oriented concepts, they will also absorb functional concepts.
Anyone writing a language today who isn't familiar with Scheme, HaskellLanguage, and MlLanguage may as well throw in the towel right now. Unless they plan to invent the next great paradigm, they will not succeed. I think it's impossible, in 2001, to write a language without taking functional concepts into account. (Of course I'm reminded of AndrewTanenbaum telling LinusTorvalds that writing a MonolithicKernel in 1991 was a fundamentally bad idea...)
-- TonTobius? (?)
Alas, MicroSoft had to come up with another non-functional, mainstream, language, and spoil your nice prediction... If CsharpLanguage had true closures it would be a real improvement over JavaLanguage. -- CarlosScheidegger
You're wrong, closures are in the 2.0 spec, and it is a real improvement over JavaLanguage.
Actually I think that means he's right. He said that if C# had true closures then it would be a real improvement. You're saying that C# v2.0 will have real closures, and it is a real improvement. You appear to be in ViolentAgreement.
Above comment is from a SlashDot discussion. I found it highly interesting, so I copied it here (with permission). If you think it doesn't belong here, please flame me, not the author. -- FalkBruegmann
I have to agree with this. Extrapolating from current language evolution I predict that in 20 years time programmers will be using . . . Lisp. Except it won't be called Lisp and it might have a different syntax, but it will offer all the power and flexibility of the world's second oldest programming language. Now that's progress! -- NoelWelsh
That *is* progress. -- DavidSarahHopwood
Lisp-like languages with non-Lisp-like syntax:
Except it won't be called Lisp and it might have a different syntax, but it will offer all the power and flexibility of the world's second oldest programming language.
People keep propagating this misconception, i.e. that the lisp syntax is in some way a problem. Nothing could be further from the truth: Lisp's syntax is in fact one of its strongest advantages! Study just enough lisp to understand what DEFMACRO does, and why an expression like
(html (:h1 "foo") (:p "Some text"))can be viewed as either data or a program, and you'll know why Lispers are so reticent of letting go of their beautifully designed EssExpressions. -- AlainPicard
Right on.
Viewing expressions as either data or a program is not dependent on Lisp's syntax. If Lisp had been defined with an infix syntax and TermTrees? in place of EssExpressions, it would have been just as expressive, and probably a lot more popular. SyntaxDoesMatter?. -- DavidSarahHopwood
DylanLanguage is Lisp with infix syntax. It's almost as expressive (missing some of the more obscure parts of the MetaObjectProtocol, and CompilerAtRunTime?), but IMHO easier to read. However, it's just as unpopular as Lisp. I suspect marketing clout matters a whole lot more than expressiveness, and both matter more than syntax. -- JonathanTang
Or it could be that functional languages are as stillborn as videophones. I don't mean to imply that the low-fi network we have today is better than videophones; It's just that we've been waiting a long time for Lisp to displace its less capable sisters and were aren't much further along.
It's not that Lisp will displace its less capable sisters. Its less capable sisters will absorb ideas from Lisp in the same way that JavaLanguage is SmalltalkMinusMinus. PythonLanguage is getting more FunctionalProgrammingLanguage features, JavaScript is an object-functional hybrid, the C++ STL is functional programming in C++. LispLanguage isn't popular for many of the same reasons SmallTalk isn't popular (I know lots of people use both of them, but its nothing compared to JavaLanguage) but the ideas are slowly shifting into mainstream programming. You can wait for the future to arrive in mainstream languages, or you jump to the future today (or 15 years ago). -- NoelWelsh
Absorption can only go so far. The central idea of functional languages is that there is no stored program state -- no variables. So even the venerable while loop is verboten. Java, Python, and other mainstream languages cannot absorb such a radically different idea. -- IanRae
Nonsense. A while construct in HaskellLanguage can be written as
while cond body = do testResult <- cond if testResult then body >> while cond body else return ()''Actually, the "while cond body" part is likely to be factored out:
while cond body = loop where loop = do testResult <- cond if testResult then do {body; loop} else return ()''''And you're both cheating. This while loop does useful work only by being in a monad, presumably IO. Though you'll surely tell me, a State Monad is still purely functional, the code above isn't. This is dysfunctional code embedded in Haskell. A while "loop" in Haskell is usually implemented using "iterate" and "find", but that requires thinking and doesn't prove a stupid point.''
TThe assertion "the code above isn't [purely functional]" is patently false. Both definitions given are indeed purely functional, the do-notation notwithstanding; it's just syntactic sugar. The following definition is equivalent and uses only lambda, function application and if-then:
while = \cond body -> cond >>= (\testResult -> if testResult then (body >> while cond body) else (return ()) )This definition, just like the others, satisfies all of Haskell's normal criteria of referential transparency and so forth. Granted, it can only be applied to monadic values, but since a value with a monadic type simply represents an action of some kind, it's no different than a while loop in any other language.
The main problem with Smalltalk is that it allows the programmer to do too much with too little effort. If you are going to create a new product and you have a bunch of people working for you, probably you would like these programmers to have the least ability to do any harm, to have them totally isolated and constrained, using your favorite compiler and each suspecting of each other. Make them compete with periodic evaluations and comparisons with their peers. The task will take longer because of the language you chose, but it does not matter since you can always make them work overtime, besides most people have C++ and Java skills, so they can be more easily replaced. Actually a boss gets rewarded if he can make his people work overtime, it shows that the boss knows the tools of the trade, so the one that gets rewarded for using a low productivity compiler like C++ and Java, is the manager. The project takes longer and he gets paid for his time, not for the time it takes to deliver. This is the usual reward for being incompetent.
Since more and more people work in C++ and Java, using another language make you look like a risk taker. Managers are not risk takers, since one pitfall may mean termination. Stockholders are risk takers (since they can invest in many stocks at the same time), but they do not make the decisions.
OTOH, there are real advantages, both technical and social, to using a language that is well-supported and popular.
[The fallacy is in assuming that only one language can be used. Multiple languages (at least three: for heavy numeric, business logic and scripting, respectively) can happily coexist in a single application.]
Software is not developed by a conspiracy of managers! AssumeIgnoranceNotMalice, AssumeStupidityNotMalice. But also KeepAnOpenMind, matey. Maybe there are good reasons for people using the languages they use.
[There are good reasons, for some value of 'good'. They just aren't software engineering (hardly surprising, as that does not really exist as yet) reasons.]
See EconomicEfficiencyIsNotEngineeringEfficiency for further explication of one part of this issue. - JayOsako
And maybe there aren't. Corporations have a terrible habit of deciding that some language or other will be the language used for all future development (until they choose the next one), irrespective of its suitability for many of the problems addressed.
In that case you should be looking to ChangeYourOrganization one way or another. Where I work currently, someone recently tried to lay a one-language law down in a business area (Java for everything). I stood and fought my ground for an analytics subsystem being in C++, and won my case. It boiled down to knocking down a lot of straw men, and finally implementing the new subsystem in both C++ and Java and showing that JNI latency was not an issue. If I had not been able to get the issue judged on its merits I would have started looking to work elsewhere because LifesTooShort to deal with a losing company. This is not just rhetoric, I have actually left an employer for similar reasons before. In that case, it was because they were too scared to start moving business functionality in C as part of a necessary shift from a dying language (Clipper). That company is now out of business.
As an imperativist, I am wary of functional languages (and i'm really talking about pure functional languages here) because I don't see how to distribute state around the program. Consider the case of an client-side FTP library: there is all sorts of state associated with the connection, from a socket handle and buffers to connection status and the current directory; there is also loads of behaviour, such as methods for sending commands, reading responses, etc. In an OO language, I can bundle up the state into an object, and present a simple interface to the rest of the program. In a procedural language, I can bundle up the state in a struct, and still provide a pretty simple interface through a set of procedures to manipulate the struct. In a functional language, I can still have a struct, but it's now immutable, which means that if a function wants to 'change' it, it has to make a new version and hand that back to the caller, who then has to use that instead.
In simple cases, this is still okay, but I can imagine more complex cases where some component on one side of the program wants to change the state of a component over on the other side, without bothering the code that's currently calling it. For example, let's say that in a P2P application (whose details are intentionally left blank!), when the NetworkBrowser, in the course of retrieving a file, discovers a new rendezvous server, it wants to update the RendezvousServerRegistry, without bothering the calling code with any kind of 'oh, by the way: I've found a new RV server' sort of message. In an imperative language, as long as the component has (or can get) a pointer to its target, it's trivial; in a functional language, it's impossible. Well, not impossible, but the only way i can see to do it is for every function which might want 'side-effects' of this sort to take the world as an argument and return a new version of the world with any changes it wants to make, which would suck.
In short, whilst functional languages may be very elegant for programming in the small, I suspect that they can't handle programming in the large. I'd be most interested to hear how functional programmers would tackle this situation.
I assume you do know that you can rebuild the imperative state framework in a few lines of Haskell? After that, you can write any portion of your code you want in imperative style, and any portion in traditional functional.
I didn't know that; my knowledge of functional languages is rather lacking. Still, using the functional language to reproduce an imperative language is a cop-out! How would my example be most cleanly implemented in a functional language?
The example above (network protocol client) would be, I think, most cleanly implemented by CoRoutines with local state. You often get suboptimal results from trying to apply imperative flow-models to the functional framework - it restricts you a lot.
Not surprising - it would be like emulating the relational model in procedural code or something. So, in the example, would it be that we would have a function registerRendezvousServer, which would be a coroutine with some internal state (a list of servers), and the network-browsing code would just call it when it found a new rendezvous server? That seems most straightforward. ThankYou.
Now, how do I do it in a pure functional language?
How do you do threads in a functional language? In particular, how do they communicate? Futures?
Functional languages sometimes provide implicit threading. I am yet to see a usage of threads which is not either an optimisation or a nice solution to a producer / consumer problem (or then, a misuse of threads where select() or somesuch would be more appropriate). But for the first one, functional languages mostly shift the optimisation burden off the programmer; and for the second one, lazy lists provide a better solution.
But yes, sometimes you want exactly that, threads. How you get them depends on the language, but eg Haskell would (does?) implement them as monadic operations of the IO monad, and using them will be boringly alike imperative languages.
[There's also O'Haskell. In O'Haskell an Object, a Process, a Thread are basically the same and they communicate by exchanging messages. This results in a program that is easy to understand, has clearly defined interfaces and is reactive without much effort. I like this far better than classical threads.]
StructureAndInterpretationOfComputerPrograms does a fine job of contrasting the imperative, object-based approach with the functional approach. It arrives at the tentative conclusion that neither is clearly better for all applications. However, most functional “languages” (as contrasted with programming methodologies) also allow an imperative style. It is possible to use Haskell just as "a better C", to quote BjarneStroustrup out of context. ;-)
Is it not also possible to use imperative languages in a functional style? Perhaps not C or Java (although you can sort of do BlocksInJava), but Python certainly has first-class functions, closures, etc. Ah, of course this is the result of the MainstreamInfluenceOfFunctionalLanguages!
It has already been hinted at with STL, but functional programming in CeePlusPlus is possible by using templates to calculate the whole (sub)program at compile time, called TemplateMetaprogramming in C++ circles. Functional programming at compile time with OOP at run time seems to be a powerful tool.
A whole lot more can be done as well - see FunctionalProgrammingInCpp. -- JohnFletcher