
The Programming Language Conundrum - bibyte
http://evrl.com/programming/2019/03/28/the-language-conundrum.html
======
dahart
> A lot has been written about "hyperproductive teams". ... there’s one thing
> in common between all the stories I’ve heard and the successes experienced
> first hand: small teams

Personally, I'd go one step further. It's small teams that were together from
the start. Going through the initial setup of a project makes all the
difference. When people come later, they lack the intuition that comes with
being around when all the structural decisions were made. Early people make
tradeoffs and bake good and bad practices into the pipeline, later people are
told not to touch certain things because it's more complicated than it looks
or will break something else that doesn't seem explicitly connected.

I've been on both sides of this fence. Having started a company and sold it -
my partner and I were hyper productive, but while the small team that
inherited the code is extremely capable, it took years longer to feel
comfortable making big changes than it took to write.

Joining other people's projects and large codebases, on the other hand, has
always taken a long time for me to be productive in. Typically it takes a year
at a new company before I'm moderately useful.

Personally I don't think this has a ton to do with programming languages, even
though I feel much more productive in python and javascript than C++ myself,
even though I've been using C++ longer. I still suspect familiarity with the
early decisions is a greater factor in productivity than language.

~~~
tolien
> It's small teams that were together from the start. Going through the
> initial setup of a project makes all the difference. When people come later,
> they lack the intuition that comes with being around when all the structural
> decisions were made. Early people make tradeoffs and bake good and bad
> practices into the pipeline, later people are told not to touch certain
> things because it's more complicated than it looks or will break something
> else that doesn't seem explicitly connected.

I've also seen this happen and agree with your analysis that it's probably not
related to the programming language - it seems more like a problem with how
the thought process behind those decisions is (not) recorded.

Short of making every project (and the codebase it results in) live for a
short enough time to guarantee that nobody new will ever have to look at it,
we've got to collectively do a better job of being able to explain the "wtf
did you do that?!" aspect of development.

~~~
pishpash
A readme (in plain language) in every folder helps a lot. Either that or it's
replaying every commit from the start. Maybe tools can be made for this.

~~~
tolien
I don’t think it’s about tools as much as culture - whether it’s a readme, a
wiki or a chat log that’s not full of talk about the weather and scones (no,
really), people have to be suitably incentivised to work that way. Something
that isn’t a customer-deliverable (they aren’t going to directly care if you
don’t record the weird business process that led to you implementing feature X
the way you did; they don’t have a comparison which tells them that if it was
recorded, changes could’ve been quicker/cheaper/less risky) is at risk of
being cut as soon as there’s a hint of time pressure to get something out the
door.

It’s coincidental that doing things in less of a “let’s all get in a room and
talk about it for 3 hours” way should make keeping remote workers in the loop
easier too.

------
yogthos
I have the exact opposite experience going from working primarily with Java to
Clojure. I worked with the former for nearly a decade, and I haven't
contributed to a single library or project I used in that time. Every time I'd
see a bug or a feature I'd like to add, I'd check the source see thousands of
classes each with its own semantics and behaviors, and give up. The amount of
effort needed to familiarize yourself with a non-trivial Java codebase is
herculean.

Meanwhile, I've contributed to many Clojure libraries, and lots of people
contributed to the ones I maintain. I can open a Clojure project and figure
out what's going on much easier than with a Java one. The code tends to be
much more direct. It's primarily written using pure functions that you can
reason about independently. It's focused on the data, so I don't have to learn
hidden behaviors. And I have a live environment with the REPL where I can run
the code and see what it does immediately.

My team has been working with Clojure for nearly a decade now. We have many
applications in production that have been developed and maintained for many
years. We've hired many new devs during that time, and we've never had
problems onboarding.

A language being expressive and flexible does not preclude it from scaling to
large projects. And when the language is not expressive, you end up with huge
amounts of incidental code because you're forced to map your problem domain to
the language as opposed to the other way around.

I think that community practices for using the language are far more
important. Clojure community started discouraging heavy use of macros early
on, and a small set of common patterns tends to be used to solve problems, and
codebases across projects tend to have a similar style to them.

------
omaranto
Even if there is a scaling limit, you can still use SmallTalk or a Lisp for
small projects (and the scope of small projects in those languages is larger
than that of, say, small Java projects) and benefit. I imagine plenty of
unglamorous software projects are small enough in scope.

I am a mathematician, not a programmer, but even I have a Lisp story like
this. I'm working with a computer science professor at my university who has
in the past worked as a programmer both for private companies and for our
government. We're studying some combinatorial game played on graphs and wanted
experimental data of which player has a winning strategy on thousands of small
graphs.

To feel more certain of the computer results we decided to each write our own
implementation independently without looking at each other's code. He wrote
his in C and I wrote mine in Common Lisp. You can imagine the punchline since
it is similar to all of the Lisp stories out there: my program is about a
tenth of the number of lines of code, took much less time to write and runs
about twice as fast!

~~~
dukoid
How would you know the projects stay small? Also, if you have to work on small
and large projects, and one tool works for both, getting proficient in both
tools might just not add enough benefit...

~~~
omaranto
I certainly have no idea how to predict if a programming project will stay
small, but maybe people who do that kind of thing for a living have some idea?

Also, I'm skeptical about this scaling limit business, but if it's true, call
the first program a prototype or proof of concept and then rewrite in a
"scalable" language when necessary. "Plan to throw one away, you will anyway."

------
timomax
Odd languages attract above average programmers, if nothing else than because
they are engaged. Small teams are more productive than large teams, because
there are almost no communication problems. I wonder how much is due to this?

~~~
geophile
I came here to make the same point. The real test would be to take those same
Lisp or Smalltalk programmers, and have them work in Java. I’ll bet you see
the same increase in productivity. It’s the people, not the language.

~~~
mamcx
No, the language is part of the equation.

I have code, for work, in: FoxPro, Delphi, Python, VB, VB.NET, C#, F#, Obj-C,
Swift, Rust, Sql, Js.

I rewrite apps and codebases, and move them. I rewrite the same stuff many
times, and make my own pseudo-ORM is my main thing when learn new languages.

Absolutely I'm more productive in some Langs than others:

Amazing at:

\- Fox, Delphi, Python (#1), F#, Swift

Average, low:

\- VB, C#, Obj-C, Js

Barely move:

\- Rust (this is my last lang, and also doing a programming language that I
have sketch in python, swift, f#. The task hit against the hardest and weakest
parts of rust).

I look at C, C++ and my instinct tell me I will suck forever at them. Same
Haskell. Ocalm? I will fly. Lisp? Nope, that crazy stuff never click. Kdb+? I
don't know, maybe.

I don't buy the meme "the language not matter, is the people" because
languages are made FOR the people. And some stuff click on you or not.

That is the reason APL is a thing for some.

~~~
ken
Whenever I hear "it might work for you, or not", my ears perk up. Not
understanding when something works or not is a great question. It's something
to explore. It's not the endgame.

I briefly studied French in college, and to say it "didn't click" would be an
understatement. It was the worst grade I got in any class ever, by far. And
yet, even the dumbest French person is fluent from when they were just a kid.
It's probably not the case that French is simply impossible for some people to
learn. Something else is going on.

Couldn't it be that we simply haven't figured out a good way to teach
programming languages yet? Software is still generally "go read the reference
manual online and you're good", but most other mature fields have moved beyond
that. Boeing is in hot water this month in part because they essentially used
that as pilot training for the 737 MAX, and it's clear to everyone that this
is not an adequate way to learn a complex new technical tool.

Unlike you, I don't find Swift particularly productive (and I've written tens
of thousands of lines in it!) -- but maybe with the right training, I would.

~~~
duado
Learning a language as an adult is completely different from learning as a
kid. Your hypothetical “dumbest French person” would not have been able to
learn French as an adult, the same way that the most physically fit 100 year
old could not survive the falls down the stairs that 3 year olds do without
even crying.

~~~
dorfsmay
Correct. A different part of the brain is used when learning a language past a
certain age (I think 8 or 10 years old).

------
herodotus
> Create a language to solve your problem;

> Solve your problem.

When I worked on a complex framework in a small team, we used Objective-C. In
the early days of the project, we created some powerful utility methods like
map and reduce which we used extensively in the early stages. These methods
let us do things like traverse complex structures very compactly. Way better
than the more plodding while-loop (perhaps with a stack) way of doing it. But,
I found myself moving away from these later in the project in favour of more
verbose code because it took me too long to understand the map/reduce code if
I needed to revisit it. The longer code was, um, longer, but it was much
easier to understand what I (or my colleagues) had done when I came back to
this code. In my view, a bunch of very smart programmers can indeed be
"hyperproductive" using a language like Smalltalk, but this hyper-productivity
may not survive the longer term life of the project.

~~~
akvadrako
How is map difficult to understand? It’s the same semantics as a for loop with
input and output lists, but less boilerplate.

~~~
emsy
From my personal experience, most developers that discover list comprehension
etc. get excited about how much they can achieve with little code that they
try to keep everything as small as possible. They end up using short, non-
descriptive variable names and you need evaluate the code in your head to find
out what a variable/list contains. It's even worse with non-sequential
callbacks and closures.

~~~
dorfsmay
In Python I went back and forth:

I discovered list comprehension and was exited and used them a lot. Then I
went to multi level list comp. Then I realise I could never debug those so
went back to loops for anything needing more than a single level. Finally I
discovered Generator Expression which are basically like list comp, but lazy
(not evaluated) and since then I break my code in a series of generator
expression which I materialise at the end with a single list comprehension.
This way I keep my code readable, it's a lot cleaner then a bunch of loops,
and I also benefit of Python's special optimisation for list comprehension.

~~~
blt
I like writing generator loops with the yield statement for more complex
processing.

------
ken
I'm skeptical for the simple reason that this post never calls out any
specific feature of Lisp or Smalltalk which could cause this problem, and
other languages which apparently don't suffer from these problems have most of
the same features. It's almost as if unpopularity is the root cause.

Guy Steele famously said that with Java they "managed to drag a lot of [C++
programmers] about halfway to Lisp". I don't hear many complaints about Java
being too 'organic' or difficult to document or that it only works on 2-pizza
teams.

If you think that sufficiently powerful languages only work on small teams of
dedicated people, why draw the line at Lisp/Smalltalk? Why aren't the Ada
people going crazy about how loose and dynamic Java is, much less Python and
Ruby -- all of which apparently "breeze through the 100, 200, 500 developer
marks without much trouble"?

I remember reading about how Codd's relational databases struggled with
acceptance because it was believed at the time that 'tables' were too complex
for the average programmer, yet today that idea is laughable. People tend to
rise to the level of expectation.

~~~
mrfredward
>other languages which apparently don't suffer from these problems have most
of the same features

Well, one of the very first differences I think of between Lisp/smalltalk and
Java is dynamic vs static typing. In Java, you have to write extra boilerplate
code to satisfy the type system. This slows you down when you're writing code.
However, when you're figuring out someone else's code, static types can be a
big help. Often times, you can guess the right way to call a method based
solely off the signature, and if pass the wrong thing, your IDE can highlight
your mistake almost instantly.

So when you're working on your own freshly written code here and now, static
typing is usually a hindrance. When you're working on 3 year old undocumented
code written by someone you've never met, static typing is a key source of
information on how things work. The bigger the team/project, the more likely
it is you're working on code that's not familiar, so it would follow that
static typing helps scalability.

~~~
kortex
I've started using type hints with python and they are amazing, not just for
historic code, but improving my productivity in real time (especially in
conjunction with an IDE). I think what's great is when you use hints, you get
benefits in linting, but you can also get away from it when you need to. With
mandatory types, you are always having to work in the type system. Best of
both worlds. But not everyone is as excited about or as thoughough with them
as I am.

~~~
jimbo1qaz
I find type hinting to be very useful, but it has some gotchas (also present
in unhinted Python), where the type you get isn't the type you expect:

\- Int and float from numpy arrays are np.int/float32/64\. And
round(np.floatXX) returns a float, but round(float) returns an int in Python
3. \- ruamel.yaml loads CommentedMap and some custom scalar types.
CommentedMap is not a subclass of dict.

------
reikonomusha
The fact that dozens of companies have been built around millions of lines of
Common Lisp code at all levels of abstraction solving some of the most
complicated problems is a testament to the scalability of Lisp.

What has changed is that most software shops aren’t solving technical problems
anymore. Most places are engaged in the business of plumbing—connect this
database (whose problems are solved) to this dashboard (whose problems are
solved)—but many of us don’t want to admit it. It’s not glamorous and Silicon
Valley prefers to keep its death grip on titles like “Senior Solutions
Architect.” Plumbing doesn’t necessarily need expressive power of a
programming language, but I contend that problem-solving greatly benefits from
it.

~~~
kazinator
this hasn't really changed. Yesteryear it was Visual Basic, reviled by anyone
coming from a Computer Science background. Most if it was "connect to
database". Prior to that, 4GL's: dBase III derivatives, right through
Microsoft's (eventually) FoxPro. Before that COBOL. There has always been
"plumbing" for as long as computers have been "business machines".

~~~
reikonomusha
I think the proportions have shifted significantly. (Proportion of “problem
solving” to “plumbing”.) There’s at least a couple orders of magnitude more
software and services available to use and connect to today than there was 25
years ago.

~~~
antt
Plumbing is not what you read in your textbooks about.

It has always been the case that the majority of programmers are plumbers. As
a fraction of people I would be surprised if we do not have more people
working on blue skies problems today because all the tools are available for
free, as opposed to the 80s when a workstation with the software on it cost
30% of the developers yearly salary.

------
a-saleh
I would say there are several languages that straddle the line.

AFAIK there exist 50+ people teams that use i.e. ocaml (Jane street,
Facebook), haskell (gallois, Facebook, Google), erlang (whatsapp, pivotal)

I would say that beyond i.e. 10 developers you suddenly need to have
onboarding solved. You need to be able to teach your new hires. You need to
have community beyond your workgroup to ask questions. You need decent library
support.

I would say it is beyond 50 where your leads start to worry you didn't `go
with IBM` so to speak. You suddenly can't just hire an expert. And you can't
coast on the fact your programmers find the language familliar.

Like, I joined 4 people team working in clojure. It was fine. You mostly could
see "oh, this is where the macro magic starts, and here I need to grok
protocols first and here I need to grok transducers first". Then my manager
got nervous that he couldn't hire new people fast enough so we had to do a
python rewrite :-/

Different team, different project, 60+ people, python. You'd think, it is just
python. But you never know when there is a metaclass hiding behind an
inheritance chain. There are parts, where we might have single person
understand the code. Sometimes they left year ago.

------
cryptonector
I don't think the issue is that the language weaves with the mind (or the
reverse). Instead I think there's several issues at play, at least these, and
probably others: a) mindshare, b) dynamic type systems suck.

(b) alone may seem insufficient, since TFA mentions Python as a language that
scales, but I've never seen large Python systems -- lots of small Python
programs and libraries, yes, but monolythic multi-mloc Python applications?
no. When you get to that size, dynamic typing issues become time sinks.

As to mindshare, if the number of developers who know Lisp is small, you're
not going to get a lot of them. Mind you, you should be able to train them --
once you speak N>3 programming languages, getting to N+1 is not that
difficult. But it's a lot easier to hire C++/Java/whatever programmers. This
is a mindshare effect.

Also, if 1.5 FTEs allows you to build a successful company, then to scale
development to 100 FTEs you have to rewrite, well, that's still a success.
Many would like to have that problem. And nowadays we're getting good at
incremental rewrites as an industry -- witness the Rust effort.

I think the future lies with Rust. Rust is a very high-level programming
language, but it still lets you get down to the same low level as C. If you
sold Rust as a Haskell w/ linear types, no/minimal monads, no I/O monad, and a
C-ish syntax -basically, what it is-, I think TFA might run away saying "oh
no, another Smalltalk that won't scale".

At the very least I'd like to think and hear a lot more about the issue --
whether and why some programming languages do or do not scale teams -- before
accepting TFA's conclusion.

------
kstenerud
"These languages are very powerful, but they don’t scale. So even when you get
ten times the productivity, the mostly tribal complexity will not scale beyond
your “pizza-sized team” and therefore you now have a hard upper limit on your
total software development capacity."

Ultimately, the problem boils down to the languages giving too much freedom.
More conventional languages like Java can scale to a massive degree because
they standardize so many things, which means that you can now share components
which amplify your work. Lisp et al are cool toys and small team tools, but
you're not going to see any large scale db libraries and parsers and
concurrency libraries and web servers and cachers and HA systems that can
interoperate with each other without a ton of shoehorning.

When every foreign chunk of code requires a ton of ramp up time just to figure
out what it's doing and how you could even integrate it, or requires changing
your IDE and workflow in ways incompatible with what you have already, you
lose more than you gain.

Worse is better. Worse gives you interoperable, reusable, amplifiable
components, in a common framework everyone understands.

~~~
WalterBright
> the languages giving too much freedom

This is why the D programming language doesn't have macros, neither text nor
AST. It's been a controversial decision, and I've had trouble convincing
people of the reasons why. Others explain it as "Walter doesn't like macros."

The reason is that macros enable one to invent one's own language withing the
language, and that language is incomprehensible to others. It happens with
every language that supports macros and macro-like constructs. (It happens
with C++ "expression templates" and operator overloading.)

People swear up and down that they'd never use macros that way, they'd use
them responsibly, and the incomprehensible mess they create is indeed
responsible.

For a hilarious example, an engineer I know recounted a story at Big Corp
where there was an aged piece of software written in assembler. The programmer
for it had long since moved on. The code had some problems and needed
updating. Unfortunately, the programmer had invented his own language using
the macro system, and nobody wanted to touch it.

My engineer friend said he could do it, and had the code fixed in a couple
hours. Amazed, the manager asked how he'd figured out those macros. He replied
"I didn't. I assembled the code, ran it through a disassembler, converted that
back to source code, then fixed it."

~~~
dagss
No experience with D, but using Go a lot, and it is the same thing there with
lack of metaprogramming.

Turns out everyone uses reflection instead to get anything done.

Not sure how much of a success that is.

~~~
WalterBright
D fully embraces metaprogramming which is a very powerful part of D. But it
stops short of being able to redefined the language, which is what macros do.

~~~
snaky
Do you consider e.g. BER MetaOCaml approach as "being able to redefine the
language"?

~~~
WalterBright
I don't know enough about OCaml to have a non-gibberish reply.

------
marcosdumay
I am yet to see a team of 100 successfully working on the same problem. I've
seen large codebases that solve lots of different problems with 100's of
people working on it at the same time, but this isn't the same thing.

My point is, if you are on the second situation, you can very likely split
your people into different teams, facing different trade-offs and with a
formal (but not static) interface between their code. So if you can get a 10
people team with the productivity of a 100 people team, but unable to scale
further, well, you will face the same problem on the 100 people team, and can
apply the same kind of solution to both. The only difference is that you are
saving 90 people.

------
zmmmmm
I think there's a really important aspect to this that the software industry
needs to confront in order to mature.

To _some extent_ \- not completely, but at least partially, power and
unmaintainability are two sides of the same coin. That is, it is exactly the
same properties that allow your amazing macro to boil 15 dimensions of a
problem down into a single beautiful one line piece of code that also make it
an unacceptable liability that should never be allowed into a mature codebase
[1]. Because if the macro didn't exhibit that amazing sublte complex behavior
then it wouldn't be powerful. But exactly by doing that, it is now something
that nobody new can understand.

There is also a fraction of the software "power" equation for which it is a
win-win: more power equals less overall non-essential complexity in the system
and the burden of propagating the associated knowledge is lower than what is
saved.

However distinguishing the above two things is completely non-trivial and if
you can't actually do that well you need to fall back on the side of avoiding
overly powerful behaviors if you want to have an actual long term, large
scale, maintainable outcome.

[1] Obviously this is an overreaching statement. But to a first approximation
this is true and the exceptions by definition have to be rare.

~~~
goatlover
I wonder what the difference is between a DSL in Lisp/Smalltalk and a
framework or powerful library like React, Rails or Pandas as far as complexity
and learning curves go. Is it that the frameworks and libraries are typically
maintained outside the team, and if popular, are widely known?

~~~
Viliam1234
> Is it that the frameworks and libraries are typically maintained outside the
> team, and if popular, are widely known?

Pretty sure this is it. A framework developed in the company can be a horrible
thing; and avoiding it may be politically impossible, because someone
important has approved spending a ton of money on developing it.

------
KirinDave
The proposition that "custom development tooling doesn't scale" is very much
news to Microsoft, Google, Facebook, LinkedIn, etc.

All of them have custom programmable configuration stacks, meta languages for
their environments, and custom application harness instructions.

So why don't those count as counterexamples? It seems like a just-so story.

~~~
mwcampbell
Those companies are so high-profile, with so many people wanting to work for
them, that they can do what they want, and the new hires will keep coming.

But in an obscure company, especially one that's not very well funded, it may
make sense to use a blub language so the company can attract programmers that
it can afford. Of course, using a less powerful language will limit the
productivity of those programmers. But having two or three moderately
productive programmers is probably better than being dependent on one bipolar
[1] programmer.

[1]:
[http://www.marktarver.com/bipolar.html](http://www.marktarver.com/bipolar.html)

~~~
KirinDave
... My experience with those companies, and I've been employed by more than
one: the decisions to make those special sauce systems predate their fame in
every case.

So no, and I don't get why you're trying to now raft programming languages you
don't like to a medical diagnosis.

~~~
mwcampbell
Touché.

My reference for "bipolar" was an article written by someone who applied that
term to programmers writing in a family of languages he _does_ like. His
description might even apply to me. I've never done any serious Lisp hacking,
but I wrote large amounts of code in Python and Lua, which are closer to Lisp
than they are to, say, C. In truth, the second paragraph in my earlier comment
was me thinking out loud on why it might have been a mistake for me to use
those languages in the context where I did. Maybe it didn't belong in a reply
to your comment.

------
andyidsinga
> These languages are very powerful, but they don’t scale.

The problem, it seems to me is that software developers often think: "what
programming language do we really like && can continue to use for $long_time
over $scaling_of_business".

When this is the case, business management expectation problems emerge
regarding costs, maintenance and timing when the business scales by 10 or
100x. Early phase teams are lambasted for making poor decisions - and "adult
supervision" ( i hate that term ) is hired to "fix things".

Thing is, the early "poor decisions" may not have been poor decisions at all
relative to the business needs. However, since costs and retooling issues
weren't discussed and planned for - the early team look like a bunch of
fools/amateurs.

As software developers, we need to understand and communicate that the tools
can we use to accomplish the needs for the business at one stage are different
than those of a later high-scale stage. its OK, completely natural, and a
requirement if we want to keep our jobs and grow with the business.

analogy: If a specialty carpenter is designing and building high end furniture
with a set of well made brand-name niche tools and techniques they wouldn't
expect that those same tools would be used if sales take off and 10x or 100x
the number of units need to be produced. It would be understood that retooling
would be required, people with expertise in those tools be hire and that there
would be new costs involved. Also, the carpenter who starts the business with
small scale tools isn't lambasted for being an idiot for picking those tools
in the early phases. It would be quite odd to suggest that that person have
picked tools and hired people for 100x production when they were selling
single digit units a year.

~~~
duado
The question is what the intention was. A carpenter doing models for IKEA
would be expected to design for million-unit volumes from the start.

~~~
andyidsinga
different problems here - if the production and scale are already well known
and understood - there are, arguably only design choices to be made that fit
into the existing tooling.

"the new chair model must fit into these production constraints"

"the new software must be written to fit into this system - JVM based, web
interface ..."

------
drmeister
We are traveling down this road. We've implemented Clasp
([https://github.com/clasp-developers/clasp.git](https://github.com/clasp-
developers/clasp.git)) - an implementation of Common Lisp that interoperates
with C++ and uses llvm as the backend. On top of this, we built Cando
([https://github.com/drmeister/cando.git](https://github.com/drmeister/cando.git))
- a computational chemistry programming environment for designing large
molecules. The end of our story hasn't been written yet.

Clasp could be used for a lot of other things.

~~~
reikonomusha
To add to cutting-edge (& open source) scientific applications, Rigetti
Computing uses Common Lisp for their quantum optimizing compiler [1] and high-
speed quantum simulator [2].

[1] [https://github.com/rigetti/quilc](https://github.com/rigetti/quilc)

[2] [https://github.com/rigetti/qvm](https://github.com/rigetti/qvm)

------
PaulAJ
The poster makes a point about conservatism in large companies, but doesn't
explore this further. Its actually a more complicated matter than just
technical ignorance in managers. The real problem is that programming
languages are seen as a tactical matter for project managers ("just use the
best one for the job"), whereas they should be considered strategic.

* At the start of a project the PM is given a budget and a timescale which were probably driven by the question "whats the earliest you can't prove you won't be done by?" There will be no slack for developers to spend 6 months coming up to speed on a new programming language and paradigm.

* Nor can the PM afford the career risk of trying something new. If you do it the standard way and it doesn't work, the decision to do it the standard way was obviously not responsible and the search for blame can be pushed elsewhere. But if you pick something novel and it doesn't work, the blame for any failure will always focus on the novel element. So there is a strong institutional pressure to keep doing things the same way to avoid the blame for failure.

* Once a piece of software is finished it has to be maintained. Most software expenditure actually goes on this phase. If you use a new programming language then you are going to have to keep a bunch of programmers around who speak that language just for that project, even if there are no changes needed this year. That is expensive, so this is another disincentive for trying a new language.

* Every technical manager has seen enthusiastic young programmers bearing some new silver bullet (see Fred Brooks) which, the youngster says, will solve all the problems at a stroke. After you have seen half a dozen of these they all start to look the same. There is also concern about "CV engineering": getting the company to take on the risk and cost of training employees in trendy technologies which won't provide real benefit but which will make those employees more likely to find a higher paid job somewhere else.

If programming languages were considered as a strategic matter then a large
company could make a decision to invest in tooling, training and increased
project risk in order to adopt a new language which would make them more
productive in the long term. But until then change will be forced on the
industry by small companies who beat the averages.

------
BuckRogers
I enjoyed the build up throughout the article to his conclusion. While I can't
prove him wrong, a lot of very smart people came up with languages like Java
and C# to solve these problems (ramp up, maintainability, retention, and more)
as efficiently as possible. While I salute the author in his quest to be
proven wrong, objectively, everything is a trade-off. I don't believe in
better.

------
karmakaze
The real problem is that there's a missing step:

    
    
      1. Create a language to solve your problem
      2. Solve your problem
      3. Document the language
    

Presuming that the original creators made a reasonable language for the
problem at hand, who wouldn't want to use a powerful, well designed language
with good fitness of purpose?

Now imagine that you were brought onto a team using a widespread (not
homegrown) language you didn't know that was used for the company's main
application, but you have no access to documentation.

~~~
fiddlerwoaroof
I find that I almost never read documentation in languages like Common Lisp
and Clojure for two reasons:

1) documentation is often unmaintained and reflects the state of the library
at some point in time, but not the current API. But...

2) even when there is good documentation, it’s often easier to just take a
code example and then use the excellent jump to definition and other tooling
to understand how the example works than it is to read the definition: in
part, because there’s always a repl available in these languages and it’s much
easier and quicker to run mini-experiments on the language at the repl than it
is to read the documentation and translate it to code.

~~~
reikonomusha
I think Lisp’s “the source is the documentation” (with comments and doc
strings) is a huge boon. I usually figure out how something works faster and
more accurately than, say Ctrl+F’ing some Python Sphinx documentation.

~~~
flavio81
>I think Lisp’s “the source is the documentation” (with comments and doc
strings) is a huge boon.

True.

At first i thought "Damn, there is little documentation on those Lisp
libraries", but as the months passed, I understood that often code was very
readable, and the fact that documentation strings are integral to the language
is also a good thing.

------
untangle
> My theory, completely made up and untested, is that these powerful
> Lisp/Smalltalk systems weave code and brains together in a way that
> amplifies both. It’s very organic, very hard to document, and thus it
> becomes very hard to absorb new brains into the system. <

Here's a simpler and less mystical theory. These programming systems are
fundamentally image-based, and much of their leverage comes from the coder's
ability to leverage all aspects of the meta-system. However, the more the core
image is evolved the easier it is for a team to get out of sync. This is the
ultimate namespace clash.

A slew of other highly-productive languages share this feature, e.g., APL and
Forth.

------
adgasf
Are teams using these languages small because the language doesn't scale well
or because you don't actually need more developers?

------
mpweiher
> 1\. Create a language to solve your problem;

> 2\. Solve your problem.

But don't we do this in every language, at least if we're doing a good job?

I remember the final "exam" of my high school CS class. It was mostly an in-
class programming exercise in Pascal.

I was the only one to finish in less than the allotted time. The first one to
finish after me did so after the _second_ extension period.

I have to admit while I was obviously inordinately pleased with myself, I was
also baffled, because the other people in the class were certainly just as
smart as I was.

So what was the difference?

The problem we were given was to draw a bunch of boxes with character graphics
with contents and some overlap. Not really hard. Everybody else coded up each
box individually with straight code. One after the other. Each time having the
handle all the edge cases (literally).

I was the only one who first created a procedure (or set of procedures) for
box drawing, and then used those procedures to draw the boxes. And yes, that
is very much a simple "language" for solving the problem. Of course the
language set some pretty tight limits on how your "language" could look, which
is a bane for expression and a boon for understanding.

So I did "define the language, solve the problem in that language". In Pascal.
Classic bottom-up programming.

So I dispute that there is a _fundamental_ difference, though there definitely
is a significant difference in degree. The difference with high-power
languages is that they allow us to apply this much more broadly, whereas with
other languages you often run into technical limitations that prevent you from
really defining the right language.

With there not being a fundamental difference, I also don't buy that we have a
fundamental, unbridgeable divide/chasm/whatever, with these high-power
languages with their problems on one side and the "blub" languages with their
other problems on the other. Rather, let's explore that regions of the
language space and see if we can't narrow the gap.

~~~
mike_ivanov
"But don't we do this in every language, at least if we're doing a good job?"

There is a difference between expressing higher level abstractions _using_ a
language and actually _morphing_ your language in way that you can directly
express those abstractions in it.

The latter is often impossible, if not because of technical limitations, but
rather due to cultural barriers. If it was only once or twice when I worked in
a team where stepping off the official language syntax dogma was considered a
punishable crime. I've seen things as innocent as "from x import y" (in
Python) being discouraged, and even using the dict function instead of {}.

People don't generally feel happy about seeing unfamiliar things in what they
consider their comfort zone. I don't know what to do about it.

~~~
mpweiher
Boy is that ever the case! The lengths people will discuss spacing after
method declarations, while being completely ignorant of the architectural
issues that are rotting their code-base.

> comfort zone

Tentative essay title: _Can Programmers be Liberated from the Gentle Tyranny
of Call /Return?_

> actually morphing your language

Yes. And no. First let's have a look at what "morphing the language" means, by
way of natural language. When we use natural languages, we can mostly
adequately describe anything we want to using the mechanisms available.
Sometimes, we need a new vocabulary, sometimes a set of interlocking
vocabulary, i.e. _jargon_. I haven't really seen a case where we need to
tinker with the structure of the language, with the grammar.

When we add a function, set of functions, interlocking objects/methods etc. I
would say that we are also adding vocabulary. And that _should_ be sufficient.
The fact that it is not sufficient to me suggests that our fundamental
"grammar" (not grammar of the surface syntax) is insufficient, not that we
need to be able to make up grammar on the spot every time.

Of course making up grammar on the spot also solves the original problem, but
it does lead to all these follow-on problems. One being that making up grammar
on-the-spot is much more complex than just adding vocabulary, and so you are
likely to get it horribly wrong. The other being comprehensibility.

------
DFXLuna
The idea is pretty simple: concise languages ( like python, smalltalk etc.)
work well when you can get away with being concise. Verbose languages ( like
the C family ) work well when you can't. It only takes a couple of tries
writing a project that favors verbosity in a concise language before this
becomes apparent.

~~~
nine_k
Languages like С allow you to control more (low-level) aspects of a program
than languages like Ruby. Ruby is only concise because it handles tons of
things for you, the way it sees fit.

You can make C++ quite concise, or quite verbose, depending on the level of
detail you can hide under layers of abstractions.

It's much like the framework vs set of libraries: a framework allows you to
write very little and produce a lot when all you're doing is wiring together
existing pieces and write business logic code it the slots provided for that.
Similarly Ruby allows you to write much lass than C if all you're doing is
wiring together hashtables of hastables of hashtables, and rely on garbage
collection.

------
jcelerier
> So why aren’t we all using either of these two languages?

because $bigcorp's dreams with languages such as Java was not to be incredibly
productive, but to be able to fire a whole team, hire replacements, and have
them be more-or-less productive on day 1. Can't do that if every project lives
in its own DSL.

~~~
ken
Even in a lower-level language, is it possible to be productive on day 1?
Instead of learning an explicit DSL, you're learning an implicit one spread
across 10 or 100 times as much code.

Imagine if regexes didn't exist, and you showed up at a new company and they
had hundreds of lines of Java for every little string matching function. Would
anyone find that more productive? Even if regexes were never used outside of
that one project, I think they'd be a huge win.

Especially at a bigco. My experience is you spend a while just getting all
your accounts set up. Half the time, I haven't even known the programming
language they used, so I spend weeks/months ramping up on that, even though
it's not domain-specific. Spending a couple days learning a new DSL is just
rounding error.

~~~
jcelerier
I'm not saying that this idea is grounded in reality :)

------
StefanHoutzager
I put a reaction on the site of the writer of the blog, but it looks like he
removed it. So I'll repeat here. The text misses structure, clearness and the
writer makes the same assumpion as Paul Graham, namely that a programmer
thinks in the programming language he uses. To start with the last: "to write
a good program, we need to think above the code level. Programmers spend a lot
of time thinking about how to code, and many coding methods have been
proposed: test-driven development, agile programming, and so on. But if the
only sorting algorithm a programmer knows is bubble sort, no such method will
produce code that sorts in O(n log n) time. Nor will it turn an overly complex
conception of how a program should work into simple, easy to maintain code. We
need to understand our programming task at a higher level before we start
writing code. [..] There are two things I specify about programs: what they do
and how they do it. Often, the hard part of writing a piece of code is
figuring out what it should do. Once we understand that, coding is easy."
(Leslie Lamport, [https://archive.li/2zZKy](https://archive.li/2zZKy)).
Sentences in de Groot's blog like "these powerful Lisp/Smalltalk systems weave
code and brains together in a way that amplifies both." are incomprehensible.
The question at the end of the blog looks rhetorical to me "I think I’ll end
while hoping that someone out there on planet Earth reads this and proves me
wrong :)". It is not clear what should be proved wrong, I suspect the writer
is satisfied with his musings.

------
externalreality
> A lot has been written about "hyperproductive teams". ... there’s one thing
> in common between all the stories I’ve heard and the successes experienced
> first hand: small teams

Funny because I don't think its small teams or a particular programming
language that leads to great productivity. You don't have to look very far or
far back to see teams, of various sizes, pulling off some amazing stuff with
assembler and C. The key to productivity is a lot simpler, and independent of
software development. Its a sense of responsibility, interest, and dedication.

In a small team that is using small talk the responsibility might come from
being on a small team with a lot of lifting to do, the interest might come
from having fun using a language that you like (regardless of the language),
and the dedication might come from the promise of getting in early on a
promising venture - hence the small team. All of these things add up to hyper-
production.

If you can establish those three things, somehow, with a large team I don't
see why hyper-production can't be achieved. Unfortunately modern project
management for large teams seems to rely heavily on techniques that rob
developers of all three qualities mentioned above in the name of so called
"agile" and in pursuit of some fictitious software assembly line.

------
pmattos
I agree with the OP. This has been called the Lisp Curse elsewhere. Over time,
your codebase becomes so high-level, full of advanced, domain-centric
abstractions that basically alienates everyone else from effectively working
on the project.

If you have a small, stable team that such issue might be relatively easy to
overcome. But with bigger teams, with higher turnover, than it might totally
cancel out any technical advantage gained from using such non-mainstream
programming languages.

------
overgard
I think what really makes those languages/teams productive is iteration time
being low. Part of that is a natural consequence of small teams and lack of
legacy code but certain languages definitely encourage it more than others. If
you have fast iteration times you can really quickly figure out a system by
experimenting, or work through bad ideas on the way to good ones.

For whatever reason software developers always seem to undervalue fast
iteration times, and the less productive languages always seem to make
iterating quickly harder, whether it’s C++s ghastly compilation times and lack
of an ABI making it hard to integrate libraries, or Java’s interdependent
class based nature causing excessive mocking and/or lots of generally
unrelated state being required to have a working object to test with. In
contrast smalltalk lets you just highlight a chunk of code and run it, and the
lack of separation between runtime and ide generally means you have enough of
the system live for things to work. I think where smalltalk doesn’t scale is
it can’t easily take advantage of things invented outside of it because it’s
so integrated and practically its own OS

------
fiddlerwoaroof
I’m not sure I buy this: I recently had to write a bit of ruby (an omniauth
strategy for my company’s OAuth2 server) and the code I encountered there (as
well as in the various rails projects I’ve worked on) may as well have been
written in macro-heavy lisp: in fact, lisp or smalltalk would be preferable
because they would have good source navigation tools for the macros, such as a
stepping macro-expander.

~~~
goatlover
Ruby supports a lot of metaprogramming, and some libraries and frameworks take
advantage of that. It's not the best counter example to Lisp/Smalltalk.

~~~
fiddlerwoaroof
My point is that a fairly popular platform that large teams use has nearly as
much metaprogramming in its widely used libraries as any Lisp or Smalltalk
codebase I’ve seen. So, I don’t think that the tendency of Lisp programs to
evolve DSLs is incompatible with large teams.

------
gumby
That's a very good insight here on large/small teams.

Although I typically hate discussions of "programming languages are like human
languages" I think it's the key here. All the team members need to share _and
be comfortable in_ not just a spoken language, but the teams local jargon, and
the programming language in use (including your team-specific conventions,
which form a kind of jargon too). So teams in these esoteric languages (and I
say this as a Lisp hacker myself) tend to be by definition small, have a lot
of cultural overlap, and can be hyper-effective. And small teams _can be_
hyper productive/effective because of the lack of coordination overhead and
because it's easier to have a high 1st derivative from a small starting point
(in other words: no large team can beat a small team in efficacy/person, but
small teams can't do everything).

That only answers half the problem; the other is: well if small team X can
beat small team Y in significant part because of the choice of tools, why
don't bigger teams use the same tools?

There's no easy answer. One is power: Lisp and C++ have too many degrees of
freedom so it's easier to get in to trouble with languages with fewer "guard
rails". This was an explicit design criterion for Go BTW: new grads are coming
here and screwing up, so let's make it hard for them to make the most
common/dangerous mistakes.

Second in the case of Lisp: it wasn't considered a deployment language as many
of the things that made is powerful (e.g. GC, lambda, dispatch, dynamic
polymorphism) were considered too expensive at a time when C and smaller
machines were taking off. Now many of those features are considered mainstream
in other languages, while the Lisp community itself therefore attracted people
who were more power users.

C++ had a driver (Windows) and an impetus (like Go's: C gets you into a lot of
trouble) but even then people looked for easier / safer languages (e.g. Java,
an explicit reaction to ++)

------
perlgeek
> I can recite many of such stories; of people keeping up with their ten
> person team by coding whatever the team did during the day in 2-3 hours at
> night using Squeak Smalltalk; about an old Lisp hacker working in a research
> setup with mostly Java colleagues and always estimating to need 10% of the
> time (and then actually making the estimate). So why aren’t we all using
> either of these two languages?

Maybe it isn't about the language, primarily, but about the team? Maybe those
super productive teams would have been successful with any language that gave
them enough freedom?

That would also explain why you can't switch your 20 Java developers to
Smalltalk, and have them perform miracles of software engineering.

------
mises
Maybe this is part of the benefit of the whole micro-service trend? I've
largely dismissed the idea until now as impractical in many cases, but this
seems like a case where a team of between three and six developers could work
in something like lisp (that may not scale well), expose an api, and
communicate with other parts.

It seems like we really need cross-language oop for this reason. MS COM might
be an example. I was reading something I clicked on yesterday when doing some
reading about reference counting, and someone commented that things like MS
Office (COM based) needed such things: something could be initialized in one
language, passed to another, and deinitialized in a third.

~~~
danielparks
> Hmm, maybe this is part of the benefit of the whole micro-service trend?

I think micro-services can actually make this worse.

The issue is that the early coders write macros and other tooling that makes
it harder for future coders to understand. In other words, they develop their
own service-specific language.

With one big service, you would expect a somewhat consistent set of practices.
So, one language for the entire service.

With micro-services you can have a different language for each service. Worse,
each language might be only slightly different.

If you end up with a consistent language across all of your micro-services,
then you’re back to the original problem.

(I’ve experienced this effect first-hand. If I’m not disciplined I’ll do a
bunch of meta programming that makes me _way_ more productive, but makes it
much harder for another programmer to understand.)

------
galaxyLogic
One downside of Lisp and Smalltalk for large projects may be that there is no
official mechanism for declaring types and interfaces. Even if you can adopt
your own conventions for implying the types they are just your convention and
other programmers might have difficulty grokking and trusting them.

Hyper-productive languages may be hyper-productive just because they use
dynamic typing and static types may be better for creating a large piece of
software by many programmers evolving over years hopefully decades.

~~~
lispm
Ever heard of CLOS, the Common Lisp Object System? It has 'classes', 'generic
functions' with 'methods' which support multiple dispatch over classes, etc.
It was defined in the late 80s and integrating it into Common Lisp made it the
first standardized OO language.

    
    
       (defclass person ()
         ((name        :type string)
          (age         :type (integer 0 150))
          (exployed-by :type company)))
    
       (defmethod rename-person ((p person)
                                 (old-name string)
                                 (new-name string))
        ...)
    
       (rename-person some-person "Jim" "James")

~~~
galaxyLogic
I've heard of it but not used. Being able to say: "(name :type string)" looks
great.

Does it mean the system gives me an error if a method is called with a number
where a string was declared to be the argument type?

~~~
lispm
At runtime every CLOS implementation will do that. Note that it allows for
more than one parameter to be specialized. In the example FOO is using
multiple dispatch with two parameters P and S. When we call FOO with arguments
for which no method exists we get:

    
    
      CL-USER 22 > (defclass person ()
                     ((name        :type string)
                      (age         :type (integer 0 150))
                      (exployed-by :type company)))
      #<STANDARD-CLASS PERSON 4210214F63>
    
      CL-USER 23 > (defmethod foo ((p person) (s string))
                     (list p s))
      #<STANDARD-METHOD FOO NIL (PERSON STRING) 402025C653>
    
      CL-USER 24 > (foo (make-instance 'person) 3)
    
      Error: No applicable methods for #<STANDARD-GENERIC-FUNCTION FOO 4060000B5C> with args (#<PERSON 402025F1DB> 3)
        1 (continue) Call #<STANDARD-GENERIC-FUNCTION FOO 4060000B5C> again
        2 (abort) Return to top loop level 0.
    
      Type :b for backtrace or :c <option number> to proceed.
      Type :bug-form "<subject>" for a bug report template or :? for other options.
    
      CL-USER 25 : 1 >

~~~
flavio81
Note to galaxylogic: When lispm wrote:

    
    
         (defmethod foo ((p person) (s string))
                         (list p s))
    

He was implicitly defining a "generic function" "foo" of two arguments.

Defmethod was defining an implementation of the generic function foo for
arguments person with string.

One could later put something like:

    
    
         (defmethod foo ((p person) (p person))
                         (send-greeting p p))
    

And thus define a "foo" that works on two persons, etc.

CLOS allows specializing not just on classes, but also on specific instances,
so some method applies only for a specific instance. For example a "foo" that
applies only to a particular "important" person.

------
zvrba
I don't buy that the "privilege" of

> 1\. Create a language to solve your problem; > 2\. Solve your problem.

belongs mainly to Lisp and Smalltalk. Each time you define a method or a class
(C#, Java, C++), you're extending and defining your "language".

I'm the leader of a 2.5-developer startup, we use C++, Java and C# for
different purposes, and I have not once thought "shit, we'd be so much more
productive if we used XXX instead of C# or Java" (C++ being the exception).
Because the real problems are around the business domain. Understanding
customer needs, wrapping our heads around Azure AD, etc, etc, etc.

The programming language has ZILCH to do with our challenges and I do not feel
hampered by PL during refactoring either -- thanks to static types.

I have some regrets, and these go against frameworks we decided to use
(EFCore, i.e., ORM, being the biggest regret of mine).

Programming language? Almost not a factor. I'm happy with all of the 3 we use,
though I'm least productive in C++ due to the amount of ceremony needed --
header/implementation files, linkage, fixing preprocessor mess by variations
of PIMPL (looking at you windows.h), slow compilation, etc, etc, etc.

If anything is indispensable for our productivity, it's a good ide and
becoming comfortable with its capabilities.

~~~
minsight
When you have a good language, you don't need a good IDE.

~~~
Koshkin
This is like saying that if you have sharp nails you do not need a hammer.
(IDEs can be, and are, extremely helpful; even simple text editors like _nano_
or _SciTE_ try to include some of the features normally found in an IDE.)

------
4thaccount
I think the small team aspect is far more important than anything else. With
two developers in a startup, you can split up key components and have quick
informal talks concerning design choices. In a real company, huge amounts of
time are wasted on all-staff meetings, team meetings, 1:1 meetings, management
fads, mandatory compliance trainings that come up quarterly and take hours,
and the sheer human problem of coordinating that many people. Big companies
have huge waste stemming from many different areas. For example, at a large
company they have people in charge of requirements that have no understanding
of the domain or how to write software. It's like the telephone game you get
as a kid where the message completely changes by the time it gets around the
circle. Of course you could have your devs do that job, but most companies
simply aren't that logical. I bet Paul Graham and another competent developer
could use a language that is not considered to be very productive (Ex: C++)
and still swim circles past a large IBM team that is being held down by it's
own weight.

~~~
mwcampbell
> mandatory compliance trainings that come up quarterly and take hours

Compliance has a bad name because it's bureaucratic. But in software,
compliance can cover important things like privacy, security,
internationalization, and accessibility. Getting these things right is a moral
imperative in many cases. For this reason, the rise of move-fast-and-break-
things startups, with their developers unfettered by bureaucracy, worries me.

~~~
4thaccount
I'll agree that there is likely some value (usually CYA for the company) and
some real value too. However, those things still take up significant time that
the two-person startup doesn't have to worry about and that is just one class
of time wasters for big companies. It's always something: A big day-long
network outage, firedrills, performance reviews, management shakeups, water
cooler gossip, sending emails, reading emails, sudden surprise requests from
executives, having to have IT install something as they took away admin
rights, preparing for audits and disaster recovery...etc. I bet a startup
could easily avoid 30% of the work which just comes with having 100-1000
people in an organization.

------
upofadown
The root issue is extensibility. The same sort of arguments come up with the
simplest extensible language: Forth. There are whole categories of embedded
applications where Forth can cut the development time down to a fraction of
what it would take to do it in C. Once that programmer leaves it takes a long
time for someone else to come up to speed to do the sort of simple
modifications that such applications tend to require.

... and where do you get a programmer that can do anything effective with an
extensible language anyway? Such people tend to be very good programmers in
general and are rare and expensive.

------
sonnyblarney
"(and do not forget: they are that powerful)"

Are they? Because small teams are naturally much more productive, I thought
that was going to be the 'aha' of the article.

~~~
_emacsomancer_
Yeah, I was expecting something along the lines of the old saw "what a team of
two programmers can do in two weeks, a team of six programmers can do in three
months".

------
fredsted
Could it be that these languages haven't evolved all of the tooling and
ecosystems other languages have? You don't spend time setting up stuff. With
web dev, you constantly spend time switching between various tools to just
even build the damn thing/app.

None of it is _needed_ , per se - for years everybody made web sites without
it - but we've all convinced each other that it's just what you do.

Maybe Smalltalk doesn't have these conventions (yet)?

------
carapace
> It’s very organic, very hard to document, and thus it becomes very hard to
> absorb new brains into the system.

I think they way out is [something like] Alan Kay's "active documents". If you
really need large teams (rather than communicating constellations of small
teams, say) then your software has to be structured to be communicable.
(Beyond Knuth's "literate programming" even, I think.)

------
dqpb
Sounds like language oriented programming:
[https://resources.jetbrains.com/storage/products/mps/docs/La...](https://resources.jetbrains.com/storage/products/mps/docs/Language_Oriented_Programming.pdf)

------
amelius
> Create a language to solve your problem;

> Solve your problem.

But a typical problem consists of multiple sub-problems. Are you going to
create a new language for each of them?

------
tmaly
I think it really comes down to the availability of training material.

Look at the amount of material for Python compared to say SmallTalk

------
dustingetz
you’re given a $10M budget to solve a problem so you write it in Lisp and keep
all the money.

Break this absurdity in any number of ways and see. Tech, business, people
etc.

------
eruci
There is more than one way to do it. Or, only one: Perl.

