The barrier to take-up of language innovation

I have been thinking recently about why so much programming language innovation is not taken up. this is my take on it...

the people doing the innovating are usually very clever - to design a new language or a new language innovation you have to be clever.

unfortunately, the majority of programmers are not as clever, so while the innovators see the benefit of their work, the majority of programmers don't understand it.

what is needed is for programming language innovations to be packaged or distilled into an easy to use tool that does not require a degree in logic theory or programming language theory to be used.

this seems to be even more difficult than doing the original innovation.

mark.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

A little self-serving

unfortunately, the majority of programmers are not as clever, so while the innovators see the benefit of their work, the majority of programmers don't understand it.

I have a similar explanation for why my program doesn't compile. Clearly I am much cleverer than the compiler.

Really, over the last several decades, many new languages have been picked up in industry for many purposes. Maybe your search for an explanation should continue ...

Well, sometimes you are

Strongly typed languages will in the general case reject code that is type-safe but too complicated for the compiler to prove its type safety.

Maybe

That might happen occasionally, but it's more often the case the code that a compiler rejects really is not typesafe. And it should reject it--handily :)

OK Mr. Smartypants

Then which one is wrong, your compiler for rejecting the program, or you for thinking that your solution was expressible in the language/semantics that your compiler accepts?

Well, then I'd say the

Well, then I'd say the actual cleverer one is the person who wrote that compiler and made it so that it'd reject such programs (because of insufficiently powerful implementation to check their type safety entirely) ... instead of accepting them and let mayhem happen at runtime, no? ;)

[Edit: and I'd call it "pragmatic humility in the wisdom" from that compiler's writer, then. ;)

Thankfully so!

And it's good that they do, because if the compiler can't figure out what the code means, the maintainer who inherits the code certainly can't do so either.

I don't mean to suggest that johncowan falls in this camp, but the level at which the "sophisticated is good" zealots have no regard for human factors in engineering is a source of continuing amazement to me. Research languages exist to explore options. Production languages exist to solve real-world problems.

While it hasn't always been easy, the main challenge in BitC hasn't been choosing the right research to integrate. It's been figuring out how to integrate it in such a way that mainstream programmers might have some hope of using that power effectively. Whether, where, and how I've succeeded (or not) remains to be seen, and I expect the process to be humbling. My point is: neither the latest cool type system nor the ability to accept arbitrarily complex programs inherently constitute "features" in real-world language designs.

but the level at which the

but the level at which the "sophisticated is good" zealots have no regard for human factors in engineering is a source of continuing amazement to me. Research languages exist to explore options. Production languages exist to solve real-world problems.

Jonathan,

Are you attending this year's SPLASH conference? One of the workshops, PLATEAU, is centered on these sorts of issues that you are flaming the forums about. I am not complaining about these flames, but I sense they are closed-fist, deep-pocketed anger and that you need a place to vent this pent-up venom. CHI conferences are not the right place, since the sort of interfaces they focus on generally don't deal with language representation. PLATEAU would be your platform.

[Edit: I also suggest you might wish to try writing to a more general audience, such as Communications of the ACM. You mention the C# language's primitive support for Unboxing in another thread, but don't explain it to those less familiar, and assume no explanation is necessary. By simply ranting you perhaps release some stress, but do not advance others' understanding of your argument. There remains a wall, and to knock it down you have to stop advancing your argument and start advancing others' understanding. Ditto for temporal constraints. Flesh these out with real-world examples of why they matter. There are also LtU forum members who have tangential interest to what you are discussing, such as Tommy McGuire and his Austin Compiler project. Just saying.]

Cheers,

Thanks for the suggestions

Z-Bo: I appreciate your comments about more background. When posting here on LtU, I guess I assume that I am writing to an audience that either knows about things like unboxing, or will ask. Also thanks for pointing out the issue of tone; I'll try to watch that better.

The thing that set me off here was probably an accident of phrasing. Johncowan's comment seemed (to me) to be so focused on perfecting the capacity to express high complexity that it never pauses to ask whether supporting complexity is good. Please note: I don't say that he intended this interpretation or that he himself advocates complexity.

I see a lot of posts here that (in my opinion) reflect a failure to think systemically. Looking back over the last 30 years, it seems to me that as PL research has delved more deeply into theory, it has slowly lost sight (as a field) of systemics. That's a shame, because in computer science we build things, and systemic views are therefore terribly important.

As you gently imply, this isn't really the place for this debate, so I'll leave it at that and get back to work.

Sounds like a great paper for Onward 2010

I see a lot of posts here that (in my opinion) reflect a failure to think systemically. Looking back over the last 30 years, it seems to me that as PL research has delved more deeply into theory, it has slowly lost sight (as a field) of systemics. That's a shame, because in computer science we build things, and systemic views are therefore terribly important.

I also did not intend for you to infer this:

As you gently imply, this isn't really the place for this debate, so I'll leave it at that and get back to work.

On the contrary, I think LtU is suitable for this discussion if you actually provide academic or trade press references to back up your view point. Even cross-references to the bitc mailing list where you discuss boxing would be helpful, but also would illustrate that you've not thoroughly discussed this topic (discussions in the BitC archive are pretty fragmented and conversational rather than a tight, cogent argument). As I understand it, based on my knowledge of the literature, there is no tutorial about this sort of stuff available for general consumption.

It's not that I don't understand these issues. I am pretty candid when I don't understand you. ;-) It's that I can't simply point to a link on the Internet so that others can read about it. You wondered why people ignore it? It simply suffers from not targeting any audience. Even the Origins of BitC paper is not really thorough enough for me to link to, say, an engineer at Google.

theorists vs. experimentalists

Re: comment-62366:

I see a lot of posts here that (in my opinion) reflect a failure to think systemically. Looking back over the last 30 years, it seems to me that as PL research has delved more deeply into theory, it has slowly lost sight (as a field) of systemics. That's a shame, because in computer science we build things, and systemic views are therefore terribly important.

In his poignant essay How To Criticize Computer Scientists, Douglas E. Comer addresses an oft-encountered “misimpression that all researchers agree on the overall aims of CS research”:

They do not. In particular, CS has inherited two, quite opposite approaches from roots in mathematics and engineering.

  1. Researchers who follow the mathematical paradigm are called theorists, and include anyone working in an area that has the terms “analysis”, “evaluation”, “algorithms”, or “theory” in the title.
  2. Researchers who follow the engineering paradigm are called experimentalists, and include most people working in areas that have the terms “experimental”, “systems”, “compiler”, “network”, or “database” in the title.

Knowing the tradition from which a researcher comes provides the basis for a well-aimed insult.

See also The Identity Crisis In Computer Science. (That essay sounds to me like a jab against computational thinking, but what do I know?)

Many other barriers

While I don't disagree that what you say is a barrier, there are many others and I feel your reason is incomplete.

Intuitive means familiar. This means improvement will generally not be intuitive, unless one can associate it with concrete physical behaviors in day-to-day life.

There is a lot of inertia. Even if you do provide a new tool, it is unlikely that others will be able to apply it to their own work due to the multiple of compatibility, debugger/IDE integration, and other issues. Providing a new paradigm as a framework or library, thus, offers better opportunity for adoption than might a nicer package of a new language or tool, even if it is painful to use. (Once a bunch of people are painfully slogging through libraries and design-patterns and self-discipline, perhaps they'll appreciate a language.)

Being right too early is the same as being wrong. Innovation won't catch on unless people see the immediate need for it. When innovation is finally needed, people won't often look to the decades-old implementation of it; they'll look to the spiffy 'new' language that reinvents that wheel. Why? Because the new language is the one being advertised and getting news, and the old tool was written by a known crank or hand-waving visionary (that being the man who was right too early). Most of our 'innovative' languages today are integrating concepts that had prototypes in 1970. Perhaps in 2050, we'll start seeing wide acceptance of the ideas of this decade.

That said, I think a lot of people underestimate "the majority of programmers". Most people - even programmers - aren't abstract thinkers. They learn by concrete need and example. But, given concrete need and example, most programmers catch on to new ideas really quickly. And need is never more concrete than when they've been slogging through frameworks and design patterns and accidental complexity.

But need for concrete examples does make it difficult to explain scalability issues to people who haven't already been screwed by them.

Tangent

Intuitive means familiar. This means improvement will generally not be intuitive, unless one can associate it with concrete physical behaviors in day-to-day life.

I've heard this argument before, but I think it's only approximately right. People have a wide range of experience from which to draw, and you can often make an improvement to an interface by building on a more appropriate metaphor. Furthermore, intuitive and familiar are not the same thing if you just measure familiarity in terms of exposure time. An intuitive concept is one that is already grasped. That's a function of simplicity of the concept as well as exposure.

Exercise of a concept - raw,

Exercise of a concept - raw, repeated application - matters more than simplicity with regards to whether people find things intuitive and familiar. Exposure hardly matters; even intelligent people have troubles grasping recursion, monads, or modus tollens before using them a few times - even after exposure (and these are not complex ideas). Humans have a phenomenal capacity for handling complexity and organized chaos in their day-to-day lives. See a recent XKCD strip, for a not atypical example.

Simplicity has its own rewards, though... such as getting things right every time (even under stress) and streamlining the thought process. In addition to simplicity, you might also consider properties such as composition and scalable composition.

I don't believe that appealing to familiarity should be high priority. When a good metaphor is available, then by all means favor it! But anything (good or bad) can become intuitive and familiar. Not just anything can be made simple, composable, or scalable.

If it isn't intuitive you

If it isn't intuitive you haven't worked hard enough ;)

In some sense this mirrors the socialist realist claim that "nature" is a prejudice, is bourgeois ideology. Fortunately we don't have seek very far for the reason of getting stuck: capitalist economy is still alive and screws our minds. I wonder which language everyone will use after the next revolution?

Pfft. How come you don't

Pfft. How come you don't know?

I wonder which language everyone will use after the next revolution?

UNCOL, of course! ;)

Two other reasons. First,

Two other reasons.

First, many languages just aren't new enough to be interesting. At best, they are refinements or straightforward advancements, but nothing revolutionary or even evolutionary enough to excite most programmers.

Second, those languages that are interesting are usually complicated which can scare people away, or the mindset is incompatible with most programmers. I'd put C++ and Scala into the former category...powerful but made for a special kind of programmer who likes clever languages.
Take Haskell as an example of the latter, it works well with people who are into very elegant math, while most everyone else just scratches their head.

Hard to Keep Up

I think the main problem is that the ease of using a language is directly tied to its ecosystem: the tools, IDEs, editors, books, blogs, etc. surrounding it. Java and C# are really easy to learn because Eclipse and Visual Studio will interactively help you fix errors in your code. NewLanguageOfTheWeek meanwhile, doesn't even have syntax coloring in your favorite editor or error messages.

This gets increasingly challenging as time goes on: the tools for existing languages keep getting better so the user's expectation of comfort goes up.

Ah! Good point. If you are

Ah! Good point.

If you are designing a language, you should also be designing its library and IDE, or at least a IDE plugin. Taken at the extreme, you have Smalltalk, which was/is a lot more than a parser/interpreter. Smalltalk's development environment is a part of the language, and accordingly a Smalltalk plugin for Eclipse would gather very little interest (since it wouldn't be smalltalk anymore!).

On the other extreme, you have languages that are designed to be interoperable with another language; take Scala and Java. Scala is often a slave to Java's development environments and libraries. The hackery involved in achieving Java integration has basically made decent IDE support very difficult to achieve. Also, Scala's semantics are too complicated to easily build the traditional error-tolerant heuristic compiler that would support most IDE features. To avoid these issues, IDE-thinking really needs to be done upfront or very early in any modern language design.

I'm much more interested in the former, where the language define its own IDE, this would necessarily be the case if the language was structured, visual, or semi-visual. However, adoption seems to prefer the latter as developers generally want to reuse old code, tools, development practices, and so on.

As a UI person, I really

As a UI person, I really like the idea of non-textual programming languages, but I'm skeptical about them:

* A mouse is a painfully low bandwidth form of user input. Multitouch could make this better, but it will take some really brilliant polymaths to be able to design a visual programming language and usable multitouch interface for it.

* Programs-as-text encourage us to use our language centers to reason about programs, which seems to be a good mental fit, and possibly a better one than our visual centers.

* It's really helpful to be able to discuss code vocally.

* Language adoption is much easier when you can easily slap snippets of code in a blog post, tweet, email, etc.

* Naming is one of the most fundamentally important parts of reasoning, so even a visual system will still likely be pretty text-centric.

As much as I think monospace text is a primitive medium, it does have a lot going for it.

I agree that text (and

I agree that text (and names) should be a major part of any new kind of combined language/environment. The point would be replacing keyboard with touch, which means getting rid of free-form unstructured text and and replacing it with some kind of touch-optimized structured editor.

Naming and Reasoning

Naming is one of the most fundamentally important parts of reasoning, so even a visual system will still likely be pretty text-centric.

Naming, in modern programming languages, is mostly accidental complexity. There are exactly two essential uses for names within programming languages:

  • We need names in data to describe complex relationships and graphs. This would, for example, include the use of surrogate or autonum keys in a relational database.
  • We need names in computation for open modular composition and live programming - i.e. integrating and extending services. And in this case we're talking about something closer to an object reference or URI than a symbolic name.

The common uses of names to hook regular libraries together, or describe types and functions are non-essential. They might be convenient - and even a non-textual language might benefit from a database of functions with searchable descriptions and global names. But in that case, those names may belong to the IDE rather than the language.

I think the "blog-post, tweet, and e-mail" note is a stronger point in favor of names, but it might be more interesting to move most libraries into distributed services so that we can use URIs and webkeys to hook applications together instead of names and libraries.

Perhaps it would help if our visual languages focus on tiny network and DI apps (with services-as-libraries) rather than monolithic apps (with libraries-as-services).

The common uses of names to

The common uses of names to hook regular libraries together, or describe types and functions are non-essential. They might be convenient - and even a non-textual language might benefit from a database of functions with searchable descriptions and global names. But in that case, those names may belong to the IDE rather than the language.

I've been thinking about this a lot lately. Names are designed humans for reading and comprehension, for finding things and abstracting what would otherwise be verbose visual connections.

In any case, we can separate names from language constructs, and make the binding of name to construct an IDE concern (say via search), say something like Conal's Tangible Values. However, my original comment was that the IDE would be considered a part of the language as far as the programmer is concerned. The language designer is not just designing syntax and semantics, they are also designing a complete user experience. In this case, the language designer can decide how to segment complexity across different components, but they can't ignore it!

Perhaps it would help if our visual languages focus on tiny network and DI apps (with services-as-libraries) rather than monolithic apps (with libraries-as-services).

Yahoo Pipes?

Hmm, the most important use

Hmm, the most important use case for names that I'd consider is so that we can attach ideas to pieces of code. People think in names. The fact that names serve as references between regions of code is a secondary concern to me.

or in flows of bytes

People don't necessarily think in names. Some of us don't, some of the time. In code I tend to use them as arbitrary mnemonic labels subject to change, which a compiler uses to construct graphs I visualize, where those graphs are the real meaning. In other words, I often think in shapes ... which change, so I think in simulations where words are part of the accompanying sound track.

When I dive into someone else's code (e.g. on every project I join), I treat names as misdirection. To understand a given symbol, I visit every place in the code where a symbol appears, so I can infer it's meaning in terms of its apparent role everywhere it gets used. So here I'm trying to find meaning in the role(s) taken in the execution graph, and the name used is 1) a marker I can search for, and 2) a clue about what an original writer was thinking.

But I think in terms of a model of how executing code behaves, generally in terms of bytes moving around. Names help only slightly.

Great comment!

And you are so right David.

I use the same strategies.

Do you use any tools to aid you?

Personally, I find names

Personally, I find names very useful in remembering what the heck I wrote in the past. I wouldn't be inclined to use a language that didn't include some kind of naming system, as I couldn't think of another notation to keep track of my abstractions.

I agree that informal naming systems are not universal. If you are stuck maintaining code or using lots of libraries that you are not extremely familiar with, then ya, life sucks.

I don't understand your comment "ya, life sucks"

You're making a value judgment. Aren't you a researcher who spends all of his time developing prototypes that aren't production-ready and mainly intended to communicate possible shifts in how to accomplish tasks?

I am just saying. Value judgments say more about your personal experience and what you prefer to work on that what is social mores and norms.

Put another way, you are the same person who told me a few months ago that it was important to question everything including simple ideas like a code wiki. Where is that attitude now?

I believe I am consistent.

I believe I am consistent. The point was that we need names for ourselves, but we might not find someone else's names to not be very useful, and even misleading according to our own understanding. The point is that programming is still a one way conversation with the machine when it should also somehow be a N-way conversation between humans (code wiki idea). In the latter case, because you are communicating with someone else, you begin to agree on a common vocabulary/style that makes the communication more efficient (as with natural language).

The current state of affair is not that great, hence the "life sucks" comment.

I just didn't understand

I just didn't understand your reply to my comments, then.

I was asking David if he used any tools to support a style of code exploration he and I both used, to see what he found effective.

There will always be scenarios where new developers are joining projects. Where I work, management has finally admitted that we have too high a cost for training new developers and we haven't put any thought into how to ease them into more complicated systems. Some new developers working on custom, isolated projects are phenomenally productive because they are working on brand new projects with no real dependencies. Others work on legacy projects that involve rewriting old applications with very poor code.

I've also seen myself, such as when diving into MySQL. SQLite, and PostgreSQL engine code, using the exact techniques described by David.

Given my experience bears out in several scenarios, from poor coding on custom one-off in-house apps to large-scale open source software development, I'd say what David is explaining is an important principle of code reading.

There's some basic things you do when reading code.

1. Figure out what every language construct in the code you are reading does. You may not need to know every feature in a language, but you have to know the subset of the language the library or project whose code you are reading makes use of.
2. Collect all references to a variable in the system.
3. Figure out who is calling what, and try to establish why.
4. Determine where the unit tests are, and look at them to see if they indicate what the code is supposed to do. Since most unit tests do not effectively test roles fulfilled by an object and instead mock the object's implementation details, this is often not a great source of information. Many developers write poor tests.
5. If the code uses design-by-contract, then your job is much easier since you know exactly what the code allows and your job is simply to figure out why it is that way, if the comments are not sufficient enough.

Print out 20,000 lines of code. It's a short novel. I've traced through rat's nest code before where it was a 10,000 line long procedure (!), and refactored it.

There are things that transcend naming, of course, too. Style is more important than naming. A lot of code is simply written a certain way because the developer doesn't trust or doesn't know a better way. I've worked with programmers who were afraid to write code differently and learn an extra idiom simply because they didn't want extra mental strain. Style tends to indicate inexperience or experience, too. Dr. Richard Hipp's style is very distinctive, and he is an Expert programmer.

Given my experience bears

Given my experience bears out in several scenarios, from poor coding on custom one-off in-house apps to large-scale open source software development, I'd say what David is explaining is an important principle of code reading.

This is basically the thought that "abstractions lie," that in order to understand how to use code we must look literally at how it works. This is not how it should be, but is how it is. I would take this further: don't bother reading the code statically, but read the code dynamically: run it in the debugger and play with it. This is how I basically figured out (to varying degrees of success) how to use the Eclipse IDE or the Scala compiler. I find the dynamic method to be more efficient for my own needs, as the amount of code I'm touching usually is not a significant chunk of the total code in question (e.g., Eclipse).

The fact that you can read code at all probably encourages the code reading approach. There is something to be said for strong encapsulation where the provider of the module can't depend on you being to able to examine it's construction. Perhaps always assume that my code is closed source even if its open, and design abstractions/write documentation accordingly.

I don't see it happening (in my lifetime)

I had a quick conversation with someone from Microsoft recently who was kind of bragging about how good his API he wrote was, and I deconstructed it very swiftly by saying what he really wanted to do was hide the representation of an automaton from the user and only expose an interface for defining URI navigation in terms of composable sequences and that the actual transition function therefore shouldn't matter (can be late-bound), and all I need to care about is that the overall transition function yields only one possible valid transition, and can explain why it reached that transition. This means you can in effect let the client provide the parsing algorithm and input format, but give them a default implementation with basic property guarantees. Their approach exposed the representation to clients and did not give the clients any correctess guarantees e.g. about an object's initial state. What kind of B.S. is that?

In my experience, companies somehow think their ad-hoc APIs are super awesome and super proprietary, when they are not even based on hard math and simply based on ad-hoc virtual class-like structures. Why does that make their ideas worth me signing an NDA to discuss how to make better and build smarter APIs? Most developers don't get it. It's not just C#. Haskell programmers assert weird things to me too. Most programmers don't even know what properties they should be shooting for in an interface. At best they can tell you the performance of a string function.

[Edit: I guess my moral was to illustrate that over-relying on names and not some spatial relationships defined in terms of math can cause a need to peer inside code. Edit #2: e.g. thinking API design is about naming things the right way. Names are a consequence of problem domain analysis and identifying the jargon of the problem domain expert, but names' adherence to the problem domain being modeled must be driven by math.]

Out of curiosity: I wonder

Out of curiosity: I wonder what you expect from "hard math" and what does it include and exclude? You use it a bit like a master signifier. My impression is that it means many things to many in particular when it comes to programming.

It has to be driven by the problem domain

It also means "many things to [me] in particular when it comes to programming."

In the example I give above, I am talking about how we compose the definition of a resource and guarantee that resource can exist. I then talk about how you could use parser generator ideas to encapsulate all access to resources.

The Scheme community, inspired by Paul Graham, they have used continuations to achieve the same effect. Jay McCarthy has done some interesting work in this area to make the idea more practical, from an engineering view point (it's not clear to me how Paul scaled the approach he used at Viaweb in the early '90s, without Jay's engineering insights). See Jay's OOPSLA 2010 and ICFP 2009 papers.

So there are two ways I could probably approach very similar problems mathematically. And the more approaches you can identify for a problem the more likely you are to understand the mental model required for thinking about this problem, and what the trade-offs are in various problem solving techniques for that domain.

tools can help remove barriers

Z-bo: Do you use any tools to aid you?

To avoid undirected discussion, I want to make sure this is about barriers to take-up in innovation, and about programming languages generally. Let's avoid a discussion of shallow issues folks can discuss any time. :-)

I agree with folks elsewhere when they say tools we use with a language affect whether a language is useful, so a language designer should be thinking about how any new thing is going to play with work flow tools, like debuggers. You want to constantly ask yourself: When someone uses this, how are they going to answer questions? When a user tries empirical experiments, will any of them work given tools at hand?

I wish I had more tools to aid the process I descibed, but for the last seven years it has just been tags under emacs. This issue is my litmus test whenever someone suggests I use an editor. I ask: how am I going to search for every place a symbol appears without a lot of trouble? This is easy in emacs if you can generate tags for all your source files, but you typically need to add a new key binding for tags-search, something like (define-key global-map "\M-?" 'tags-search)

And then M-, (alt or meta comma) takes you to the next hit on your search instantly, and this iteration is independent of other things you do in the emacs UI. That means you can stop and make files editable and resume your search where you left off without starting over from scratch.

Let's not start an emacs sub-thread just because I mentioned it. However, folks providing any IDE support should think about how to easily search for everywhere a string or regular expression appears. And if you can do this without restarting the search every time you take any other action in an environment, you get big bonus points. Language designers should avoid constructs where searching for regular expressions in an editor will not answer questions a developer is trying to answer.

(I tried to think of an example, but I don't have one. At times Smalltalk has seemed awkard for breaking the keyword parts of selectors in pieces -- the #at:put: selector has an expression between at: and put: where it appears in code -- but the regular expression "at:.*put:" will work in emacs tags search if both parts appear on the same line in source code. I work mostly in C and C++, so don't infer I'm developing now in Smalltalk.)

When I start working on a new project, I can often perform gross level optimizations -- provided the code already works at the moment and I can test whether I broke it -- even if I don't understand how the code works. Basically I make invariant preserving transformations, so if it worked before, it should still do the same thing, just less awkwardly now. So when I improve something, and folks ask me if I figured out how the code works, they're very surprised when I say that wasn't necessary. :-)

But to really do something useful, you need to grok the semantics of code not expressed in correct syntax, grammar, and type declarations. Maybe there's a lesson in there for language designers -- I dunno. I put a lot of contract info in code comments, which really bothers the anti-comments crowd. (I suspect some comment haters want all proof removed they wrote code that doesn't do what they intended; how can you prove their intent?)

For me to improve existing code, I need to build at least three different models 1) what code actually does, 2) what might be a good thing for code to be doing, and 3) what original writers thought code was doing. Sometimes (2) has several variants and (3) matches none of them, so I have to conclude a design has bugs and change to one of the (2) models.

If language designers can think of more ways of capturing intent along side explicit do-what-I-say code instructions, this would be very helpful. In practice I like to substitute equivalents to test for equivalence empirically. So it would be nice to see support for that in languages, if it can be helped by any small choices that seem like free options. Object-oriented languages, for example, make it somewhere easier to substitute pieces with identical interfaces.

A big barrier to adopting innovation is "I can't tell what's going on." So visibility into actual behavior should be included in language offerings. I'm vaguely planning to let any browser connect to my language's runtime so system state can be browsed like a virtual file system. (What happened during that unit test anyway? Just open up a browser right now.)

It's funny

You are so right again.

The Code Maps front page article motivated me to write a deconstructive critique of what is wrong with modern IDEs like Visual Studio, NetBeans and Eclipse. It's a essay in progress. I'll throw it up on arxiv when it's done to get feedback.

What you portray here is to me an important user story not captured by these IDEs. Eclipse Galileo fixed some of the navigation problems with Eclipse IDE

What I find funny is the total lack of empirical studies on usability for navigation. As I recall Galileo was just revamped based on what the developers thought people wanted. Not sure there was much HCI influence or studies to figure out what people did most often in the IDE.

It's funny you mention Emacs, which despite being very old and having a limited interface does a better job supporting navigation than Visual Studio 2008. A better comparator would be Hopscotch IDE for Newspeak. Check it out if you haven't. Navigation is at the very core of Hopscotch, as all Smalltalk IDEs are. It's funny that all other non-Smalltalk languages have taken 30+ years to catch up in this regard, and still aren't quite there yet with modern Smalltalk (in other words, Newspeak).

The trouble with so much HCI research in IDEs is its more about adding features and not about subtraction or redoing core abstractions. Too much is about MIT-style institutions trying to demonstrate how clever they are by creating something fancy. You could improve things so much just by getting the basic principles right that have been there since the first IDEs.

When I dive into someone

When I dive into someone else's code (e.g. on every project I join), I treat names as misdirection.

That seems like a painfully pessimistic attitude. I don't assume every identifier in code I read is the One True Name, but I figure most names add some positive information. You seem to be saying that not only are they at zero information, they're negative. I shudder to think of what kind of code you've been subjected to.

Unintentional Lies of Omission

I don't assume every identifier in code I read is the One True Name, but I figure most names add some positive information. You seem to be saying that not only are they at zero information, they're negative. I shudder to think of what kind of code you've been subjected to.

Not necessarily. Partial positive information can be worse than none at all if it leads to unwarranted assumptions: If something does X and Y but is named "foo" you'll have to at least briefly investigate it; if it's named "doThingX" you might just go with that.

And it's not just a matter of "use better names". You can't predict what assumptions a reader of the code will have, and can't list every possible subtlety of purpose for a piece of code in a name of reasonable length.

If you and the writer share

If you and the writer share similar assumptions, then the code will be easier to read by you. If you are used to reading code from someone, then reading new code by this person will be easier. If you are working closely with someone, he is reading your code and you are reading his, then it will be easier.

If you are reading code by some random person whose assumptions you don't understand, then sure. You need to understand their styles and assumptions first before you can easily read their code. Nothing new.

Note that this is a

Note that this is a relatively easy hypothesis to check historically. When less support was expected, you'd want to see more innovation (though controlling for other factors may be difficult). Similarly, when building tool support is relatively cheap, because of shared tools (thing emacs, unix pipelines).

Debatable. Historically, IDE

Debatable. Historically, IDE support has been pretty crappy or spartan, so many developers did not depend on them in ways that were very language integrated (think emacs). Many veteran language designers still think Emacs is good enough for their own use, and it reflects in the languages they design.

Today is very different. IDEs no longer suck, and so many developers are very used to their features.

These claims are exactly the

These claims are exactly the sort of thing that be (a) checked rigorously rather than anecdotally and (b) can then be used to substantiate (or disprove) the original claim.

Your claims were that

Your claims were that languages are more innovative when they don't depend on great support (counter-example: smalltalk) or that they have good tool support WHEN building that support is easy. The last claim is a bit bizarre as the tools are constantly evolving along with the standards on feature sets. Emacs support used to be the best we could do in the early 90s, but today would not even warrant a second glance.

Yes, if all the tool technology and expectations stayed constant while the languages evolved, then we could check them with rigor. Unfortunately, that is not the case.

*My* claim was that clams of

*My* claim was that clams of that nature (that were not made by me) are open to relatively easy empirical test.

Apologies. I'm confusing

Apologies. I'm confusing claims and the usefulness that the claims have in answering the questions we are concerned with.

I agree, but anecdotally...

I agree with Ehud that empirical test is a good way to pursue this.

Anecdotally, however, I can say that having grown up before the prominence of IDEs, I find that I have little use for them beyond augmented code browsing. This is probably entangled with the fact that most of my dev experience has been on UNIX, where IDEs are far behind their Windows/Mac competitors.

Good Libraries, source level

Good Libraries, source level debuggers, profilers, etc. take a lot of work to produce and are important for developers. Focusing on whether those tools are integrated by a GUI app, shell and CLI tools, or an overgrown extensible editor shouldn't be the main issue.

Um... duh?

Wait, I thought I posted this earlier but must not have hit post.

People come up with new languages all the time and it is pretty easy to get a few people to try them out. In absolute numbers, language adaptation prbly hasn't fallen all that much by any sane metric. It's only by sane economic metrics that language innovation has diminished in importance.

And that's your answer: You can't find many business problems that are hung up waiting for a new language to improve returns over the next few years. No demand, no uptake. There are too many programmers and too much low hanging fruit that can be harvested by lousy programmers -- thus few to nil current business problems for which a new language is a significant part of a much needed solution.

No uptake because there's no current money in it.

Clever?

Clever isn't really the correct attribute. As dmbarbour points out, most people can be clever when pressed.

No, (imo) the problem lies in a lack of concern for human factors. These directly drive adoption. Here at LtU, and in academia the push for PLT is rarely how best to make programming languages for people, but far more often how to make the programming language best for machines. Not a huge surprise when designers tend to be heavy CS/Math educated.

New languages tend to be a bit unwieldy or more 'weird' than they need to be. Or worse yet, they tend to be based off of other academic languages that have already failed to gain widespread adoption.

Evidence?

Here at LtU, and in academia the push for PLT is rarely how best to make programming languages for people, but far more often how to make the programming language best for machines.

It's funny, I've found exactly the opposite. "Programs should be written for people to read, and only incidentally for machines to execute," is not a line that comes out of industry (nor have I seen much sympathy for it in my 12 years living in the working world).

I wonder what languages you have in mind, and what your standard is for making languages best "for people." I would hold up Haskell as a huge success in making an ideal language for programmers, with Java and C++ much less so.

I would argue that the ability to reason about Haskell programs builds heavily on centuries of tradition in logic and formal reasoning. On the other hand, C++ (for example) has many language features explicitly aimed at allowing the programmer to be explicit about machine representations ("register", "volatile", "inline", ...).

It's funny, I've found

It's funny, I've found exactly the opposite. "Programs should be written for people to read, and only incidentally for machines to execute," is not a line that comes out of industry (nor have I seen much sympathy for it in my 12 years living in the working world).

And I've found the opposite. Business programmers (I've dealt with) maintain code. They understand the need for readable code. I can't say the same of the academic and non-professionals (scientists, statisticians, etc) I've dealt with. YMMV; anecdotes mean little when the criteria is as subjective as it is.

I wonder what languages you have in mind, and what your standard is for making languages best "for people."

I wasn't talking about languages so much as the focus of discussion and actual research. LtU front page currently has 10 articles, (beginning with First-class modules: hidden power and tantalizing promises and ending with FunLoft reactive, concurrent programming language for posterity) of those only one (Software Development with Code Maps) deals directly with user interface concerns.

As far as research goes I fall towards this paper regarding a C# usability study as a good example of something that (imo) is too rare.

I would hold up Haskell as a huge success in making an ideal language for programmers

And I would hold up Haskell as a huge failure as far as adoption is concerned. Not a rock solid statistic but after ~20 years, I would hope that a "huge success" would match more than .004% online job postings. Even something as relatively new as Scala is way ahead of it on adoption.

I would argue that the ability to reason about Haskell programs builds heavily on centuries of tradition in logic and formal reasoning.

And I would argue that logic and formal reasoning are not exactly the purview of your common frontline developer. Even if they were, that seems at least a bit orthogonal to designing a language so that humans can interact with it well.

Yes, I largely second this.

Yes, I largely second this. Thanks for the C# usability study link (haven't read it yet, only had a quick glance) -- interesting aspect, that they did as early as 2001, btw.

(I mean, other options they had would have been to chose doing so after a couple more years of presence on the market, or say, to wait for C#2, or etc)

Converging on a definition of "best for people"

... anecdotes mean little when the criteria is as subjective as it is.

OK, but I did come up with at least one example contradicting your original claim ("... in academia the push for PLT is rarely how best to make programming languages for people ...") with the SICP mantra.

And I would hold up Haskell as a huge failure as far as adoption is concerned. Not a rock solid statistic but after ~20 years, I would hope that a "huge success" would match more than .004% online job postings.

Well now you're moving the goalposts, to the point of making your argument tautological. Industry selects better languages for people because the languages that industry selects are used more often in industry.

Fine, Haskell doesn't have a lot of marketshare. And Redbook magazine is more widely read than Shakespeare. I thought that we were talking about where the push for making programming languages "best for people" is coming from.

And I would argue that logic and formal reasoning are not exactly the purview of your common frontline developer.

And I would argue that, although that may be true, nevertheless it's a better place to be than where they are. At some point in time, engineers weren't familiar with Calculus either.

There's three essential

There's three essential things that I'm trying to say:

1. The percentage of programming language research done on human factors is far too low.

2. Perhaps as a side effect of 1, the percentage of discussion on sites like LtU on human factor concerns surrounding programming languages is far too low.

3. The amount of time and effort given by programming language creators on human factors compared to other design/implementation aspects is far too low.

It's not terribly complicated...

Well now you're moving the goalposts, to the point of making your argument tautological. Industry selects better languages for people because the languages that industry selects are used more often in industry.

If Haskell were an ideal programming language for developers, why are so few programmers using it after 20 years?

If job postings aren't a viable metric, what readily available measure do you propose for programming language adoption?

(using scala since it's relatively complex/weird compared to mainstream languages and had far less time to gain a foothold)
Amazon search results? (haskell 7570, scala 20050)
Google search results? (haskell 14m, scala 17m)

I believe that if the study done on C# I linked to was done on Haskell, we would find that the language does poorly at some of the usability metrics despite being elegantly built upon logic and formal reasoning. That's subjective though, and without the research or even the community knowledge about human factors within programming languages it's going to be hard to do more than guess.

Popularity is not quality...

If Haskell were an ideal programming language for developers, why are so few programmers using it after 20 years?

Are you serious? What on earth gave you the idea that the quality of a programming language has anything to do with its popularity? You realize you're basically arguing that PHP is a better language than C#, right?

The languages popular in industry tend to be objectively pretty terrible and poorly designed, precisely because they're being shaped by forces other than just "what's best for developers in general".

Without those other factors, a new language built using in-depth research on human factors would fail just as badly as any obscure math-y language, for pretty much the same reasons.

In fact, speaking of MS and human factor research, remember everyone getting upset about the new "Ribbon" UI in MS Office? That's what happens when you let research on human factors drive a design. And while Microsoft has the ability to cram something down its users' throats until they finally realize it's an improvement, most of us don't have that option.

... but quality impacts popularity.

You realize you're basically arguing that PHP is a better language than C#, right?

If you take my point to the extreme, flip the actual criteria I stated, and then ignore reality to make an outlandish scenario, yes.

Certainly there's other contributing factors, but quality of design will effect adoption rate. Haskell has been around long enough, and the usage gap between it and other languages it's competing with for adoption is huge enough that (imo) those other contributing factors cannot account for the whole difference. Since I'm fairly sure we'll all agree that Haskell is a technically solid language, I can't help but think human factors are a problem.

Human factors are at play

Human factors are at play here. Haskell wasn't designed as a language to be adopted en-masse by programmers as they think today. Conventional programmers aren't meant to be Haskell programmers, rather Haskell is meant to help create more Haskell programmers, meaning those that think formally and functionally. Haskell has been a resounding success in this regard, mission accomplished.

Now, a wide adoption rate...you can always get that by shooting for the bottom; e.g., PHP or Perl. Maybe like the difference between Lady Gaga and a singer more obscure but arguably more creative and higher quality (sorry, I just know Lady Gaga).

quality of design will

quality of design will effect adoption rate

It would be nice if that were true. But I doubt there is evidence for it.

My reasoning: 'Quality' is nearly impossible to measure in an objective way. As noted, the correlations between subjective quality and popularity appear quite weak. And, to the limited extent a correlation exists, we are not in position to argue that the causal relationship is from quality → popularity. (That relationship might actually be inverted, or both might be caused by other factors.)

There is stronger evidence for a sort of 'inertia': getting there first is more important than quality... because people are loathe to include multiple independent languages in their projects (especially if the IDE doesn't work across them), because humans are loathe to learn multiple languages that fill the same niche (regardless of quality issues), because intelligent project managers are more likely to develop projects in languages that have a large pool of human resources, et cetera.

With regards to adoption, often 'worse is better' - not because bad quality wins devoted fans, but because bad quality gets there first... and will then have the funding to improve over time.

I wish for quality to affect adoption rate. And maybe it does, on some glacial temporal scale. But without stronger evidence, I suspect it's wishful thinking.

MainSail (Machine

MainSail (Machine Independent SAIL, where SAIL was Stanford AI Language) was definitely a very tiny niche language in the late 1970s. I had some desirable features, ran on PDP-10s (and other machines, hence the MA part), had linked libraries, and _may_ have had some of the lazy features of Algol-60, on which it was based. (I don't know, and neither Wexelbat's "HIstory of Programming Languages" or the Web has much on SAIL or MainSail. Confirming its niche status.)

Why mention it? Because it was a central part of Intel's ECAD program from around the late 1970s to well into the 1990s. (The Wikipedia entry claims it was running commercially as recently as 2005.)

How and why Intel adopted it probably depends a lot on personalities, on those who had used it in school, or liked its "academic" features. But adoption of a language for a central purpose (CAD) was not done lightly, nor was it done on looking around to see that Pascal, COBOL, FORTRAN, or BASIC programmers were most in demand at the time.

Nor was it done on the basis of new hires not liking to learn a new language. It was expected then--and I hope is expected now--that a CS or EE graduate would know enough about theory and algorithms and suchlike to just accept that a new job probably means a few months of deep immersions in the tools and languages his employer uses.

I was at Intel from 1974 to 1986 and knew a lot of the CAD tools people. This was back when commercial CAD meant the Calma and Applicon machines used by Boeing, Lockheed, and mechanical engineers. So Intel developed most of its own tools, including place-and-route tools, including the earliest uses of simulated annealing tools (Timberwolf, done in conjunction with UC Berkeley, as many other projects were done with).

About the time Intel was widely-deploying tools that successfully laid out very large (for the time) chips, which basically worked the first time (a rarity in the industry at that time!), the "Star Wars Software" battle was raging in the theoretical computer science community. Some of the big names in software (Parnas, others) were arguing that the conventional techniques of the time ("structured programming") could not handled millions of lines of code reliably.

Well, some folks were already building chips with the computational complexity equivalent to this, using the best ideas they could steal from the theoretical folks. Shades of Wadler's "mining mathematics for good ideas." (Granted, the issues in real-time control of interceptors, lasers, etc. is not isomorphic to the chip design, layout, verification problem, but there are some similarities. And, importantly, the very latest ideas from academia were used freely, and boldly. It didn't matter if a new hire was "uncomfortable" using MainSail, or if most engineers viewed topological verification as suspiciously as some now view monads or other newfangled ideas from the eggheads (Britspeak: boffins): they simply were told it was part of their job to use the tools that did Continuity Verfication Check (CVS) or that used highfalutin' ideas out of statistical mechanics to "relax" cells into nearly-optimal positions.)

I had my own experiences with using cutting-edge science in interesting ways. (And my work even overlapped with that of Scott Kirkpatrick, the IBM scientist who first published in 1981-2 on simulated annealing.)

One thing that really struck me is that corporations often have need for tools that are somewhat beyond what is publicly advertised, and that they often steal good ideas from other parts of science and turn them into products.

BTW, Intel using MainSAIL may have been "worse is better," but in circa 1980 it is hard to argue that they should've used C, which was just coming on strong, for their particular needs. For sure, probably nearly all of the programmers they hired back around then would've been the then-standard Pascal or maybe FORTRAN programmers, but, like I said, new hires are expected to learn new tools.

(There are probably much more recent examples, but I have the luxury the last 24 years to pick whatever I want to focus on. My friends who work in Silicon Valley startups are using mostly the usual LAMP stack crud. We sometimes get together to talk about cool stuff from category theory, FP, math, and what seems to be about where computing is going once the Twitter Generation has moved on.)

It's funny, I've found

It's funny, I've found exactly the opposite. "Programs should be written for people to read, and only incidentally for machines to execute," is not a line that comes out of industry (nor have I seen much sympathy for it in my 12 years living in the working world).

If you are currently working at a place with unreadable code and/or no way to trace code to requirements (e.g., BDD, TDD, whatever), then you should move on to a different place to work. From stuff I've read that you've written elsewhere on the Internet you're extremely smart and shouldn't waste your brightest years stuck in a place that inflicts pain on you.

On the other hand, it is possible some code you have to read is hard to read for performance issues. This should be documented.

Even in a start-up-similar environment to the one I'm in we try to write readable code. The best code is the one that is peer reviewed at the design and implementation level. Initial prototypes might be ugly guide wire, but eventually they're refactored into extremely good solutions. Only the most runaway cases have bad code -- such is the case with tight deadlines and extreme requirements turbulence. But most business apps don't require tight deadlines or have vague requirements where you have to ask 12 domain experts the same question 12 different ways each just to learn the right answer. I've seen the full spectrum, though.

Uh?

[[ I would hold up Haskell as a huge success in making an ideal language for programmers ]]

Perhaps it is, but only for the tiny subset of programmers who can understand monads?
And I would also add for those programmers who don't care
too much about performance, because I've read that the 'lazy default' has a consequence that the performance can vary a lot in difficult to understand way..

Not *my* view of an ideal language for programers..

I don't want to come off as

I don't want to come off as condescending about the bulk of the population, so bear this in mind...

Imagine the issue is that English has a "basic" language, consisting of ordinary, everyday words about things, actions, names, etc. "John is going to the store."

But it also various more advanced languages, with words like "entropy," "codicil," "mitochondrial," "poset," and so on.

The hope for a universal language, or even a very popular language, would then parallel some of the criticism of languages like Haskell. Perhaps this:

"Perhaps it is, but only for the tiny subset of language users who can understand entropy?"

I came to Haskell after Smalltalk and Lisp, with some bad experiences with Fortran and Basic in the 70s, and to me it was wonderful. Being able to talk about infinite lists as a mathematician would ("Let S be the set of prime numbers") without planning in advance how many elements to compute is both elegant and reduces certain kinds of out of bound errors. ("But our accounting people never anticipated that a salary could exceed a million dollars!")

This is just one example, of course. Other examples would be folks have mentioned, things like dependent typing, guards as filters, and even such simple things as functions returning other functions as values. (Obvious, but there were a few comments here in another thread about how difficult it is for some folks to wrap their heads around this possibility. One of the huge gains from advanced languages is the "mental expansion" that happens when a new approach is actually accessible for experimentation with right at the keyboard.)

It's true that most programmers never really use any college-level math, not even much calculus. (I'll bet 95% of programmers never need to use any of it.) And very few non-math majors even get exposed to set theory, set-builder notation (list comprehensions), or concepts of continuity. The deep connections between programming, logic, and topology are not really visible to them.

But there are a lot of places in the world, even in programming, where such things are very important. LTU discusses them a lot. (And I think they show up nicely in some areas like linguistics.)

So I'm pretty happy that Haskell, OCaml/ML, Scala, etc. have gotten enough traction, enough of a user community, to not just die out like a lot of experimental languages have in the past. To me it's not critical that these languages become "very" popular.

Different tools, different languages, for different uses.

Again, no intent to be condescending. But I think advanced concepts, like advanced vocabulary in natural languages, are important things. I'm glad some languages support them.

Set notation

And very few non-math majors even get exposed to set theory, set-builder notation (list comprehensions), or concepts of continuity.

Hm, are you sure? At least in German schools, basic set notation is obligatory from 5th grade on, and set comprehensions are probably 7th grade material. I can hardly imagine a college graduate who would have difficulties understanding the notation. (Continuity is a different story, of course, but also much less essential for grokking PL notation.)

I went through American

I went through American public school and then college for not-computer science. Basic set concepts (union, intersection) are about a week or two around 5-7th grade and that's it.

Though I agree that it shouldn't be a difficult notation to pick up.

Most of the younger

Most of the younger programmers I know (I was born in 1951, so nearly all programming people I talk to are younger than I am!) really have no exposure to areas like this. I think teaching of this is either done in a cursory way or not at all, a part of the death of "New Math" in the U.S. That, and less reading of popular books on science. (Personally, I learned about a lot of this stuff from popular books and "Scientific American" articles and columns, books by Martin Gardner, George Gamow, E. T. Bell, Constance Reid, etc. By the time we rushed through set theory stuff, I knew it.)

As the later comment points out, even most American set theory stuff is about simple Venn Diagram things like union and intersection. (Though, frankly, I think Venn diagrams are unfairly dismissed as high school stuff....I wish a lot more people drew Venn diagrams when they are making arguments. And having simple logical connectives in our set comprehensions is something we take for granted in languages like Haskell, but to many it's a revelation that languages can have easily-used primitives for these purposes.)

About 15 years ago I was chatting with some very bright programmers who were working a bunch of start-up companies….a few of them were involved in what became BitTorrent, others were at PGP, etc. We got to talking about vectors and vector spaces and it was pretty obvious that their knowledge of vectors started and ended at the old physics chestnut (simple example) of a sailboat in a river, with the resultant (pun intended) addition of vectors rules. They had no deeper ideas about linear algebra, vector spaces, tensors, etc. They did find it very cool when I explained how the stresses in a piece of glass or a crystal could not be "resolved" in the same vectorial way, and why tensors are used. Then I explained how the same stress-energy tensor is a chunk of glass is mapped onto the stress-energy of space itself, the curvature tensor.

American schools are not teaching much in the way of deeper ideas. Some highly-motivated folks learn this stuff, or come to programming math or physics.

Which goes to the issue of why "egghead" ideas from functional programming, or logic programming, take so long to get widespread use. "Object-oriented" is a bit easier for most people to grok (comprehend), as our real-world experiences teach us that everything is a rock or a log or something, and that some things inherit from broader classes, etc. And yet the Simula --> Java period was 30 years. Some have predicted from this that the transition from Miranda/Hope/Haskell to wider use will take a similarly-long period, but I think it will take even longer.

(I think the process-oriented, or morphism-oriented view of things is just as fundamental, that verbs are as important as nouns are, that Heraclitus had as much to say about how things work as Plato did. But the notation for functions, function application, and set theory is foreign to a lot of people. The emphasis on "arrows" in category theory is, I think, a useful step toward making these ideas much more familiar to people: everybody has a deep understanding of paths, links, arrows, actions, verbs. Now all we need is a "New New Math" to start teaching things like this to younger kids. Lawvere and Schanuel showed that bright high schoolers are capable of understanding the material in "Conceptual Mathematics.")

I would center a university course around SICP (perhaps with Scheme replaced with Haskell) and with a parallel or interstitial series of lectures on functions, set theory, very basic category theory, and a little bit about groups, rings, fields, abstract spaces, continuity, compactness, and some hints about the Curry-Howard isomorphism, "programs as proofs," etc.

This won't happen in the U.S., as near as I can see. It's not even happening at M.I.T. anymore. The "trade school" trend is dominating.

-- Tim

This won't happen in the

This won't happen in the U.S., as near as I can see. It's not even happening at M.I.T. anymore. The "trade school" trend is dominating.

Does anyone know when or if MIT will publish results on how effective their switch to Python was? They certainly made a hubaloo out of the change event, and did not publish statistics on the ineffectiveness of the previous curriculum.

I would probably say the central problem in American schools is lack of transparency. When I wrote a curriculum assessment of my school's CS program my senior year in college, I based it on the INFOSEC security assessment and evalution methodology. What's interesting is how few schools I surveyed had any methodology at all. I surveyed the elites, the local area, and comparable international schools. In my experience, and also talking with professors, it is not the "trade school" trend that is dominating. It is the "we can do whatever we want and not be expected to measure it" approach to teaching that is dominating. I've heard professors tell me about the brutal politics at many colleges, where they deliberately dumb down the curriculum to increase graduation rate and thus increase the college's Bundy money or whatever for graduating students.

What do you consider to be

What do you consider to be the best examples of useful innovations that have not been taken up? Starting there would help focus both question and answer.

Properly implemented Tail Calls?

That would at or near the top of my list. I'm even willing to compromise and go with explicit tail calls, say goto f(x,y); instead of return f(x,y);. Yet most of the languages that have become popular in the last 20 years don't support them, and usually large segments of the community are actually quite hostile towards them. (like the Java, JavaScript, and Python communities)

Tail calls is one

Tail calls is one Interesting example for discussion. It's been claimed (by people with more JVM knowledge than me) that implementing TCO conflicts with Java's method for implementing its security model. Since the ability to do various types of " sandbox light" was considered a key feature of Java at its origination, that would seem to be a case where other language features, that were in conflict with tail calls, were considered more important by the language designers. Similarly, in C++ it is considered to be an important feature of the language to provide LIFO destructors for stack based objects. These destructors can call arbitrary code and are triggered from thrown exceptions. So C++ seems like another case where conflicting language features took precedence.

What about languages where TCO guarantees are not in any sort of conflict with other features and would have been a pure positive for users, but yet were not implemented due to a lack of know how/time by the language designers? I count myself among those who think it a shame that good portable intermediate languages were not created sooner, but optimistic that LLVM and related projects can fill the gap.

It's been claimed (by people

It's been claimed (by people with more JVM knowledge than me) that implementing TCO conflicts with Java's method for implementing its security model.

This is indeed a persistent myth.

Thanks for the link

Thanks for the link naasking. I quickly browsed the paper, and here is what I understood. The authors, Clements and Felleisen, say that at the time Sun designed the JVM and Microsoft designed the CLR, they did not know how to implement TCO alongside the security policies they wanted to use. The 2004 paper claims to present a new method of doing that. So relative to the discussion in this thread, the reason for not taking up the tail call innovation was indeed a perceived language feature conflict.

Tangentially, as I understood the paper's proposal, in order to make the proposed security checking implementation method efficient, it requires that a fixed set of security permissions/grants be embedded in tables that are maintained as part of the execution context and get updated transparently to the programmer. So the static set of permissions is apparently a built in part of the ABI, and changes to that set would require recompiling. Perhaps that restriction is acceptable to the designers, but I'm not sure.

Explicit Tail Calls in C++

Tail calls in the JVM was an unsolved problem at the time, but now F# and the CLR support them. C++ destructors and explicit tail calls would not be a problem; there would be an interaction between goto f(x,y) and destructors, but in relative C++ terms, this interaction seems positively benign.

I think that the degree to which proper tail call implementations conflict with various design features is usually overblown.

Tail calls in the JVM was an

Tail calls in the JVM was an unsolved problem at the time, but now F# and the CLR support them.

Not very well though, for two reasons:

1. Tail calls on the CLR are significantly more expensive than ordinary function calls.

2. Tail calls only work when the CLR is running in fully trusted mode, ie. when code access security checks are all disabled.

C++ destructors are LIFO by

C++ destructors are LIFO by design (including both regular exit and exceptional unwinding) and they can call arbitrary code. They more or less require stack frames to implement. Something that looks like a tail call really is not in the presence of non-trivial destructors. So tail calls are not possible in C++ in most situations where one might like them. On the other hand, it might be nice for the language standard to guarantee TCO where it is possible.

Explicit tail calls

My understanding is that Leon implied an explicit tail call to have a different semantics: all destructors are invoked before the actual call takes place (in the usual order). Makes some sense, but it is much trickier than it sounds. To be useful at all, the destructors would need to be invoked before the call, but after the arguments to the call have been passed (otherwise, the argument expressions could not legally refer to any local variable). This seems pretty complicated, and it is not clear how it interfers with exceptions and such.

Also, I think that the main issue with tail calls in C++ is actually not destructors. It's C++'s heavy reliance on pointers and references, usually to stack-allocated objects. This is an almost insurmountable problem for automatic TCO. Even with explicit tail calls, any tail call to a function taking a local reference would be undefined. Since the use of const references for optimised argument passing is omnipresent, this is pretty much a show stopper in practical terms. Consider a function int f(const string&). Under normal circumstances, the call

f("bla");

will happily construct a temporary object that is guaranteed to survive the lifetime of the call. For a tail call, it couldn't do that. And there are lots of similar situations. As a result, tail calls would have to be extremely restricted, and thus potentially useless.

Modern C++ compilers give

Modern C++ compilers give error messages for code that trys to return local objects by reference to the caller, so the same tech could be applied to code that trys to pass local objects by reference to an explicit tail call.
Similarly, returning local objects by value is fine and the same should be true for passing local objects by value to a tail call. One can work harder to get into trouble by constructing a local object O1 that holds a reference to another local object O2 and then returning O1 by value or passing it to a tail call. Offhand, I'm not sure about the state of current compilers to notice that such code is FUBAR. It seems like it shouldn't be too hard for a compiler to keep track of which local objects are tainted in this way and also not allow such objects to be passed by value or reference to an explicit tail call.

I'm not sure I see a good motivation for adding a language feature that requires function bodies with "different semantics" with properties like e.g. messages printed by destructors would be output in a different order. It would be simpler to just prohibit the use of an explicit tail call when local objects with non-trivial destructors are in scope.

Not concerned with error messages

I am not so much concerned with diagnosing obvious misuses (that should be relatively easy), but rather that all the necessary restrictions render the feature fairly useless.

messages printed by destructors would be output in a different order

I don't see why that should be the case.

It would be simpler to just prohibit the use of an explicit tail call when local objects with non-trivial destructors are in scope.

That would clearly violate the philosophy that you should be able to use user-defined classes like built-in types.

"I am not so much concerned

"I am not so much concerned with diagnosing obvious misuses (that should be relatively easy), but rather that all the necessary restrictions render the feature fairly useless."

The restrictions would still allow for the canonical examples of tail calls that are typically presented to argue for their elegance. How about an example of what you see as an important usage which you think would be disallowed?

"I don't see why that should be the case."

Because the destructors would be called in a different order under your proposal. If function f1(x1,x2) is a candidate for a recursive tail call, and it creates local objects O1(x1,x2) and O2(x1,x2) in that order, then you proposal to destroy O2 and then O1 before the f1(x3,x4) . Then in the next instantiation your version ends up destroying O2(x3,x4) and O1(x3,x4) in that order. The dependence on the arguments to f1 is given here to make things explicit, but of course the outputs could depend on other hidden state as well.

"That would clearly violate the philosophy that you should be able to use user-defined classes like built-in types"

Except where you can't. There are other examples of programming idioms where one wants to treat the two differently (e.g. when deciding whether to call memcpy() or do an element by element assignment within an array) and methods to try and safely deduce which case applies. There is definitely a judgment call to make about which is better:

1) Tail calls only when a compiler is smart enough
or
2) Guarantee of tail calls whenever it is provably safe
or
3) Explicit tail call syntax where compilation fails if it isn't provably safe
or
4) Explicit tail call with different semantics for the function and also fails when not safe.

I see version 2 or 3 as prefereable to 1 or 4,

Violent agreement?

How about an example of what you see as an important usage which you think would be disallowed?

Admittedly, I don't have any good example handy, since I haven't really thought about how I would want to use tail calls in C++. But you most likely won't be able to have your typical const& arguments on functions that you want to be tail-callable.

Because the destructors would be called in a different order under your proposal. [...]

Ah, now I see: you mean the order between different function invocations. Well, yes, of course. The semantic difference between tail-calls and ordinary ones (in one way or the other) is unfortunate, but seems unavoidable in a language as messy as C++. I guess that is part of my argument against them. Maybe we are just in violent agreement here?

I see version 2 or 3 as prefereable to 1 or 4

In principle, except that this would have to be part of the language spec, and the conditions for "provably safe" are almost impossible to specify in C++ without being extremely restrictive.

Local C++ Objects

The more I thought about my claim, the more complications I saw. Passing local objects as arguments does seem to be a thorny issue; for example what happens if the source address for the local object overlaps the destination address for the argument? It would seem that you would need to assume that the copy constructors that are involved can deal with memory aliasing... yuck!

OOP has at least one

OOP has at least one well-known striking example (of "[...]useful innovations that have not been taken up").

(Well, even if one isn't that much into/a proponent of that OOPL paradigm, that remains something difficult to ignore) :

Design By Contract(tm).

Eiffel's very design proposed it be thoroughly integrated with the rest of the language's features (and with an emphasis on paying attention to the consistency with them -- notably the type system) as early as in the mid 80's.

Almost twenty five years later, other mainstream OOPLs (e.g., up to, at least, C# 3.0, in 2007 -- an "OK enough" language otherwise, to me) hadn't integrated the idea.

C# is just an example, as I especially watched its evolution, there. But it's a (fact!) vast majority of (OO-)PLs out there ... that just don't do DbC.

Suggested "exercise": find out the proportion (of those languages -- if only "OO", that's still OK -- with/without DbC)... ;)

The D language has some

The D language has some built in facilities for DBC and unit testing.

Dependent types

Design by contract is a relatively powerful concept, but I'd rather see the widespread adoption of dependently typed languages in tandem with more powerful type checking algorithms. With dependent types I can not only define datatypes whose instances satisfy their invariants by construction, but also include pre and post conditions in the type signatures of functions. They also give you polymorphic and existential types, and the list goes on.

[...]but also include pre

[...]but also include pre and post conditions in the type signatures of function.

Ah? Sounds powerful in the expressiveness of such captures then, indeed.

Well, I know close to nothing about DT's, but this is definitely the type of tip able to excite one's curiosity, as compared to more "classical" DbC pre/post/inv-based I know a little better. Thanks for the info!

I'll have to look closer into DT's way of doing DbC, some time.

Dependent Types

I wrote a blog post recently about dependent types with some examples that enforce pre/post conditions. It uses ATS for the examples. It might help when you want to look at DT's a bit closer some time.

"pre and post conditions in

"pre and post conditions in the type signatures of functions"

In other words, they are in the interface, not in implementation. This is the case with Eiffel, where pre and postconditions are not instructions. This is in contrary to eg. classic assert() and Microsoft's Code Contracts, which is a library and thus part of implementation.

br Jussi

Statically checked

You are missing the main thing, namely that with dependent types, these conditions actually are/have to be proved at compile time, at call sites for example. No such thing is done in Eiffel, where they are merely glorified assertions.

Missing the thing with DT

which I do not know at all, but on the other side coming back on topic:
I am not sure that DT is an innovation ready for adoption, DbC maybe more so.
I would not like underestimate DbC, the work done with Eiffel to integrate DbC with the rest of language features and the help the Eiffel compiler offers to ease a programmer's work.

br Jussi

Strange assertion

You do realise that in Eiffel those 'glorified assertions' integrates with the class hierarchy see the "Design by Contract" part

You call this 'glorified assertions'?
Strange assertion..

Yes

Yes, I do realise that -- I mean, otherwise they wouldn't even be "glorified", or what else would be left?

C++ has dependent types

There is some stuff left. C++ has dependent types (through templates) and the ability to do static asserts using that facility. However, the human factors related to these facilities are poor in several ways, including 1) verbosity, 2) difficulty making friendly compile time error messages, 3) sometimes poor interaction with the language's declaration/definition separation, 4) non-locality of the definitions that enforce the sub-type signature of a function, and 5) programmers spend some extra time working out which properties are can be statically expressed and which must be dynamically checked. Of course, dependent types can benefit from a much cleaner design, but I don't see where they would be able to replace a facility like in the D language that allows compile time testing of non-static assertions about type signatures via automated unit testing.

How?

C++ has dependent types (through templates)

Can you elaborate? AFAICT, all you have is constants as template arguments, but that's far from giving you dependent types.

Template arguments can be

Template arguments can be either types or integral constants. In case they are types, the types can have traits which are typedefs given within the scope of the class definition of the template type argument.

That's not dependent types

Well, yes, but that's not dependent typing. You would have dependent types, for example, if you were able to legally write something like (in C++0x'ish syntax):

template<int n> class dt { ... };
auto f(int i) -> dt<i> { ... }

I don't agree, but I'm not

I don't agree, but I'm not sure what you are saying (is "->" a synonym for "is defined by" in this language you are thinking of).

C++ does allow you to completely specialize the definition of the class dt depending on the value of the template argument n.

Alternative function syntax

The arrow notation is just new C++0x alternative function syntax. I used it because when writing it in traditional C style,

dt<i> f(int i) { ... }

the scoping of i is screwed up.

Not sure what you are disagreeing with exactly. "Dependent types" is a technical term with a well-established meaning, and being able to "specialize the definition of the class dt depending on the [constant!] value of the template argument n" does not have terribly much to do with it (it is more like an indexed family of types). In any case, C++ doesn't give you anything even remotely close to the expressiveness of dependently typed languages.

The important points are

The important points are getting obscured by side issues.

Main point:
C++ does have dependent types according to every definition of that concept I have come across. The manner in which C++ provides dependent types is open to many criticisms in terms of user-friendliness, but I don't understand the basis for your notion that the functionality is not available. Please provide an example of what you want to do.

Side points;
The syntax "->" is already used in C++ for pointer lookup.

There is no good reason to even try to use the same temp variable name for the template argument and the function argument. I expect that "dt f(int i)" would fail to compile, but I'm not a language lawyer so it might just generate a warning to fix and give unexpected results (and I'm not going to spend time figuring out how to tell this blog software that the template argument isn't a request to italicize).

close tag

I don't know much about dependent types, but presumably the reason to use the same variable name in the template argument and the function argument is so that the return type of the function depends on the argument passed to the function.

Ok. Well C++ is a

Ok. Well C++ is a statically typed language. So in C++ it is possible to have the return type of the function depend on the argument type(s) - int, in this case. And it is possible to have the return type of the function depend on an integral value that is known at compile time - e.g. constant value or one based on a compile time property such as some function of sizeof(). In that case though, there is no reason to use the integer as a function argument. If one actually wants the return value to depend on the value of an argument that is only known at runtime, then the best C++ offers is the factory pattern, where one returns a reference to a base type which actually points to a derived type that depends on the function argument(s).

Thanks

Thanks. But while I don't know much about dependent types, I do know a little about C++. Actually, I'd be surprised if you could find any regular on LtU that isn't aware that C++ is statically typed. I'm also familiar with the capabilities of the C++ template system. It clearly doesn't provide the ability to express Andreas' simple

auto f(int i) -> dt<i> { ... }

example, from which (based on my limited knowledge of dependent types) I infer that C++ templates do not support dependent typing.

Dependent on "runtime" values

Main point:
C++ does have dependent types according to every definition of that concept I have come across.

Then those definitions probably were misleading. I assume they were saying something along the lines of "a dependent type is a type that depends on a value". While not wrong, that is an oversimplification. The main characteristic of dependent types is that they can dependent on (more or less arbitrary) expressions, particularly ones referring to variables from the context, and thus indeed "runtime" values if you wish (although there tend to be restrictions on those expressions to ensure decidability and phase separation of type checking).

As an example from the C world, consider printf. It cannot safely be typed in C or C++, because its latter argument types depend on the string value of its first argument. In a dependently-typed language, you could give a precise and safe type to printf.

[Edit: for some other simple examples and further links, see e.g. here.]

Side points;
The syntax "->" is already used in C++ for pointer lookup.

True, but? I didn't invent this new function syntax (nor would I ever claim that C++ syntax is not messed up), but it's in the new standard.

There is no good reason to even try to use the same temp variable name for the template argument and the function argument.

Well, as long as you don't have dependent function types... ;)

It is possible in C++ to

It is possible in C++ to construct types that depend parametrically and arbitrarily on const strings, including a compile time constant control string in printf format. It is never possible, by definition, to have a thing in C++ called a type that depends on a value that only becomes known at runtime. So to the extent that the definition of dependent types depends on the ability having the things called "types" by the language depend on runtime only values, then that is indeed impossible in C++. If that is indeed the case, I'm a little confused about how it jibes with your comment earlier in this thread that "You are missing the main thing, namely that with dependent types, these conditions actually are/have to be proved at compile time, at call sites for example. No such thing is done in Eiffel, where they are merely glorified assertions." It seemed like you were saying there that the interesting property of dependent types was compile time checking and here you are saying it is a definitional property of dependent types that they allow runtime dependency.

Using types to prove

Using types to prove properties that depend on runtime values is exactly what makes dependent types so powerful. You're right, C++ does not support dependent types, and, as amazing as it may sound, dependent types are about proving, at compile-time, properties involving runtime values.

If *all* the properties of a

If *all* the properties of a value can be determined at run time then it is a constant. C++ classes can be dependent on just those properties that are known at compile time. Though, as I remarked above, the language can be justifiably criticized for not always making it convenient to express that dependence.

Not all, only enough to

Not all, only enough to prove the property expressed via types. Safely eliding array bounds checks at compile-time is a simple example (see DML). One does not need to know the exact value of i in

for (size_t i = 0; i < vector.length(); i++)
        vector[i] = i; // *

to tell that, under reasonable assumptions, i, at the line marked with an asterisk, will always be a safe index for vector.

Properties as types

It is possible in C++ to construct types that depend parametrically and arbitrarily on const strings, including a compile time constant control string in printf format.

Yes, but there is no way for a C++ type expression to actually analyse the string -- which is what you would need to type printf.

I'm a little confused about how it jibes with your comment earlier in this thread

No contradiction there. It is really very simple: in a dependently typed language, you can express formulas from, e.g., higher-order logic (over program expressions) as types. Well-typedness then implies that a proof can be found for these formulas, either by the compiler, or in harder cases, by the programmer. You don't generally need to know any actual runtime value to prove properties about it (although equality constraints can easily be expressed, too, of course).

True, sort of. Template

True, sort of. Template metaprogramming in C++ is a Turing complete, compile time language. So it is theoretically possible to do almost anything with information known at compile time, but it can be very ugly and cumbersome. The example of analyzing a control string is a relevant one, as C++98 compilers do not understand in case of e.g. const char cs="%s somestring"; that the expression cs[3] is actually a compile time constant. So one would have to represent the string as individual characters to reason about it using C++98 template metaprogramming. The C++0x standard fixes this issue with the constexpr declaration (basically telling the compiler to go ahead and figure the compile time constness) but this is not implemented yet by current compilers.

I looked at some dmt papers to get a better understanding of what you and pkhuong were saying. Based on that reading, I would have argued your side of this sub-thread differently. Rather than claiming it is necessary for dependent types to be based on runtime values (which I still do not believe is true), I would have said instead that whether or not C++ literally has some forms of dependent types, the most interesting things that people want to do with dependent types require *algebraic reasoning over compile time quantities* rather than just evaluation of compile time constant expressions. Whether or not it is possible to do such reasoning with template metaprogramming, it would simply be too baroque to bother and there is no standard support for doing so.

That leads me back to the point I was originally trying to make about the D language approach of basically providing a compile_time-runtime to evaluate programmer specified unit tests that are integrated with class definitions. That approach clearly fills some hole that would be left by a dependent type logic which only handled linear inequalities over particular integral expressions. Less elegant, in a way, but also simpler and more complete.

Er, what?

Rather than claiming it is necessary for dependent types to be based on runtime values (which I still do not believe is true)

But... that's exactly the definition of dependent types, that sets them apart from simple type-level computation. I really have no idea where you're finding anything that says otherwise.

Types depending only on "values" known at runtime is just syntactic sugar for lifting those values to their type-level equivalents--useful, but hardly novel, and very far from the power provided by true dependent types.

The examples I've seen held

The examples I've seen held up as canonical for dependent typing involve reasoning about variables, x1, x2,...etc with desired or known relations between them that are expressed at compile time; in most cases these relations seem to be restricted to linear equality/inequality for practicality reasons. In such examples the dependent type depends on the relationships (e.g. x1

Other canonical properties

Other canonical properties involve things like the well-balancedness of red-black or 2-3 trees. Linear relations over the integers are an interesting sweetspot because they can be checked automatically; to support pretty much arbitrarily stronger properties, it suffices to depend on the programmer for a larger portion of the proof (e.g. Coq).

C++ "concepts"

They are considered useful by many, including Bjarne Stroustrup himself, but losed voting in 201x standard committee. Could imagine that the majority saw some barriers for their adoption by ordinary programmers.

br Jussi

new languages serve a handful of purposes

most of these purposes suit the language inventor, not programmers at large

for example (if you'll excuse the acerbic tone) :

* a theoretical itch
taking it in strides to make it harder to explain why your program won't work
sometimes esoteric on purpose, these make harder problems relatively easier,
but often because easy problems are hard too

it is also good material for a paper

* a silver bullet
if only goal directed evaulation, actor based concurrency, ad-hoc polymorphism
features bolted on to the authors language of choice, often hap hazardly.

often these are the result of zealotry

* the sugary lump
if only perl,c was more like smalltalk, if only .....
existing concepts with a fresh new c-like syntax

most of the new languages I've seen outside of ltu revolve around java/c# variants,
mostly procedural class based languages, with some degree of typing, single dispatch.

these solve the problem of 'I want to think in java but not have to write in it'

ultimately:

a lot of 'innovation' in programming languages is rarely novel. many features and ideas have been tried and experimented with before, and have a relatively long history.

many new languages aren't developed with a specific problem in mind, and as a result, don't solve any problem well enough to be adopted.

or are yet to mature: no documentation, test suite, incomprehensible error messages, no debugging support, a spartan standard library. unfit for anything more than a toy program.

but it is not all bad news!

language features that are good will often get adopted by more established programming languages. languages start small and grow well, it can take a while for a new language to be useful.

hoare argued for two distinct families of languages: one to experiment with new features, and one to compile existing features together. i'd argue that more mainstream languages are frequently the latter type. language experimentation is a good place for ideas to grow and mature, not to revolutionise the world.

it is not a matter of 'dumbing down' your ideas but finding an idea that is easy to adopt.
learning is effort and people don't want to invest so readily in a new technology.

there is plenty of room left for innovation too: testing, documentation, debugging, versioning - all parts of the software life-cycle oft ignored by new languages. we focus too much on making code easier to write than easier to maintain and deploy.

but please, enough with the meta-programming already.

I mostly second this, and

I mostly second this, too, and you have an entertaining way to put this/your "ugly truth" there above, btw. :)

I just don't get your very last sentence:

but please, enough with the meta-programming already

See, I do business apps in a strongly, say, MS-based & OOPL-conservative environment, with teams overseas, and many different level of competences. For a living, of course. Can't complain much, though; I'm very OK with my fate, as I work with intelligent people, who are also nice, nevertheless. But as you may have guessed, this also brings the probability of me having "fun" with meta-programming opportunities ... pretty much to zero.

Now, if I can't even play with meta-programming in my spare time (well, because you don't want me to... ;) -- when should I?

a little better just isn't good enough

When you are considering using a new language rather than one you are familiar with the new language needs to be a lot better not just a little better. The costs with changing languages is usually fairly high in almost any context even if it is just in terms of your own time and effort. Laziness is considered a virtue by many programmers so the payback in terms of writing real programs needs to be pretty obvious.

Look at existing languages that are successful to find how they deal with this issue. Scala is compatible with Java so it can use the Java virtual machine and libraries. Java used C syntax giving it the appearance of being a C-like language. Perl, Python and Ruby all started in niches and then expanded out of them.

I doubt cleverness of language designers or programmers has much to do with language adoption.

+1, Agreed. I doubt

+1, Agreed.

I doubt cleverness of language designers or programmers has much to do with language adoption.

I'd just add:

You actually need to be pretty clever to design a sound, useful language that you'd like having a successful adoption. I take it as being necessary, but also as being largely insufficient. Because, indeed, I also believe that:

... then, you need to be even cleverer (or get help, or constructive feedback) to make it friendly not only to you, but also to others.

... and then, you need to make (or have someone more skilled) at least one "good enough" implementation of it.

... and finally come up with (at least) the documentation your language deserves.

Phew, so you realize that's a pretty long way to go, in all -- and seems like language adoption, no matter how clever the creator is, can definitely not depend upon the creator's cleverness only, or even, upon the language's intrinsic qualities only.

So that, well, it's primarily... a lot of meticulous work, as usual. And way before any amount of cleverness you happen to have. My bet is most of successful languages' creators could confirm this feeling here... would they be less busy :)

Conversely, I'm not even sure whether genuine, true innovation is absolutely necessary then, for a good language adoption, if all other quality factors I thought of above are met. But then, oops... that's kind of the opposite topic from this thread's, I suppose.

Reminder

From the LtU Rules for Discussion:

Avoid ungrounded discussion: Discussions which start out with the posting of an opinion or idea that hasn't been clearly described, and for which no references are given, tend to result in unproductive debates with a reduced quality of discussion. It is much easier to evaluate and respond to someone's position when given a link to a carefully thought-out description of that position, and/or references which put the idea in a clear context. If a long description proves necessary, it should be posted elsewhere, such as on your own blog or website, and posted as a link on LtU.

Ungrounded discussion... the motivation behind my post

As a rule I would tend to agree about avoiding ungrounded discussion, but...

I think that programming language inovation is desperately needed in IT, and my posting was intended to be a sincere plea to academic PL researchers to make their work more understandable/usable by the majority of working programmers.

It appears to me that there is a big divide between academics/reseachers working in PL inovation, and the ordinary programmers who "toil in the fields", many of whom don't even have time to wonder why their job is sometimes so difficult (let alone come up with solutions).

From my experience as a programmer working outside of academia, the vast majority of PL "inovation" that we see is that produced by IT manufacturers to suit their own commercial agendas. And I think it's bit sad that so much valiant effort seems generate so little change in the IT industry.

regards,
Mark.

What do you want to do?

And I think it's bit sad that so much valiant effort seems generate so little change in the IT industry.

1. Languages should enable "Doing little with great effect."

2. But growing a language is "Doing a lot with little effect."

Since well-established mainstream, or even obscure, languages increasingly cover aspects of [1] after large investments in [2] it is increasingly more difficult to (sell to) do [2].

the (non-)value of recent PL innovation

what is needed is for programming language innovations to be packaged or distilled into an easy to use tool that does not require a degree in logic theory or programming language theory to be used.

This is the wrong question.

Suppose a genie came along and handed you the answer. It will cost you a scant $500,000 to build. As scientifically measured, it will make your "average programmer" about 0.05% safer and 0.5% more efficient in exchange for an up front training cost of a mere $500.

Imagine you have the answer to "what is needed [...] to be packaged or distilled [....]" and, those are the terms.

I think that that's about where things are in fact.

Why no one uses functional languages

I discussed possible reasons for slow take up of functional languages in Why no one uses functional languages, SIGPLAN Notices 33(8):23-27, August 1998. A later version is How enterprises use functional languages, and why they don't, The Logic Programming Paradigm: A 25 Year Perspective, Shakertown, April 1998. Springer-Verlag. Many of the reasons also apply to other languages, but I'm happy to say, some of the reasons apply less to functional languages now than they did a decade ago.

A Bit Stale

That is, your writings on the subject. Time has progressed, the field changed a lot over the last dozen years.

For example, if there's one (granted hybrid procedural, OO, impure, eager, etc.) success of functional programming then, to me, that would be Javascript, I think. A subject which actually merits its own discussion at 'how good it is' as a programming language for the web. Also, I am still waiting, no doubt it's out there somewhere, for 'Functional Programming Pearls in Javascript.'

Moreover, F#, Ocaml, GHC seem to have generated interest in some parts of IT; I doubt they'll ever find anything better for programming in the financial community.

Multicore might once become a reason to favor (pure?) functional declarative programming (for business logic) over other imperative paradigms.

So, the future is bright; at least bright enough for a follow-up paper ? *wink, wink, notch, notch*

Moreover, F#, Ocaml, GHC

Moreover, F#, Ocaml, GHC seem to have generated interest in some parts of IT; I doubt they'll ever find anything better for programming in the financial community.

These are the same people that were using Objective C, Smalltalk, and Lisp early. If anything, things seem to be moving backwards, there are fewer/smaller PL niches in the financial community (at least in the states).

The Net is Patient

People make bets on whether it will survive 200 or 500 years (in its current form).

I doubt we'll see a new functional language emerge which will fix most of IT's problems; most mono-paradigm languages can only function in small niche markets, and have to compete with multi-paradigm options. Having said that, I think in another decade or so we'll see an uptake of functional programming in specific applications, though they may be hidden behind a C#/F# layer.

It's just a believe, some problems are just solved too well by functional programming. But I think it will happen in an unobtrusive/low-key manner; like Javascript, or maybe, some day, proper higher-order functions/closures in C.

JavaScript...

JavaScript can hardly be classed as a functional language. None of the reported benefits of functional programming can be had in JavaScript. It just happens to have a construct which approximates lambdas. In that case why not include the smorgasbord of new imperative languages which also have a lambda-like feature.

Functional languages will not win because of multicore. Functional programming is not a silver bullet which will automatically solve the inherent problems of parallel processing... An imperative language which has a way to control effects will be more effective and useful in the end.

RE: JavaScript

You can't reason about composition, refactoring, reordering, elimination, partial-evaluation, and abstraction as though JavaScript function parameters strictly map domain values to range values. Therefore I share your opinion: JavaScript is not a functional language. But I understand many people think of 'functional language' as meaning 'can support functional programming idioms'. That would be the same group of people who call Lisp, Scheme, and OCaml 'functional'.

I doubt your claim about imperative languages and controlling effects. Imperative statements are all about implicit time - before and after.

I'd place my bet on explicit temporal semantics, which offer a sort of declarative concurrency and synchronization (A and B are happening at the same time) and even some nice real-time properties (A occurs between 300 and 400 microseconds after B).

I also believe that functional programming will likely be part of any winning solution. Working with pure values is useful for distributed and parallel scalability. Explicit control over inputs is important for security (and thus multi-organization scalability). Functional offers both those properties. Working with your analogy: functional programming is a reasonable candidate for silver bullet - but bullets don't propel themselves. We still need a jacket, a cartridge, a magazine, and a gun. Temporal semantics are promising element of that solution.

Javascript...

In that case why not include the smorgasbord of new imperative languages which also have a lambda-like feature.

Why not? Support for lambdas enables most (trivial) functional programming idioms.

Maybe that is just what one should expect anyway? If you see academic language design (ML, Haskell,...) as an incubator for ideas of which some of them may pay of in their long-term investment, say 20-50 years, then in another fifty years the net result of all of that functional programming might just be that. I.e., most languages just adopt a lambda on board.

(Okay, that was even a bit too cynical for my taste. Maybe the current situation should be phrased as: "Adoption of current Wisdom is Slow" ;) )

C++ has DbC too ?

Have no reference to any source at hand though. Resembles the state of affairs with C++ and DT.

Mostly Prosaic, Boring Reasons [Long]

The biggest barrier to adoption of language innovations is that FEW INNOVATORS EVER REALLY TRY. I won't refer to any language designs or features (which indeed may be relevant in some cases) and just address 1) the high "management" and "marketing" hurdles that seems to accompany successful adoption and 2) only "general purpose" languages (i.e., not Lout, R, Coq, or whatever).

Most language innovations aren't packaged up in languages, implementations and distributions that are suitable for mass adoption even by early language tools adopters.

First, there must be quality platform specific distributions kept in tight version synchronization: popular Windows binary installer, popular Linux packages, and Mac OSX. For some languages, the existence of both 32 and 64 bit versions may be important.

Cygwin for Windows will *never* cut the mustard. More generally, the distributions need to be self contained, taking responsibility for all 3rd party low level tools used (assemblers, linkers, C-libraries, etc.) and their versions. 99% of language users should never need to know this back end machinery exists.

What's worse (often fatal) is when there are multiple, slightly (or more) incompatible distributions for a single language. Users want to learn "the language" and power users want to contribute new features and libraries to "the language." Generally, the "benign dictatorship" approach to language definition, implementation, versioning and distribution is most wise for early adoption (and often, beyond).

The distribution must feature really good documentation for the language (both tutorial and reference), the runtime system (early language adopters will typically care), the libraries and the available tools.

IDE support *may* be important to certain languages used for certain problem domains, but I am not convinced that this is important. IIRC, PHP, Python, Perl and Ruby all became widely used languages in the absence of IDE support (at least during their period of rapid adoptions). Shy of IDE integration, there should at least be templates for the most popular (free) editors with indentation, syntax highlighting, pretty printing and ideally more (compilation, documentation extraction, program execution, etc.).

These days, language distributions must contain the oodles of data structure, algorithm and problem domain specific libraries that people have come to expect. A new language need not rival the libraries of Perl or C++ or Python right away, but the initial distribution must be complete enough to convince new adopters that this level of completeness is forthcoming sometime soon (within a few years of initial release).

There must be many sample applications in the distribution, written in a style suitable for inspection and pedagogy. These are not "killer apps." Instead, they need to reflect the kinds of things most users want to do - parse text, format output, read structured data/binary data, frob Internet protocols, use templates to produce HTML pages (or other formatted files), cobble together an attractive GUI (by contemporary standards), access the major SQL databases (SqlLite doesn't cut it) or the lighter weight DBM database, spawn processes and communicate with them, use various IPC protocols, display images or draw charts, play music files, perform simple math over small to medium sized data sets, sort data, take advantage of multiple core CPUs (a popular desire these days), etc.

What's more, the applications have to show how the language makes these common tasks *easier* for the developer, compared to the languages they already know, and maybe more speed/space efficient as well - preferably both. If not more speed/space efficient, then the sample applications much exhibit that the solutions in the sample applications are clearly speed/space efficient enough (with developer defined definitions of "enough").

As a special case, if the language in the distribution features fancy language innovations X and Y, then sample programs must show how to use X and Y and, more importantly, how the availability of X and Y make the programmer's life "easier", according to some explicitly stated goals of the target programmer (speed, safety, cleanly scaling with additional cores/CPUs, far fewer lines of code, whatever).

Sample programs should encompass high quality example code and documentation essentially for every library call. As an off the cuff example, the popular wxWindows portable GUI library does an impressive job here, where one program with tabbed panes illustrates every library feature with a short program in one pane and source code and short documentation in their own panes accompanying the application pane.

Finally, adoption seems to require near full time evangelization by the language's associated "Genius/Wizard" spokesperson(s). I don't follow the pop-scene much today, but back in the day, Stroustroup, Larry Wall, Guido Von Rossum, a small army of Sun folks, etc. were constantly speaking at some conference, giving some interview, traveling around talking to relatively tiny, fledgling user groups (and even individual companies large and small), writing multiple articles, putting updates on the Web, handling inquiries and potential bug reports on a mailing list, maybe spending some time on IRC, and finally, somehow managing various aspects of the evolving language design, implementation, library development and distribution (via delegation).

Should an individual build a group to accomplish all of this, or an existing team accomplish all of this, then one must be willing and able to then evangelize a second time to the "suits" who must sign off on deployment of applications written in the innovation-containing-language in their commercial applications.

Whew! No wonder few software language innovations are put into mainstream use via adoption of innovation-imbued languages by mainstream developers and their organizations. It's such a distracting, non-intellectual, yet extremely challenging and risky effort - why would language researchers ever drop their current life's work modus operandi in academia to take on such a daunting managerial and marketing task with a high failure rate in the best of circumstances?

Makes sense to me.

Well said!

Scott, that's extremely well put. I'ld add that the Genius/Wizard usually needs to figure out how to assemble, care for, and feed a core group of evangelists to spread the word. That's a social role rather than an engineering role; not many people are good at both.

I only hope that it turns out to be as simple as you suggest... :-)

other folks money or die

Scott to me seems to be saying that the successful birthing process is too expensive for the inventive types to undertake on their own gumption. Which is obviously the case.

Programming languages "win" when they make money for sponsors and/or investors early and often -- with a few exceptions. E.g., Python, Javascript, PHP, etc. gained very early support and got to mature because very early on they were worth something to the check writers (right place, right time, acceptable ideas).

Someone says "Oh, I have discovered a great new static type system with these amazing properties and our studies suggest it is a huge win..." I believe them but I also believe that until someone is paying the innovators to mature the thing it's going nowhere fast.

For the most part, the only way that pay comes is from immediate gratification -- an immediate application that somebody wants to pay for in order to make money.

There are rare exceptions. E.g., XQuery. In that domain, the main investors were well aware from decades of experience that they could afford to be patient and dip into their deep pockets.

To add insult to the injury of that reality, often what can "immediately benefit" early on and attract sponsorship or investment is determined only weakly on comparative technical merits among contenders and much more by, well, politics.

I keep (apparently in vain) trying to mention this way of looking at things in this thread because I reject the notion that a good idea (in the sense a PL Theorist might mean "good idea") can automatically pay for itself if only those in possession of the idea will apply themselves to "packaging it up nicely". The flow of money determines which PL ideas go big and the flow of money is only very, very loosely correlated with the "good ideas".

Exceptions?

I find it to be the opposite. With excruciatingly few exceptions, the languages that have succeeded _not_ been done by industry for profit. Java and C#'s respective successes are the outliers, not the rule. Look at these examples:

C, C++, Ada, SML, Ocaml, Haskell, Objective-C, Python, PHP, Ruby, Perl, Lisp, Scheme, Smalltalk, JavaScript, Pascal.

Of the languages in this list, about half were done in academia and half in industry. And the ones that were done in industry were never big money makers for their primary sponsors.

Given there are only three (VB being the third) major examples of languages that I can think of that were big financial successes and also highly adopted, I'd argue that there is essentially no correlation between money and the adoption rate of a programming language.

However, I think maybe the correlation holds for DSLs, but not GPLs. For example:

MATLAB, R, SQL, Verilog.

I think in these cases, these popular languages target domains that are populated by specialists whose primary skillset is not programming in general, and programming is an incidental and fairly small part of their cost, and thus they can afford the kind of expensive tools that are required. Not only that, but each domain has few free offerings and less competition in general.

those who forget history :-)

C: funded initially and without full awareness by Bell Labs / AT&T in their early attempt to implement "commodity computing", payed its way up until they started sloffing off the unix group by internal efficiencies (e.g., software to help 411, software to help other researchers publish, etc.). Took 'em a while to figure out that they hadn't in fact found a way to make a profit but they funded the researchers behind it believing a profit waited in the wings. The researchers were playing with someone else's money. C++, no different.

Ada. SML, Ocaml, Haskel: None have the the kind of adoption the original question post asked for (as I understand the question).

Objective-C: Thanks to NeXT and later Apple.

Python: Look into who was paying Guido and why. But also, see next:

PHP, Ruby: In the early days of the "dot com" boom around the web there was huge demand for web-oriented programming environments. At that time, a few people were able to crank out languages on the margins of cranking out libraries (PHP a very early example, Ruby a late one). The maturation of these languages was funded mainly because, along the way, the languages and their emerging libraries were generating profits that, in part, were reinvested in the main developers of those languages.

Similarly Perl.

Scheme and Smalltalk, of course, are NOT widely adopted in the sense of the original question. They are examples of the grand frustration of "why don't good ideas get used"?

Javascript's creation myth has to do with abandoning something like a really good Scheme to quickly knock out something that "looks like Java" so that the sponsor (Netscape) could make a quick profit.

Pascal was pretty stagnated until a commercially important implementation for the DOS PC took off.

The original question was, as I understand it:

I have been thinking recently about why so much programming language innovation is not taken up. this is my take on it...

[...]

what is needed is for programming language innovations to be packaged or distilled into an easy to use tool that does not require a degree in logic theory or programming language theory to be used.

The innovations in question demonstratively do not require a degree in logic theory of PLT to be used. The question of lack of uptake is, based on historical empirical analysis... entirely because none of these innovations have solved any sufficiently compelling problem to generate the investment needed to mature the language for such adoption.

Sponsors

I was replying to this in your OP:

Programming languages "win" when they make money for sponsors and/or investors early and often -- with a few exceptions. E.g., Python, Javascript, PHP, etc. gained very early support and got to mature because very early on they were worth something to the check writers (right place, right time, acceptable ideas).

Perhaps you mean something different when you say "sponsors and investors". I interpret that phrase to include those who fund the PL implementors and core library implementors...and not the application programmers. It's a whole different and far more complex argument if you include everyone who ever programmed in the language and those who funded them.

In each of these cases, and in all the subsequent cases you refer to in your reply, the languages did not in fact make money for either their core implementors or their sponsors or investors, neither early nor often (or even, later). In almost all cases, the mythical profit did not pan out. There are a large number of successful languages that were offshoots from a large organization funding many different things, but the language itself wasn't profitable. And there are no examples of small companies making their bread and butter off of a language implementation of their own language. Some small companies have very small but respectable businesses providing libraries and frameworks for languages like Ruby, Python, and PHP, particularly web frameworks, but that's a far cry from implementing languages or doing language innovation.

Now however, I do agree that the sponsors and investors of the core implementors may have perceived the potential for profits, and this factored into how much energy they put into promoting them. That may have improved the language's fates markedly. But my point was about actual profits and how those correlate to programming language success (or don't correlate, as I argue).

It appears to me that C#, Java, and VB are just about the only languages who ever made money for their core implementors.

As for the rest of the argument per the original forum topic, I find the question too vague to really comment--is this "innovation" that is so sadly not taken up in the form of crazy type systems or new PL implementations? They are profoundly different questions in my opinion.

re: Sponsors

Perhaps you mean something different when you say "sponsors and investors". I interpret that phrase to include those who fund the PL implementors and core library implementors...and not the application programmers. It's a whole different and far more complex argument if you include everyone who ever programmed in the language and those who funded them.

In the early days, the users of a new language are often contributors to the language design, implementation, and libraries. E.g., early C and Unix started doing useful work very quickly within the labs (the story goes). Many of the first application writers helped to refine the language and the system. You can tell analogous true stories about Perl, Python, PHP, etc.

In each of these cases, and in all the subsequent cases you refer to in your reply, the languages did not in fact make money for either their core implementors or their sponsors or investors, neither early nor often (or even, later).

I disagree. I understand you to be saying something like this: "Look at C. Bell/AT&T never made money from C. Everyone knows that." Right?

It's not true though. In the early days, C and Unix got busy very quickly saving money within Bell Labs. They were doing needed work for other parts of the labs Faster, Cheaper, and Better than any available alternative. It's true that C (and Unix) later became huge without AT&T seeing any kind of direct return -- but it was the initial, immediate profitability of the early work that gave it room to mature. Similarly for the others.

There are a large number of successful languages that were offshoots from a large organization funding many different things, but the language itself wasn't profitable. And there are no examples of small companies making their bread and butter off of a language implementation of their own language.

I never claimed that languages that win big had to reap windfall profits for the original investors -- only that the early stages of development are (almost always) self-funding.

It is almost but not quite tautological that there is no big money to be made in languages. An interesting exception to the rules is XQuery. XQuery was not quickly able to pay its own way -- it needed patient, plodding investors over several years. Nowadays, there are at least three businesses (two stodgy, one that started up just a few years ago) that are making decent money from it (because quality implementations are very hard to do)).

Now however, I do agree that the sponsors and investors of the core implementors may have perceived the potential for profits, and this factored into how much energy they put into promoting them.

Exceptions like XQuery aside, generally sponsors / investors are not that patient and have a more realistic view of what returns they can expect. Javascript was mentioned as a widely adapted functional(-ish) language. Look at its Creation Story: Eich understood himself to have patient investors in a Scheme-based extension language; they quickly pulled the plug on that; they wanted to leverage Java hype; they allowed him take one rushed swipe at knocking out Javascript very quickly. Netscape arguably didn't ultimately manage itself well (and arguably, did) ... point is that Javascript won big because, very early in its life, it generated a return. Indeed - it killed off its own parent project which would have taken longer but which would have had a hard time not making a better language design for the problem.

It appears to me that C#, Java, and VB are just about the only languages who ever made money for their core implementors.

You are thinking "made money over the lifetime of the language" but I am talking about "paid its own way soon after invention and until it matured [and no longer needed sponsorship for further development]".

As for the rest of the argument per the original forum topic, [....]

Right, that. My point is:

Packaging language "innovations" -- regardless of what we consider to be an "innovation" -- is an almost incidental part of the problem. It's trivial and irrelevant. There is "packaging error" standing in the way of adoption. There is no supply shortage of these innovations. What is missing is demand.

You can't, generally speaking, generate demand by saying "isn't this a cool language feature?".

You can't, generally speaking, generate demand by saying "we did a study and it looks like you'll have up to 30% fewer bugs if you use this new language!" Nobody will really believe you (and rightly so) and, anyway, such a minor improvement isn't worth much.

You only (first approximation) really get demand for a new language feature if, very early on, that language is doing something, for someone, way, way faster, cheaper and better than any alternative ---- and there are many other people who want to do similar things faster, cheaper, and better. Basically, if your language innovation isn't being shown off in some commercial setting where it makes other business people jealous... it probably isn't going to win big anytime soon.

I take exception to that

And there are no examples of small companies making their bread and butter off of a language implementation of their own language.

But I work in one!

Practical programming

This is a very elitist point of view. You are looking at the peasants and asking them why they don't eat cake.

Practical programming has many constraints. Fancy language features might be awesome, but before most programmers can use them they first need to be maturely implemented in a non-toy compiler and supported on all the platforms required. You also have to justify why such features are worth the added burden of implementing them, learning how best to use them in existing codebases and making sure they don't needlessly overcomplicate the code and make it harder to maintain. Some language ideas are best left to academic papers.